From 790485bc888a6244ddb0696da4d6c595d1cecf6e Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 27 Jun 2023 16:58:20 +0530 Subject: [PATCH 001/864] feat: support for uploading artifact to release --- .github/workflows/tauri-build.yml | 109 +++++++++++++++++++----------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index fb4c73c9..fb4b55ba 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -1,57 +1,88 @@ -name: publish -on: - push: - tags: - - 'v*' - workflow_dispatch: +name: 'publish' + +on: pull_request jobs: - release: + create-release: + permissions: + contents: write + runs-on: ubuntu-20.04 + outputs: + release_id: ${{ steps.create-release.outputs.result }} + + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: get version + run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + - name: create release + id: create-release + uses: actions/github-script@v6 + with: + script: | + const { data } = await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: `app-v${process.env.PACKAGE_VERSION}`, + name: `Desktop App v${process.env.PACKAGE_VERSION}`, + body: 'Take a look at the assets to download and install this app.', + draft: true, + prerelease: false + }) + return data.id + + build-tauri: + needs: create-release permissions: contents: write strategy: fail-fast: false matrix: platform: [macos-latest, ubuntu-20.04, windows-latest] - runs-on: ${{ matrix.platform }} + runs-on: ${{ matrix.platform }} steps: - - name: Checkout repository - uses: actions/checkout@v3 - - - name: Install dependencies (ubuntu only) + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + - name: install dependencies (ubuntu only) if: matrix.platform == 'ubuntu-20.04' - # You can remove libayatana-appindicator3-dev if you don't use the system tray feature. run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - - - name: Rust setup - uses: dtolnay/rust-toolchain@stable - - - name: Rust cache - uses: swatinem/rust-cache@v2 - with: - workspaces: './src-tauri -> target' - - - name: Sync node version and setup cache - uses: actions/setup-node@v3 + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + - name: install frontend dependencies + run: npm install # change this to npm or pnpm depending on which one you use + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - node-version: 'lts/*' - cache: 'npm' # Set this to npm, yarn or pnpm. + releaseId: ${{ needs.create-release.outputs.release_id }} - - name: Install frontend dependencies - # If you don't have `beforeBuildCommand` configured you may want to build your frontend here too. - run: npm install # Change this to npm, yarn or pnpm. - - - name: Build the app - uses: tauri-apps/tauri-action@v0 + publish-release: + permissions: + contents: write + runs-on: ubuntu-20.04 + needs: [create-release, build-tauri] + steps: + - name: publish release + id: publish-release + uses: actions/github-script@v6 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + release_id: ${{ needs.create-release.outputs.release_id }} with: - tagName: ${{ github.ref_name }} # This only works if your workflow triggers on new tags. - releaseName: 'App Name v__VERSION__' # tauri-action replaces \_\_VERSION\_\_ with the app version. - releaseBody: 'See the assets to download and install this version.' - releaseDraft: true - prerelease: false + script: | + github.rest.repos.updateRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: process.env.release_id, + draft: false, + prerelease: false + }) From 219fa9f7835bbd894ff4a4e5418dfb7a911ac3b4 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 27 Jun 2023 18:35:00 +0530 Subject: [PATCH 002/864] feat: adding support for mac build --- src-tauri/tauri.macos.conf.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src-tauri/tauri.macos.conf.json diff --git a/src-tauri/tauri.macos.conf.json b/src-tauri/tauri.macos.conf.json new file mode 100644 index 00000000..e22a206a --- /dev/null +++ b/src-tauri/tauri.macos.conf.json @@ -0,0 +1,13 @@ +{ + "build": { + "macOS": { + "target": [ + "universal" + ], + "universalBinary": [ + "x86_64", + "arm64" + ] + } + } +} From 45b708ec6dac95e2d2d1fdebc948de196bc31883 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 27 Jun 2023 21:42:29 +0530 Subject: [PATCH 003/864] feat: adding support for mac arch64 --- .github/workflows/tauri-build-mac-arm.yml | 89 +++++++++++++++++++++++ src-tauri/tauri.macos.conf.json | 13 ---- 2 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/tauri-build-mac-arm.yml delete mode 100644 src-tauri/tauri.macos.conf.json diff --git a/.github/workflows/tauri-build-mac-arm.yml b/.github/workflows/tauri-build-mac-arm.yml new file mode 100644 index 00000000..b27ccad4 --- /dev/null +++ b/.github/workflows/tauri-build-mac-arm.yml @@ -0,0 +1,89 @@ +name: 'publish' + +on: pull_request + +jobs: + create-release: + permissions: + contents: write + runs-on: ubuntu-20.04 + outputs: + release_id: ${{ steps.create-release.outputs.result }} + + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: get version + run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + - name: create release + id: create-release + uses: actions/github-script@v6 + with: + script: | + const { data } = await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: `app-v${process.env.PACKAGE_VERSION}`, + name: `Desktop App v${process.env.PACKAGE_VERSION}`, + body: 'Take a look at the assets to download and install this app.', + draft: true, + prerelease: false + }) + return data.id + + build-tauri: + needs: create-release + permissions: + contents: write + strategy: + fail-fast: false + matrix: + platform: [macos-latest] + + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + - name: install dependencies (ubuntu only) + if: matrix.platform == 'ubuntu-20.04' + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + - name: install frontend dependencies + run: npm install # change this to npm or pnpm depending on which one you use + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + releaseId: ${{ needs.create-release.outputs.release_id }} + args: --target aarch64-apple-darwin + + publish-release: + permissions: + contents: write + runs-on: ubuntu-20.04 + needs: [create-release, build-tauri] + + steps: + - name: publish release + id: publish-release + uses: actions/github-script@v6 + env: + release_id: ${{ needs.create-release.outputs.release_id }} + with: + script: | + github.rest.repos.updateRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: process.env.release_id, + draft: false, + prerelease: false + }) diff --git a/src-tauri/tauri.macos.conf.json b/src-tauri/tauri.macos.conf.json deleted file mode 100644 index e22a206a..00000000 --- a/src-tauri/tauri.macos.conf.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "build": { - "macOS": { - "target": [ - "universal" - ], - "universalBinary": [ - "x86_64", - "arm64" - ] - } - } -} From db3bb35edf7c89cbef189bae8b03c8a39a1715ae Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 27 Jun 2023 21:48:58 +0530 Subject: [PATCH 004/864] fix: setting up build target on amd64 mac to arrch64 --- .github/workflows/tauri-build-mac-arm.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/tauri-build-mac-arm.yml b/.github/workflows/tauri-build-mac-arm.yml index b27ccad4..db6fa96e 100644 --- a/.github/workflows/tauri-build-mac-arm.yml +++ b/.github/workflows/tauri-build-mac-arm.yml @@ -52,11 +52,7 @@ jobs: node-version: lts/* - name: install Rust stable uses: dtolnay/rust-toolchain@stable - - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-20.04' - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + run: rustup target add aarch64-apple-darwin - name: install frontend dependencies run: npm install # change this to npm or pnpm depending on which one you use - uses: tauri-apps/tauri-action@v0 From 5a47946179bed7d6611c9c6709431b85aa09be7f Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 27 Jun 2023 21:57:13 +0530 Subject: [PATCH 005/864] feat: added support for building windows linux and mac build using github actions --- .github/workflows/tauri-build-mac-arm.yml | 85 ----------------------- .github/workflows/tauri-build.yml | 21 +++++- 2 files changed, 18 insertions(+), 88 deletions(-) delete mode 100644 .github/workflows/tauri-build-mac-arm.yml diff --git a/.github/workflows/tauri-build-mac-arm.yml b/.github/workflows/tauri-build-mac-arm.yml deleted file mode 100644 index db6fa96e..00000000 --- a/.github/workflows/tauri-build-mac-arm.yml +++ /dev/null @@ -1,85 +0,0 @@ -name: 'publish' - -on: pull_request - -jobs: - create-release: - permissions: - contents: write - runs-on: ubuntu-20.04 - outputs: - release_id: ${{ steps.create-release.outputs.result }} - - steps: - - uses: actions/checkout@v3 - - name: setup node - uses: actions/setup-node@v3 - with: - node-version: lts/* - - name: get version - run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV - - name: create release - id: create-release - uses: actions/github-script@v6 - with: - script: | - const { data } = await github.rest.repos.createRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: `app-v${process.env.PACKAGE_VERSION}`, - name: `Desktop App v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install this app.', - draft: true, - prerelease: false - }) - return data.id - - build-tauri: - needs: create-release - permissions: - contents: write - strategy: - fail-fast: false - matrix: - platform: [macos-latest] - - runs-on: ${{ matrix.platform }} - steps: - - uses: actions/checkout@v3 - - name: setup node - uses: actions/setup-node@v3 - with: - node-version: lts/* - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - run: rustup target add aarch64-apple-darwin - - name: install frontend dependencies - run: npm install # change this to npm or pnpm depending on which one you use - - uses: tauri-apps/tauri-action@v0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - releaseId: ${{ needs.create-release.outputs.release_id }} - args: --target aarch64-apple-darwin - - publish-release: - permissions: - contents: write - runs-on: ubuntu-20.04 - needs: [create-release, build-tauri] - - steps: - - name: publish release - id: publish-release - uses: actions/github-script@v6 - env: - release_id: ${{ needs.create-release.outputs.release_id }} - with: - script: | - github.rest.repos.updateRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - release_id: process.env.release_id, - draft: false, - prerelease: false - }) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index fb4b55ba..d5924b61 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -41,7 +41,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [macos-latest, ubuntu-20.04, windows-latest] + platform: [ macos-latest, ubuntu-20.04, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -65,11 +65,26 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} + - name: setup env for mac arm (Mac only) + if: matrix.platform == 'macos-latest' + run: | + rustup target add aarch64-apple-darwin + npm install + - name: build for mac arm (Mac only) + if: matrix.platform == 'macos-latest' + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + releaseId: ${{ needs.create-release.outputs.release_id }} + args: --target aarch64-apple-darwin + + publish-release: permissions: contents: write runs-on: ubuntu-20.04 - needs: [create-release, build-tauri] + needs: [ create-release, build-tauri ] steps: - name: publish release @@ -83,6 +98,6 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, release_id: process.env.release_id, - draft: false, + draft: true, prerelease: false }) From d207a656a717342168e9b4551482492762e7e95c Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 28 Jun 2023 18:30:13 +0530 Subject: [PATCH 006/864] feat: script to download nodejs feat: intial code to download node based on operating system and architecture chore: sonar lint fix fix: sonar security for unzip chore: fix for sonar code smell --- package-lock.json | 279 +++++++++++++++++++++++++++++++++++++- package.json | 7 +- src-build/downloadNode.js | 247 +++++++++++++++++++++++++++++++++ 3 files changed, 529 insertions(+), 4 deletions(-) create mode 100644 src-build/downloadNode.js diff --git a/package-lock.json b/package-lock.json index b673b91c..9df0ec03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,17 @@ { "name": "phoenix-code-ide", - "version": "3.0.2", + "version": "5.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.0.2", + "version": "5.0.0", "devDependencies": { - "@tauri-apps/cli": "1.4.0" + "@tauri-apps/cli": "1.4.0", + "adm-zip": "0.5.10", + "fs-extra": "11.1.1", + "tar": "6.1.15" } }, "node_modules/@tauri-apps/cli": { @@ -198,6 +201,158 @@ "engines": { "node": ">= 10" } + }, + "node_modules/adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } }, "dependencies": { @@ -288,6 +443,124 @@ "integrity": "sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==", "dev": true, "optional": true + }, + "adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } } diff --git a/package.json b/package.json index 0cc8d0c3..076ed738 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,11 @@ "serve": "tauri dev" }, "devDependencies": { - "@tauri-apps/cli": "1.4.0" + "@tauri-apps/cli": "1.4.0", + "tar": "6.1.15", + "adm-zip": "0.5.10", + "fs-extra": "11.1.1" + }, + "dependencies": { } } diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js new file mode 100644 index 00000000..ca8c0fc7 --- /dev/null +++ b/src-build/downloadNode.js @@ -0,0 +1,247 @@ +import * as https from "https"; +import * as fs from "fs"; +import tar from "tar"; +import * as path from "path"; +import AdmZip from 'adm-zip'; +import {fileURLToPath} from 'url'; +import {dirname} from 'path'; +import * as fsExtra from "fs-extra"; + + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const LTS_URL_PREFIX = 'https://nodejs.org/dist/latest-v18.x/'; + +/** + Fetches the latest Node.js version by making a request to a specified URL. + @returns {Promise} A promise that resolves with the latest Node.js version string on success, + or rejects with an error if the latest version cannot be found. + */ +async function fetchLatestNodeVersion() { + return new Promise((resolve, reject) => { + https.get(LTS_URL_PREFIX, (res) => { + let data = ''; + + res.on('data', (chunk) => { + data += chunk; + }); + + res.on('end', () => { + + const versionMatch = /node-v(\d+\.\d+\.\d+)/.exec(data); + if (versionMatch) { + resolve(versionMatch[1]); + } else { + reject(new Error('Could not find latest Node.js version')); + } + }); + }).on('error', reject); + }); +} + +/** + * Downloads a Node.js binary file from a specified version, platform, and architecture. + * @param {string} version - The version of Node.js to download (e.g., "14.17.0"). + * @param {string} platform - The platform for which to download the binary (e.g., "win","linux","darwin"). + * @param {string} arch - The architecture for which to download the binary (e.g., "x64","arm64"). + * @returns {Promise} - A Promise that resolves to the downloaded file name if successful. + * @throws {Error} - If the file fails to download after the maximum number of retries. + */ + +async function downloadNodeBinary(version, platform, arch) { + const extension = (platform === "win") ? "zip" : "tar.gz"; + const fileName = `node-v${version}-${platform}-${arch}.${extension}`; + + const fullPath = `${__dirname}/${fileName}` + // Check if the file already exists + if (fs.existsSync(fullPath)) { + console.log(`File ${fileName} already exists. No need to download.`); + return fileName; + } + const MAX_RETRIES = 3 + console.log(`downloading node ${version} for ${platform} ${arch}`); + for (let attempt = 0; attempt < MAX_RETRIES; attempt++) { + try { + const file = fs.createWriteStream(fullPath); + await new Promise((resolve, reject) => { + https.get(`${LTS_URL_PREFIX}node-v${version}-${platform}-${arch}.${extension}`, (res) => { + res.pipe(file); + res.on('end', () => resolve(fileName)); + res.on('error', (err) => { + fs.unlink(fileName, () => { + }); // Remove the file on error + reject(err); + }); + }); + }); + return fileName; // If the download was successful, return the file name + } catch (err) { + console.error(`Download attempt ${attempt + 1} failed.`); + if (attempt < MAX_RETRIES - 1) { + console.log(`Retrying download...`); + } + } + } + throw new Error(`Failed to download file after ${MAX_RETRIES} attempts.`); +} + + +/** + * Extracts a tar archive file to the specified output directory. + * @param {string} inputFile - The path of the tar archive file to be extracted. + * @param {string} outputDir - The path of the directory where the files will be extracted. + * @returns {Promise} - A Promise that resolves when the extraction is complete. + */ +async function untarFile(inputFile, outputDir) { + // Ensure that inputFile and outputDir are absolute paths + const file = path.resolve(inputFile); + const outdir = path.resolve(outputDir); + + const MAX_FILES = 10000; + const MAX_SIZE = 1000000000; // 1 GB + + let fileCount = 0; + let totalSize = 0; + try { + await tar.x({ + file: file, + cwd: outdir, + filter: (path, entry) => { + fileCount++; + if (fileCount > MAX_FILES) { + throw new Error('Reached max. number of files'); + } + + totalSize += entry.size; + if (totalSize > MAX_SIZE) { + throw new Error('Reached max. size'); + } + + return true; + } + }); + console.log('Extraction complete'); + } catch (err) { + console.error(err); + } +} + +/** + Unzips a file at the specified path to the specified extraction path. + @param {string} zipFilePath - The path to the ZIP file to be extracted. + @param {string} extractPath - The path where the contents of the ZIP file should be extracted. + @returns {void} + */ +function unzipFile(zipFilePath, extractPath) { + const MAX_FILES = 10000; + const MAX_SIZE = 1000000000; // 1 GB + const THRESHOLD_RATIO = 50; + + let fileCount = 0; + let totalSize = 0; + let zip = new AdmZip(zipFilePath); + let zipEntries = zip.getEntries(); + zipEntries.forEach(function (zipEntry) { + fileCount++; + if (fileCount > MAX_FILES) { + throw new Error('Reached max. number of files'); + } + + let entrySize = zipEntry.getData().length; + totalSize += entrySize; + if (totalSize > MAX_SIZE) { + throw new Error('Reached max. size'); + } + + let compressionRatio = entrySize / zipEntry.header.compressedSize; + if (compressionRatio > THRESHOLD_RATIO) { + throw new Error('Reached max. compression ratio'); + } + + if (!zipEntry.isDirectory) { + zip.extractEntryTo(zipEntry.entryName, extractPath); + } + }); + +} + +/** + * Copies the latest version of Node.js binary for a specific platform and architecture. + * @param {string} platform - The platform for which to download the Node.js binary. (e.g., "win", "linux", "mac") + * @param {string} arch - The architecture for which to download the Node.js binary. (e.g., "x86", "x64") + * @returns {Promise} - A Promise that resolves when the Node.js binary is copied successfully. + */ +async function copyLatestNodeForBuild(platform, arch) { + const version = await fetchLatestNodeVersion(); + const fileName = await downloadNodeBinary(version, platform, arch); + const fullPath = `${__dirname}/${fileName}` + let nodeFolder = ""; + + if (platform === "win") { + unzipFile(fullPath, "."); + nodeFolder = fileName.slice(0, -4); + } else { + await untarFile(fullPath, "."); + nodeFolder = fileName.slice(0, -7); + } + console.log(nodeFolder); + const fullPathUnzipFolder = `${__dirname}/${nodeFolder}`; + const fullPathOfNode = `${__dirname}/node`; + await removeDir(fullPathOfNode); + + try { + fs.renameSync(fullPathUnzipFolder, fullPathOfNode); + } catch (err) { + console.error('ERROR:', err); + } + const tauriDestFolder = `${__dirname}/../src/node`; + await removeDir(tauriDestFolder) + + await copyDir(fullPathOfNode, tauriDestFolder); + +} + +/** + * Copies a directory from the source path to the destination path asynchronously. + * @param {string} source - The path of the source directory. + * @param {string} destination - The path of the destination directory. + * @returns {Promise} - A promise that resolves when the directory is successfully copied, or rejects with an error. + * @throws {Error} - If an error occurs during the copying process. + */ +async function copyDir(source, destination) { + try { + console.log(source); + console.log(destination); + await fsExtra.copy(source, destination); + console.log('Successfully copied the folder!'); + } catch (err) { + console.error('An error occurred: ', err); + } +} + +/** + * Asynchronously removes a specified directory if it exists. + * + * @async + * @function + * @param {string} dirPath - The path of the directory to be removed. + * @returns {Promise} A promise that resolves to a string indicating whether the directory was not found or was successfully removed. + * @throws {Error} If an error occurs during the operation, it will be logged to the console. + */ +async function removeDir(dirPath) { + try { + const exists = await fsExtra.pathExists(dirPath); + + if (!exists) { + return 'Directory not found!'; + } + + await fsExtra.remove(dirPath); + return 'Directory removed!'; + } catch (err) { + console.error(err); + } +} + +await copyLatestNodeForBuild("linux", "x64"); From 7adaaddd8650fbc8ab46b8e723225b568821e959 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 29 Jun 2023 00:48:24 +0530 Subject: [PATCH 007/864] chore: add support to bundle node as resource --- src-build/downloadNode.js | 6 ++---- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 10 +++++++++- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index ca8c0fc7..848bb486 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -26,7 +26,6 @@ async function fetchLatestNodeVersion() { res.on('data', (chunk) => { data += chunk; }); - res.on('end', () => { const versionMatch = /node-v(\d+\.\d+\.\d+)/.exec(data); @@ -112,12 +111,10 @@ async function untarFile(inputFile, outputDir) { if (fileCount > MAX_FILES) { throw new Error('Reached max. number of files'); } - totalSize += entry.size; if (totalSize > MAX_SIZE) { throw new Error('Reached max. size'); } - return true; } }); @@ -195,10 +192,11 @@ async function copyLatestNodeForBuild(platform, arch) { } catch (err) { console.error('ERROR:', err); } - const tauriDestFolder = `${__dirname}/../src/node`; + const tauriDestFolder = `${__dirname}/../src-tauri/node`; await removeDir(tauriDestFolder) await copyDir(fullPathOfNode, tauriDestFolder); + await removeDir(fullPathOfNode); } diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a20adbf8..6bd00d7e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,7 +16,7 @@ tauri-build = { version = "1.4.0", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4.1", features = ["window-all"] } +tauri = { version = "1.4.1", features = [ "fs-all", "window-all"] } [features] # by default Tauri runs in production mode diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index bc4ea195..209400df 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -16,6 +16,12 @@ "all": false, "window": { "all": true + }, + "fs": { + "all": true, + "scope": [ + "$RESOURCE/*" + ] } }, "bundle": { @@ -42,7 +48,9 @@ "providerShortName": null, "signingIdentity": null }, - "resources": [], + "resources": [ + "node/*" + ], "shortDescription": "", "targets": "all", "windows": { From f92c577b4653906a302de0c9836b10dfbb4d7ff5 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 29 Jun 2023 01:22:47 +0530 Subject: [PATCH 008/864] chore: addiing support to install node while running npm install --- package-lock.json | 1 + package.json | 3 ++- src-build/downloadNode.js | 24 ++++++++++++++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9df0ec03..8d968f8f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "phoenix-code-ide", "version": "5.0.0", + "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.4.0", "adm-zip": "0.5.10", diff --git a/package.json b/package.json index 076ed738..42a0c6a2 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "tauri": "tauri", "build": "", "servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", - "serve": "tauri dev" + "serve": "tauri dev", + "postinstall" : "node ./src-build/downloadNode.js" }, "devDependencies": { "@tauri-apps/cli": "1.4.0", diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index 848bb486..52549ab6 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -6,6 +6,7 @@ import AdmZip from 'adm-zip'; import {fileURLToPath} from 'url'; import {dirname} from 'path'; import * as fsExtra from "fs-extra"; +import * as os from "os"; const __filename = fileURLToPath(import.meta.url); @@ -179,7 +180,7 @@ async function copyLatestNodeForBuild(platform, arch) { unzipFile(fullPath, "."); nodeFolder = fileName.slice(0, -4); } else { - await untarFile(fullPath, "."); + await untarFile(fullPath, __dirname); nodeFolder = fileName.slice(0, -7); } console.log(nodeFolder); @@ -242,4 +243,23 @@ async function removeDir(dirPath) { } } -await copyLatestNodeForBuild("linux", "x64"); +/** + * Retrieves platform details including the operating system platform and architecture. + * @returns {Object} An object containing the platform and architecture details. + * @example + * const platformDetails = getPlatformDetails(); + * console.log(platformDetails.platform); // "win" or the actual platform value + * console.log(platformDetails.arch); // the architecture value + */ +function getPlatformDetails() { + const platform = os.platform(); + const arch = os.arch(); + return { + platform: (platform === "win32") ? "win" : platform, + arch: arch + } +} + +const platformDetails = getPlatformDetails(); + +await copyLatestNodeForBuild(platformDetails.platform, platformDetails.arch); From 1f0db1f14541b170eecb5dac3aeef6e908ba1811 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 29 Jun 2023 02:09:42 +0530 Subject: [PATCH 009/864] fix: windows build faliure --- src-build/downloadNode.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index 52549ab6..98813332 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -173,19 +173,19 @@ function unzipFile(zipFilePath, extractPath) { async function copyLatestNodeForBuild(platform, arch) { const version = await fetchLatestNodeVersion(); const fileName = await downloadNodeBinary(version, platform, arch); - const fullPath = `${__dirname}/${fileName}` + const fullPath = (platform === "win") ? `${__dirname}\\${fileName}` : `${__dirname}/${fileName}`; let nodeFolder = ""; if (platform === "win") { - unzipFile(fullPath, "."); + unzipFile(fullPath, __dirname); nodeFolder = fileName.slice(0, -4); } else { await untarFile(fullPath, __dirname); nodeFolder = fileName.slice(0, -7); } console.log(nodeFolder); - const fullPathUnzipFolder = `${__dirname}/${nodeFolder}`; - const fullPathOfNode = `${__dirname}/node`; + const fullPathUnzipFolder = (platform === "win") ? `${__dirname}\\${nodeFolder}` : `${__dirname}/${nodeFolder}`; + const fullPathOfNode = (platform === "win") ? `${__dirname}\\node` : `${__dirname}/node`; await removeDir(fullPathOfNode); try { @@ -193,7 +193,7 @@ async function copyLatestNodeForBuild(platform, arch) { } catch (err) { console.error('ERROR:', err); } - const tauriDestFolder = `${__dirname}/../src-tauri/node`; + const tauriDestFolder = (platform === "win") ? `${__dirname}\\..\\src-tauri\\node` : `${__dirname}/../src-tauri/node`; await removeDir(tauriDestFolder) await copyDir(fullPathOfNode, tauriDestFolder); From 6253a1153959e7a95fb5817ac2471acb33b90fe7 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 29 Jun 2023 02:17:25 +0530 Subject: [PATCH 010/864] chore: add log to see platform details --- src-build/downloadNode.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index 98813332..4ac48b2a 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -261,5 +261,6 @@ function getPlatformDetails() { } const platformDetails = getPlatformDetails(); +console.log(platformDetails); await copyLatestNodeForBuild(platformDetails.platform, platformDetails.arch); From 2d98919ddae84cfdc7c10a6bccb98cfe639fcc36 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 29 Jun 2023 16:04:41 +0530 Subject: [PATCH 011/864] feat: added support for cleaning node and support for installing node for darwin x64 --- .github/workflows/tauri-build.yml | 1 + package.json | 5 ++- src-build/cleanNode.js | 21 +++++++++ src-build/downloadNode.js | 48 +++----------------- src-build/utils.js | 74 +++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 44 deletions(-) create mode 100644 src-build/cleanNode.js create mode 100644 src-build/utils.js diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index d5924b61..e16fb3f3 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -70,6 +70,7 @@ jobs: run: | rustup target add aarch64-apple-darwin npm install + npm run installNodeDarwin - name: build for mac arm (Mac only) if: matrix.platform == 'macos-latest' uses: tauri-apps/tauri-action@v0 diff --git a/package.json b/package.json index 42a0c6a2..f3d4440d 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,10 @@ "build": "", "servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", "serve": "tauri dev", - "postinstall" : "node ./src-build/downloadNode.js" + "postinstall": "node ./src-build/downloadNode.js", + "cleanNode": "node src-build/cleanNode.js", + "preinstallNodeDarwin": "npm run cleanNode", + "installNodeDarwin": "node ./src-build/downloadNode.js '{\"platform\":\"darwin\",\"arch\":\"x64\"}'" }, "devDependencies": { "@tauri-apps/cli": "1.4.0", diff --git a/src-build/cleanNode.js b/src-build/cleanNode.js new file mode 100644 index 00000000..3e9a0c5f --- /dev/null +++ b/src-build/cleanNode.js @@ -0,0 +1,21 @@ +import {fileURLToPath} from "url"; +import {dirname} from "path"; + +import {removeDir, listFolders, getPlatformDetails} from "./utils.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +async function cleanNode() { + const listOfNodeFolders = await listFolders(__dirname, "node"); + for (let files of listOfNodeFolders) { + await removeDir(files); + } + const platform = getPlatformDetails().platform; + const tauriDestFolderNode = (platform === "win") ? `${__dirname}\\..\\src-tauri\\node`(args.length === 1) + : `${__dirname}/../src-tauri/node`; + await removeDir(tauriDestFolderNode) + console.log(listOfNodeFolders); +} + +await cleanNode(); diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index 4ac48b2a..0a02f90e 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -6,7 +6,8 @@ import AdmZip from 'adm-zip'; import {fileURLToPath} from 'url'; import {dirname} from 'path'; import * as fsExtra from "fs-extra"; -import * as os from "os"; +import {getPlatformDetails} from "./utils.js"; +import {removeDir} from "./utils.js"; const __filename = fileURLToPath(import.meta.url); @@ -219,48 +220,9 @@ async function copyDir(source, destination) { } } -/** - * Asynchronously removes a specified directory if it exists. - * - * @async - * @function - * @param {string} dirPath - The path of the directory to be removed. - * @returns {Promise} A promise that resolves to a string indicating whether the directory was not found or was successfully removed. - * @throws {Error} If an error occurs during the operation, it will be logged to the console. - */ -async function removeDir(dirPath) { - try { - const exists = await fsExtra.pathExists(dirPath); - - if (!exists) { - return 'Directory not found!'; - } - - await fsExtra.remove(dirPath); - return 'Directory removed!'; - } catch (err) { - console.error(err); - } -} - -/** - * Retrieves platform details including the operating system platform and architecture. - * @returns {Object} An object containing the platform and architecture details. - * @example - * const platformDetails = getPlatformDetails(); - * console.log(platformDetails.platform); // "win" or the actual platform value - * console.log(platformDetails.arch); // the architecture value - */ -function getPlatformDetails() { - const platform = os.platform(); - const arch = os.arch(); - return { - platform: (platform === "win32") ? "win" : platform, - arch: arch - } -} - -const platformDetails = getPlatformDetails(); +let args = process.argv.slice(2); +console.log(args); +const platformDetails = (args.length === 1) ? JSON.parse(args[0]) : getPlatformDetails(); console.log(platformDetails); await copyLatestNodeForBuild(platformDetails.platform, platformDetails.arch); diff --git a/src-build/utils.js b/src-build/utils.js new file mode 100644 index 00000000..5cb70e8b --- /dev/null +++ b/src-build/utils.js @@ -0,0 +1,74 @@ +import * as fsExtra from "fs-extra"; +import { promises as fs } from 'fs'; +import * as path from "path"; +import * as os from "os"; +/** + * Asynchronously removes a specified directory if it exists. + * + * @async + * @function + * @param {string} dirPath - The path of the directory to be removed. + * @returns {Promise} A promise that resolves to a string indicating whether the directory was not found or was successfully removed. + * @throws {Error} If an error occurs during the operation, it will be logged to the console. + */ +export async function removeDir(dirPath) { + try { + const exists = await fsExtra.pathExists(dirPath); + + if (!exists) { + return 'Directory not found!'; + } + + await fsExtra.remove(dirPath); + return 'Directory removed!'; + } catch (err) { + console.error(err); + } +} +/** + * Asynchronously lists all folders in a given start path that start with a specific filter. + * + * @param {string} startPath - The directory path where the search should start. + * @param {string} filter - The string filter to match the beginning of the folder names. + * @returns {Promise} - A promise that resolves with an array of folder paths that match the filter. + * @throws {Error} - Throws an error if there's an issue reading the directory or retrieving the stats of a file. + * + * @example + * // return ['/path/to/folder1', '/path/to/folder2'] + * listFolders('/path/to', 'folder') + * + * @example + * // return ['/path/to/Foo', '/path/to/FooBar'] + * listFolders('/path/to', 'Foo') + */ + +export async function listFolders(startPath, filter) { + let files = await fs.readdir(startPath); + let folders = []; + + for(let file of files) { + let fullPath = path.join(startPath, file); + let stat = await fs.stat(fullPath); + if(file.startsWith(filter)) { + folders.push(fullPath); + } + } + return folders; +} + +/** + * Retrieves platform details including the operating system platform and architecture. + * @returns {Object} An object containing the platform and architecture details. + * @example + * const platformDetails = getPlatformDetails(); + * console.log(platformDetails.platform); // "win" or the actual platform value + * console.log(platformDetails.arch); // the architecture value + */ +export function getPlatformDetails() { + const platform = os.platform(); + const arch = os.arch(); + return { + platform: (platform === "win32") ? "win" : platform, + arch: arch + } +} From f536dc5d7f11261e39f39966d415786d0b0992b1 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 29 Jun 2023 16:23:23 +0530 Subject: [PATCH 012/864] chore: fix for sonar cloud builds --- src-build/downloadNode.js | 6 ++---- src-build/utils.js | 10 ++++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index 0a02f90e..5d3bfc4f 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -6,9 +6,7 @@ import AdmZip from 'adm-zip'; import {fileURLToPath} from 'url'; import {dirname} from 'path'; import * as fsExtra from "fs-extra"; -import {getPlatformDetails} from "./utils.js"; -import {removeDir} from "./utils.js"; - +import {getPlatformDetails, removeDir} from "./utils.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -122,7 +120,7 @@ async function untarFile(inputFile, outputDir) { }); console.log('Extraction complete'); } catch (err) { - console.error(err); + throw new Error(err); } } diff --git a/src-build/utils.js b/src-build/utils.js index 5cb70e8b..310bf6da 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -1,7 +1,8 @@ import * as fsExtra from "fs-extra"; -import { promises as fs } from 'fs'; +import {promises as fs} from 'fs'; import * as path from "path"; import * as os from "os"; + /** * Asynchronously removes a specified directory if it exists. * @@ -25,6 +26,7 @@ export async function removeDir(dirPath) { console.error(err); } } + /** * Asynchronously lists all folders in a given start path that start with a specific filter. * @@ -46,10 +48,10 @@ export async function listFolders(startPath, filter) { let files = await fs.readdir(startPath); let folders = []; - for(let file of files) { + for (let file of files) { let fullPath = path.join(startPath, file); - let stat = await fs.stat(fullPath); - if(file.startsWith(filter)) { + await fs.stat(fullPath); + if (file.startsWith(filter)) { folders.push(fullPath); } } From 69067f09f63877ce326ba6cf69536797cf142ce1 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 29 Jun 2023 16:49:21 +0530 Subject: [PATCH 013/864] fix: arm64 binary for mac --- .github/workflows/tauri-build.yml | 2 +- package.json | 4 ++-- src-build/downloadNode.js | 4 +++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index e16fb3f3..fe82ab67 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -70,7 +70,7 @@ jobs: run: | rustup target add aarch64-apple-darwin npm install - npm run installNodeDarwin + npm run installNodeArmDarwin - name: build for mac arm (Mac only) if: matrix.platform == 'macos-latest' uses: tauri-apps/tauri-action@v0 diff --git a/package.json b/package.json index f3d4440d..3343d10c 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,8 @@ "serve": "tauri dev", "postinstall": "node ./src-build/downloadNode.js", "cleanNode": "node src-build/cleanNode.js", - "preinstallNodeDarwin": "npm run cleanNode", - "installNodeDarwin": "node ./src-build/downloadNode.js '{\"platform\":\"darwin\",\"arch\":\"x64\"}'" + "preinstallNodeArmDarwin": "npm run cleanNode", + "installNodeArmDarwin": "node ./src-build/downloadNode.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'" }, "devDependencies": { "@tauri-apps/cli": "1.4.0", diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index 5d3bfc4f..e06eaaed 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -64,7 +64,9 @@ async function downloadNodeBinary(version, platform, arch) { try { const file = fs.createWriteStream(fullPath); await new Promise((resolve, reject) => { - https.get(`${LTS_URL_PREFIX}node-v${version}-${platform}-${arch}.${extension}`, (res) => { + const downloadUrl = `${LTS_URL_PREFIX}node-v${version}-${platform}-${arch}.${extension}`; + console.log(downloadUrl); + https.get(downloadUrl, (res) => { res.pipe(file); res.on('end', () => resolve(fileName)); res.on('error', (err) => { From 29c0378873d68fbb0b8878c22aab72ebdd58d1d9 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 29 Jun 2023 18:07:58 +0530 Subject: [PATCH 014/864] chore: remove unwanted logs --- .github/workflows/tauri-build.yml | 1 - src-build/cleanNode.js | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index fe82ab67..1d7249ac 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -69,7 +69,6 @@ jobs: if: matrix.platform == 'macos-latest' run: | rustup target add aarch64-apple-darwin - npm install npm run installNodeArmDarwin - name: build for mac arm (Mac only) if: matrix.platform == 'macos-latest' diff --git a/src-build/cleanNode.js b/src-build/cleanNode.js index 3e9a0c5f..b7158256 100644 --- a/src-build/cleanNode.js +++ b/src-build/cleanNode.js @@ -12,10 +12,9 @@ async function cleanNode() { await removeDir(files); } const platform = getPlatformDetails().platform; - const tauriDestFolderNode = (platform === "win") ? `${__dirname}\\..\\src-tauri\\node`(args.length === 1) + const tauriDestFolderNode = (platform === "win") ? `${__dirname}\\..\\src-tauri\\node` : `${__dirname}/../src-tauri/node`; - await removeDir(tauriDestFolderNode) - console.log(listOfNodeFolders); + await removeDir(tauriDestFolderNode); } await cleanNode(); From e90d5d1a68a68f13a6e6bf677daa52b52f9f35cb Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 29 Jun 2023 18:13:21 +0530 Subject: [PATCH 015/864] chore: adding more logs --- src-build/cleanNode.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src-build/cleanNode.js b/src-build/cleanNode.js index b7158256..005a53d5 100644 --- a/src-build/cleanNode.js +++ b/src-build/cleanNode.js @@ -7,6 +7,7 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); async function cleanNode() { + console.log('cleaning current node used by phcode from workspace'); const listOfNodeFolders = await listFolders(__dirname, "node"); for (let files of listOfNodeFolders) { await removeDir(files); From 560408b76ffb4f1dc11191ff32f732f2d87a09f0 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 30 Jun 2023 20:18:30 +0530 Subject: [PATCH 016/864] feat: adding support for sidecar --- src-build/cleanNode.js | 16 +- src-build/downloadNode.js | 17 +- src-build/utils.js | 9 +- src-tauri/Cargo.lock | 832 ++++++++++++++++++++------------------ src-tauri/Cargo.toml | 2 +- src-tauri/app/hello.js | 0 src-tauri/tauri.conf.json | 12 +- 7 files changed, 484 insertions(+), 404 deletions(-) create mode 100644 src-tauri/app/hello.js diff --git a/src-build/cleanNode.js b/src-build/cleanNode.js index 005a53d5..f8e4caf5 100644 --- a/src-build/cleanNode.js +++ b/src-build/cleanNode.js @@ -1,21 +1,27 @@ import {fileURLToPath} from "url"; import {dirname} from "path"; -import {removeDir, listFolders, getPlatformDetails} from "./utils.js"; +import {removeDir, listFilesAndFolders, getPlatformDetails} from "./utils.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); async function cleanNode() { console.log('cleaning current node used by phcode from workspace'); - const listOfNodeFolders = await listFolders(__dirname, "node"); + const listOfNodeFolders = await listFilesAndFolders(__dirname, "node"); for (let files of listOfNodeFolders) { await removeDir(files); } const platform = getPlatformDetails().platform; - const tauriDestFolderNode = (platform === "win") ? `${__dirname}\\..\\src-tauri\\node` - : `${__dirname}/../src-tauri/node`; - await removeDir(tauriDestFolderNode); + const tauriDestFolderNode = (platform === "win") ? `${__dirname}\\..\\src-tauri` + : `${__dirname}/../src-tauri`; + + const listOfNodeFoldersToDelete = await listFilesAndFolders(tauriDestFolderNode,"node-"); + console.log(listOfNodeFoldersToDelete); + for (let files of listOfNodeFoldersToDelete) { + await removeDir(files); + } + } await cleanNode(); diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index e06eaaed..a48f0a05 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -6,7 +6,7 @@ import AdmZip from 'adm-zip'; import {fileURLToPath} from 'url'; import {dirname} from 'path'; import * as fsExtra from "fs-extra"; -import {getPlatformDetails, removeDir} from "./utils.js"; +import {getPlatformDetails, getSideCarBinName, removeDir} from "./utils.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -194,12 +194,19 @@ async function copyLatestNodeForBuild(platform, arch) { } catch (err) { console.error('ERROR:', err); } - const tauriDestFolder = (platform === "win") ? `${__dirname}\\..\\src-tauri\\node` : `${__dirname}/../src-tauri/node`; - await removeDir(tauriDestFolder) - await copyDir(fullPathOfNode, tauriDestFolder); - await removeDir(fullPathOfNode); + const srcNode = (platform === "win") ? `${fullPathOfNode}\\node.exe` : `${fullPathOfNode}/bin/node`; + const destFileName = getSideCarBinName(platform, arch); + const tauriDestNode = (platform === "win") ? `${__dirname}\\..\\src-tauri\\${destFileName}` : `${__dirname}/../src-tauri/${destFileName}`; + try { + fs.copyFileSync(srcNode, tauriDestNode); + console.log("File copied successfully!"); + } catch (err) { + console.log("Error Found:", err); + throw new Error(err); + } + await removeDir(fullPathOfNode); } /** diff --git a/src-build/utils.js b/src-build/utils.js index 310bf6da..96edcec7 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -44,7 +44,7 @@ export async function removeDir(dirPath) { * listFolders('/path/to', 'Foo') */ -export async function listFolders(startPath, filter) { +export async function listFilesAndFolders(startPath, filter) { let files = await fs.readdir(startPath); let folders = []; @@ -74,3 +74,10 @@ export function getPlatformDetails() { arch: arch } } + +export function getSideCarBinName(platform, arch) { + if (platform === "linux") { + return "node-x86_64-unknown-linux-gnu"; + } + return "node"; +} diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 759d1abd..3e9d30dc 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -17,6 +26,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +dependencies = [ + "memchr", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -49,9 +67,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "atk" @@ -74,7 +92,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] @@ -83,6 +101,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.1" @@ -109,9 +142,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] @@ -129,9 +162,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.3.2" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -139,11 +172,12 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.17" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" dependencies = [ "memchr", + "serde", ] [[package]] @@ -154,9 +188,9 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytemuck" -version = "1.12.3" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" +checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" [[package]] name = "byteorder" @@ -166,9 +200,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cairo-rs" @@ -191,7 +225,7 @@ checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" dependencies = [ "glib-sys", "libc", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] @@ -238,11 +272,12 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.11.0" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0357a6402b295ca3a86bc148e84df46c02e41f41fef186bda662557ef6328aa" +checksum = "215c0072ecc28f92eeb0eea38ba63ddfcb65c2828c46311d646f1a3ff5f9841c" dependencies = [ "smallvec", + "target-lexicon", ] [[package]] @@ -282,9 +317,9 @@ dependencies = [ [[package]] name = "cocoa-foundation" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" +checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" dependencies = [ "bitflags", "block", @@ -329,9 +364,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "core-graphics" @@ -348,21 +383,20 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" dependencies = [ "bitflags", "core-foundation", - "foreign-types", "libc", ] [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" dependencies = [ "libc", ] @@ -378,9 +412,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if", "crossbeam-utils", @@ -388,9 +422,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] @@ -419,17 +453,17 @@ dependencies = [ "proc-macro2", "quote", "smallvec", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] name = "cssparser-macros" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfae75de57f2b2e85e8768c3ea840fd159c8f33e2b6522c7835b7abac81be16e" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 1.0.107", + "syn 2.0.22", ] [[package]] @@ -439,15 +473,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ "quote", - "syn 1.0.107", + "syn 1.0.109", ] -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - [[package]] name = "darling" version = "0.20.1" @@ -492,15 +520,15 @@ dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version 0.4.0", - "syn 1.0.107", + "rustc_version", + "syn 1.0.109", ] [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", @@ -535,24 +563,24 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "dtoa" -version = "0.4.8" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" +checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" [[package]] name = "dtoa-short" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03329ae10e79ede66c9ce4dc930aa8599043b0743008548680f25b91502d6" +checksum = "dbaceec3c6e4211c79e7b1800fb9680527106beb2f9c51904a3210c03a448c74" dependencies = [ "dtoa", ] [[package]] name = "dunce" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "embed-resource" @@ -561,7 +589,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80663502655af01a2902dff3f06869330782267924bf1788410b74edcd93770a" dependencies = [ "cc", - "rustc_version 0.4.0", + "rustc_version", "toml 0.7.5", "vswhom", "winreg", @@ -575,9 +603,9 @@ checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" [[package]] name = "encoding_rs" -version = "0.8.31" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ "cfg-if", ] @@ -588,42 +616,72 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +[[package]] +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] +[[package]] +name = "fdeflate" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +dependencies = [ + "simd-adler32", +] + [[package]] name = "field-offset" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e1c54951450cbd39f3dbcf1005ac413b49487dabf18a720ad2383eccfeffb92" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ "memoffset", - "rustc_version 0.3.3", + "rustc_version", ] [[package]] name = "filetime" -version = "0.2.19" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "windows-sys", ] [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", "miniz_oxide", @@ -652,9 +710,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -671,24 +729,24 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -697,32 +755,32 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 2.0.22", ] [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-core", "futures-macro", @@ -780,7 +838,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] @@ -797,7 +855,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] @@ -811,7 +869,7 @@ dependencies = [ "gobject-sys", "libc", "pkg-config", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] @@ -823,28 +881,28 @@ dependencies = [ "gdk-sys", "glib-sys", "libc", - "system-deps 6.0.3", + "system-deps 6.1.1", "x11", ] [[package]] name = "generator" -version = "0.7.2" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266041a359dfa931b370ef684cceb84b166beb14f7f0421f4a6a3d0c446d12e" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" dependencies = [ "cc", "libc", "log", "rustversion", - "windows 0.39.0", + "windows 0.48.0", ] [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -863,15 +921,21 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "gio" version = "0.15.12" @@ -898,7 +962,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.0.3", + "system-deps 6.1.1", "winapi", ] @@ -924,17 +988,17 @@ dependencies = [ [[package]] name = "glib-macros" -version = "0.15.11" +version = "0.15.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64" +checksum = "10c6ae9f6fa26f4fb2ac16b528d138d971ead56141de489f8111e259b9df3c4a" dependencies = [ "anyhow", - "heck 0.4.0", + "heck 0.4.1", "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -944,22 +1008,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" dependencies = [ "libc", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] name = "glob" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "bstr", "fnv", "log", @@ -974,7 +1038,7 @@ checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" dependencies = [ "glib-sys", "libc", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] @@ -1015,21 +1079,21 @@ dependencies = [ "gobject-sys", "libc", "pango-sys", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] name = "gtk3-macros" -version = "0.15.4" +version = "0.15.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f518afe90c23fba585b2d7697856f9e6a7bbc62f65588035e66f6afb01a2e9" +checksum = "684c0456c086e8e7e9af73ec5b84e35938df394712054550e81558d21c44ab0d" dependencies = [ "anyhow", "proc-macro-crate", "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -1055,18 +1119,15 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "hex" @@ -1085,18 +1146,18 @@ dependencies = [ "markup5ever", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", - "itoa 1.0.5", + "itoa 1.0.6", ] [[package]] @@ -1146,9 +1207,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1156,11 +1217,10 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.18" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" +checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" dependencies = [ - "crossbeam-utils", "globset", "lazy_static", "log", @@ -1174,9 +1234,9 @@ dependencies = [ [[package]] name = "image" -version = "0.24.5" +version = "0.24.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945" +checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" dependencies = [ "bytemuck", "byteorder", @@ -1187,9 +1247,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown 0.12.3", @@ -1224,6 +1284,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + [[package]] name = "itoa" version = "0.4.8" @@ -1232,9 +1303,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "javascriptcore-rs" @@ -1320,9 +1391,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "line-wrap" @@ -1333,11 +1404,17 @@ dependencies = [ "safemem", ] +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -1345,12 +1422,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "loom" @@ -1407,9 +1481,9 @@ dependencies = [ [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" @@ -1419,20 +1493,21 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", + "simd-adler32", ] [[package]] @@ -1517,9 +1592,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", @@ -1527,23 +1602,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.7" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.7" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -1574,11 +1649,30 @@ dependencies = [ "objc", ] +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "os_pipe" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" +dependencies = [ + "libc", + "windows-sys", +] [[package]] name = "overload" @@ -1608,7 +1702,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] @@ -1623,32 +1717,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.3.5", "smallvec", - "windows-sys", + "windows-targets", ] [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - -[[package]] -name = "pest" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4" -dependencies = [ - "thiserror", - "ucd-trie", -] +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "phf" @@ -1713,7 +1797,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -1727,7 +1811,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -1772,32 +1856,33 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "plist" -version = "1.3.1" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd39bc6cdc9355ad1dc5eeedefee696bb35c34caf21768741e81826c0bbd7225" +checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590" dependencies = [ - "base64 0.13.1", - "indexmap 1.9.2", + "base64 0.21.2", + "indexmap 1.9.3", "line-wrap", + "quick-xml", "serde", "time", - "xml-rs", ] [[package]] name = "png" -version = "0.17.7" +version = "0.17.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" +checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11" dependencies = [ "bitflags", "crc32fast", + "fdeflate", "flate2", "miniz_oxide", ] @@ -1816,13 +1901,12 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro-crate" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "thiserror", - "toml 0.5.10", + "toml_edit", ] [[package]] @@ -1834,7 +1918,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", "version_check", ] @@ -1864,11 +1948,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-xml" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" +dependencies = [ + "memchr", +] + [[package]] name = "quote" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] @@ -1933,7 +2026,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.10", ] [[package]] @@ -1956,12 +2049,9 @@ dependencies = [ [[package]] name = "raw-window-handle" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a" -dependencies = [ - "cty", -] +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "redox_syscall" @@ -1972,26 +2062,35 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + [[package]] name = "redox_users" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.8", - "redox_syscall", + "getrandom 0.2.10", + "redox_syscall 0.2.16", "thiserror", ] [[package]] name = "regex" -version = "1.7.0" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ - "aho-corasick", + "aho-corasick 1.0.2", "memchr", - "regex-syntax", + "regex-syntax 0.7.2", ] [[package]] @@ -2000,32 +2099,26 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "regex-syntax" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] -name = "rustc_version" -version = "0.3.3" +name = "rustc-demangle" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" -dependencies = [ - "semver 0.11.0", -] +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc_version" @@ -2033,20 +2126,34 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.16", + "semver", +] + +[[package]] +name = "rustix" +version = "0.37.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62f25693a73057a1b4cb56179dd3c7ea21a7c6c5ee7d85781f5749b46f34b79c" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", ] [[package]] name = "rustversion" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "safemem" @@ -2097,31 +2204,13 @@ dependencies = [ [[package]] name = "semver" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" dependencies = [ "serde", ] -[[package]] -name = "semver-parser" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" -dependencies = [ - "pest", -] - [[package]] name = "serde" version = "1.0.164" @@ -2148,20 +2237,20 @@ version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ - "itoa 1.0.5", + "itoa 1.0.6", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" +checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 2.0.22", ] [[package]] @@ -2182,7 +2271,7 @@ dependencies = [ "base64 0.21.2", "chrono", "hex", - "indexmap 1.9.2", + "indexmap 1.9.3", "serde", "serde_json", "serde_with_macros", @@ -2220,7 +2309,7 @@ checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -2235,9 +2324,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", @@ -2253,6 +2342,22 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared_child" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "simd-adler32" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" + [[package]] name = "siphasher" version = "0.3.10" @@ -2261,9 +2366,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] @@ -2319,9 +2424,9 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.8.4" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", @@ -2351,9 +2456,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -2380,20 +2485,20 @@ dependencies = [ "cfg-expr 0.9.1", "heck 0.3.3", "pkg-config", - "toml 0.5.10", + "toml 0.5.11", "version-compare 0.0.11", ] [[package]] name = "system-deps" -version = "6.0.3" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2955b1fe31e1fa2fbd1976b71cc69a606d7d4da16f6de3333d0c92d51419aeff" +checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3" dependencies = [ - "cfg-expr 0.11.0", - "heck 0.4.0", + "cfg-expr 0.15.3", + "heck 0.4.1", "pkg-config", - "toml 0.5.10", + "toml 0.7.5", "version-compare 0.1.1", ] @@ -2452,7 +2557,7 @@ checksum = "3b27a4bcc5eb524658234589bdffc7e7bfb996dbae6ce9393bfd39cb4159b445" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -2466,6 +2571,12 @@ dependencies = [ "xattr", ] +[[package]] +name = "target-lexicon" +version = "0.12.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1c7f239eb94671427157bd93b3694320f3668d4e1eff08c7285366fd777fac" + [[package]] name = "tauri" version = "1.4.1" @@ -2482,19 +2593,22 @@ dependencies = [ "glib", "glob", "gtk", - "heck 0.4.0", + "heck 0.4.1", "http", "ignore", "objc", "once_cell", + "os_pipe", "percent-encoding", "rand 0.8.5", "raw-window-handle", - "semver 1.0.16", + "regex", + "semver", "serde", "serde_json", "serde_repr", "serialize-to-javascript", + "shared_child", "state", "tar", "tauri-macros", @@ -2519,9 +2633,9 @@ checksum = "7d2edd6a259b5591c8efdeb9d5702cb53515b82a6affebd55c7fd6d3a27b7d1b" dependencies = [ "anyhow", "cargo_toml", - "heck 0.4.0", + "heck 0.4.1", "json-patch", - "semver 1.0.16", + "semver", "serde", "serde_json", "tauri-utils", @@ -2542,7 +2656,8 @@ dependencies = [ "png", "proc-macro2", "quote", - "semver 1.0.16", + "regex", + "semver", "serde", "serde_json", "sha2", @@ -2559,10 +2674,10 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eb12a2454e747896929338d93b0642144bb51e0dddbb36e579035731f0d76b7" dependencies = [ - "heck 0.4.0", + "heck 0.4.1", "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", "tauri-codegen", "tauri-utils", ] @@ -2618,7 +2733,7 @@ dependencies = [ "ctor", "dunce", "glob", - "heck 0.4.0", + "heck 0.4.1", "html5ever", "infer", "json-patch", @@ -2627,7 +2742,7 @@ dependencies = [ "phf 0.10.1", "proc-macro2", "quote", - "semver 1.0.16", + "semver", "serde", "serde_json", "serde_with", @@ -2649,16 +2764,16 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.3.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ + "autocfg", "cfg-if", "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi", + "redox_syscall 0.3.5", + "rustix", + "windows-sys", ] [[package]] @@ -2700,20 +2815,21 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if", "once_cell", ] [[package]] name = "time" -version = "0.3.17" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" dependencies = [ - "itoa 1.0.5", + "itoa 1.0.6", "serde", "time-core", "time-macros", @@ -2721,15 +2837,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" dependencies = [ "time-core", ] @@ -2745,29 +2861,28 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.25.0" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", - "memchr", "num_cpus", "pin-project-lite", - "windows-sys", ] [[package]] name = "toml" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] @@ -2820,20 +2935,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 2.0.22", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", "valuable", @@ -2852,9 +2967,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ "matchers", "nu-ansi-term", @@ -2883,23 +2998,17 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" -[[package]] -name = "ucd-trie" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" - [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unicode-normalization" @@ -2912,15 +3021,15 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", @@ -2936,11 +3045,11 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.2.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" +checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" dependencies = [ - "getrandom 0.2.8", + "getrandom 0.2.10", ] [[package]] @@ -2989,12 +3098,11 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", - "winapi", "winapi-util", ] @@ -3108,7 +3216,7 @@ dependencies = [ "pango-sys", "pkg-config", "soup2-sys", - "system-deps 6.0.3", + "system-deps 6.1.1", ] [[package]] @@ -3131,7 +3239,7 @@ checksum = "eaebe196c01691db62e9e4ca52c5ef1e4fd837dcae27dae3ada599b5a8fd05ac" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn 1.0.109", ] [[package]] @@ -3219,7 +3327,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba01f98f509cb5dc05f4e5fc95e535f78260f15fea8fe1a8abdd08f774f1cee7" dependencies = [ - "syn 1.0.107", + "syn 1.0.109", "windows-tokens", ] @@ -3231,31 +3339,25 @@ checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows_aarch64_gnullvm 0.42.0", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", - "windows_x86_64_gnullvm 0.42.0", - "windows_x86_64_msvc 0.42.0", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_gnullvm", "windows_aarch64_msvc 0.48.0", "windows_i686_gnu 0.48.0", "windows_i686_msvc 0.48.0", "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_gnullvm", "windows_x86_64_msvc 0.48.0", ] @@ -3265,12 +3367,6 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" @@ -3283,12 +3379,6 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" @@ -3301,12 +3391,6 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" -[[package]] -name = "windows_i686_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" - [[package]] name = "windows_i686_gnu" version = "0.48.0" @@ -3319,12 +3403,6 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" -[[package]] -name = "windows_i686_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" - [[package]] name = "windows_i686_msvc" version = "0.48.0" @@ -3337,24 +3415,12 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" @@ -3367,12 +3433,6 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -3438,9 +3498,9 @@ dependencies = [ [[package]] name = "x11" -version = "2.20.1" +version = "2.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2638d5b9c17ac40575fb54bb461a4b1d2a8d1b4ffcc4ff237d254ec59ddeb82" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" dependencies = [ "libc", "pkg-config", @@ -3448,12 +3508,12 @@ dependencies = [ [[package]] name = "x11-dl" -version = "2.20.1" +version = "2.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1536d6965a5d4e573c7ef73a2c15ebcd0b2de3347bdf526c34c297c00ac40f0" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" dependencies = [ - "lazy_static", "libc", + "once_cell", "pkg-config", ] @@ -3465,9 +3525,3 @@ checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" dependencies = [ "libc", ] - -[[package]] -name = "xml-rs" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6bd00d7e..8504e476 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,7 +16,7 @@ tauri-build = { version = "1.4.0", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4.1", features = [ "fs-all", "window-all"] } +tauri = { version = "1.4.1", features = [ "shell-sidecar", "fs-all", "window-all"] } [features] # by default Tauri runs in production mode diff --git a/src-tauri/app/hello.js b/src-tauri/app/hello.js new file mode 100644 index 00000000..e69de29b diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 209400df..656ac655 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -3,7 +3,7 @@ "build": { "beforeBuildCommand": "npm run build", "beforeDevCommand": "npm run servePhoenix", - "devPath": "http://localhost:8000/src", + "devPath": "../src/", "distDir": "../src/", "withGlobalTauri": true }, @@ -22,6 +22,12 @@ "scope": [ "$RESOURCE/*" ] + }, + "shell": { + "sidecar": true, + "scope": [ + { "name": "node", "sidecar": true } + ] } }, "bundle": { @@ -31,7 +37,7 @@ "deb": { "depends": [] }, - "externalBin": [], + "externalBin": ["./node"], "icon": [ "icons/32x32.png", "icons/128x128.png", @@ -49,7 +55,7 @@ "signingIdentity": null }, "resources": [ - "node/*" + "app/*" ], "shortDescription": "", "targets": "all", From 33d617b1f29f8c58d85ac78a5d7c0c9670d2475b Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 30 Jun 2023 20:44:29 +0530 Subject: [PATCH 017/864] fix: add missing side car entries for windows and mac --- src-build/utils.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src-build/utils.js b/src-build/utils.js index 96edcec7..acb0e620 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -76,8 +76,14 @@ export function getPlatformDetails() { } export function getSideCarBinName(platform, arch) { - if (platform === "linux") { + if (platform === "linux" && arch === "x64") { return "node-x86_64-unknown-linux-gnu"; } + if (platform === "darwin" && arch === "x64") { + return "node-x86_64-apple-darwin"; + } + if (platform === "win32" && arch === "x64") { + return "node-x86_64-pc-windows-msvc.exe"; + } return "node"; } From e12a1d6ce220f52cac1f56e33fd8ad3cb6d35814 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 30 Jun 2023 21:12:35 +0530 Subject: [PATCH 018/864] fix: for windows and arm64 mac builds --- src-build/utils.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src-build/utils.js b/src-build/utils.js index acb0e620..fe84bca7 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -82,8 +82,11 @@ export function getSideCarBinName(platform, arch) { if (platform === "darwin" && arch === "x64") { return "node-x86_64-apple-darwin"; } - if (platform === "win32" && arch === "x64") { + if (platform ==="darwin" && arch === "x64"){ + return "node-aarch64-apple-darwin"; + } + if (platform === "win" && arch === "x64") { return "node-x86_64-pc-windows-msvc.exe"; } - return "node"; + throw new Error(`unsupported ${platform} ${arch}`); } From 0c3f958231f28494d3d2498b594ee990fed0bdbb Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 30 Jun 2023 21:29:17 +0530 Subject: [PATCH 019/864] fix: arm64 build faliure in mac --- src-build/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-build/utils.js b/src-build/utils.js index fe84bca7..b7381559 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -82,7 +82,7 @@ export function getSideCarBinName(platform, arch) { if (platform === "darwin" && arch === "x64") { return "node-x86_64-apple-darwin"; } - if (platform ==="darwin" && arch === "x64"){ + if (platform ==="darwin" && arch === "arm64"){ return "node-aarch64-apple-darwin"; } if (platform === "win" && arch === "x64") { From 67c8f18769e5c7ffe414ff13c2012dc4a40bd368 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 30 Jun 2023 22:17:14 +0530 Subject: [PATCH 020/864] feat: initial code to execute node from sidecar --- src-tauri/app/hello.js | 7 +++++++ src-tauri/src/main.rs | 18 +++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src-tauri/app/hello.js b/src-tauri/app/hello.js index e69de29b..1ca59bcb 100644 --- a/src-tauri/app/hello.js +++ b/src-tauri/app/hello.js @@ -0,0 +1,7 @@ +import * as http from "http"; + +//create a server object: +http.createServer(function (req, res) { + res.write('Hello World!'); //write a response to the client + res.end(); //end the response +}).listen(8080); // diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index e27813ad..276f3790 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,11 +1,23 @@ #![cfg_attr( - all(not(debug_assertions), target_os = "windows"), - windows_subsystem = "windows" +all(not(debug_assertions), target_os = "windows"), +windows_subsystem = "windows" )] +use tauri::api::process::Command; + // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command #[tauri::command] -fn greet(name: &str) -> String { +fn greet(handle: tauri::AppHandle) -> String { + let resource_path = handle.path_resolver() + .resolve_resource("app/hello.js") + .expect("failed to resolve resource"); + Command::new_sidecar("node") + .expect("failed to create `my-sidecar` binary command") + .args(resource_path.as_path().to_str()) + .spawn() + .expect("Failed to spawn sidecar"); + let name = "hello"; + println!("hello"); format!("Hello, {}! You've been greeted from Rust!", name) } From 8f563f0b707d002e3b1b2aac547bfb5d77d59ea4 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 30 Jun 2023 22:58:31 +0530 Subject: [PATCH 021/864] fix: unable to open port in windows --- src-tauri/app/hello.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/app/hello.js b/src-tauri/app/hello.js index 1ca59bcb..cbda3d02 100644 --- a/src-tauri/app/hello.js +++ b/src-tauri/app/hello.js @@ -4,4 +4,4 @@ import * as http from "http"; http.createServer(function (req, res) { res.write('Hello World!'); //write a response to the client res.end(); //end the response -}).listen(8080); // +}).listen(8080,'localhost'); // From 34f143d702a2faa45ee8f031e0ca10b6a5754be1 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 1 Jul 2023 00:27:22 +0530 Subject: [PATCH 022/864] fix: node not loading --- src-tauri/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 276f3790..2cb97bb9 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -7,7 +7,7 @@ use tauri::api::process::Command; // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command #[tauri::command] -fn greet(handle: tauri::AppHandle) -> String { +fn greet(handle: tauri::AppHandle, name: &str) -> String { let resource_path = handle.path_resolver() .resolve_resource("app/hello.js") .expect("failed to resolve resource"); @@ -16,7 +16,7 @@ fn greet(handle: tauri::AppHandle) -> String { .args(resource_path.as_path().to_str()) .spawn() .expect("Failed to spawn sidecar"); - let name = "hello"; + // let name = "hello"; println!("hello"); format!("Hello, {}! You've been greeted from Rust!", name) } From 79959575f586217d5baa17cad01e16a5ddd0fc77 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 7 Jul 2023 17:08:50 +0530 Subject: [PATCH 023/864] feat: action scaffolding to trigger update notification json pull requests on release creation --- .github/workflows/updateNotification.js | 28 ++++++++++++++ .github/workflows/updateNotification.yml | 47 ++++++++++++++++++++++++ docs/readme.md | 2 + docs/tauri/readme.md | 4 ++ 4 files changed, 81 insertions(+) create mode 100644 .github/workflows/updateNotification.js create mode 100644 .github/workflows/updateNotification.yml create mode 100644 docs/readme.md create mode 100644 docs/tauri/readme.md diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js new file mode 100644 index 00000000..9a0858da --- /dev/null +++ b/.github/workflows/updateNotification.js @@ -0,0 +1,28 @@ +import fs from 'fs'; + +export default async function printStuff({github, context, githubWorkspaceRoot}) { + console.log(github, context, "yo"); + const fullRepoName = context.payload.repository.full_name; + console.log("repository full name: ", fullRepoName); // Eg: 'phcode-dev/phoenix-desktop' + const owner = fullRepoName.split("/")[0], repo = fullRepoName.split("/")[1]; + console.log("repository owner, repo: ", owner, repo); // Eg: 'phcode-dev/phoenix-desktop' + const releaseTag = context.payload.release.tag_name; + console.log("Release Tag name: ", releaseTag); + const isPreRelease = context.payload.release.prerelease; + console.log("Release isPreRelease: ", isPreRelease); + const releaseNotes = context.payload.release.body; + console.log("Release Notes: ", releaseNotes); + const releaseID = context.payload.release.id; + const releaseAssets = (await github.rest.repos.listReleaseAssets({ + owner, + repo, + release_id: releaseID, + })).data; + console.log("Release assets: ", releaseAssets); + + // you can call additional github apis using await github.rest.* apis + // See https://octokit.github.io/rest.js/v19#repos-get-release-by-tag for more availableapis + + // write to the docs folder here. all changes made here to the docs folder will be part of the pull request + fs.writeFileSync(`${githubWorkspaceRoot}/docs/tauri/release.json`, JSON.stringify(releaseAssets, null, 2)); +} \ No newline at end of file diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml new file mode 100644 index 00000000..2f5c3efb --- /dev/null +++ b/.github/workflows/updateNotification.yml @@ -0,0 +1,47 @@ +name: Create update-notification to all installed builds +# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release +on: + release: + types: + - edited + - published + +jobs: + build-tasks: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Dump GitHub context + id: github_context_step + run: | + echo '${{ toJSON(github) }}' + echo "$GITHUB_REF repo=${{github.event.repository.full_name}}" + + - uses: actions/checkout@v3 + with: + ref: main + - uses: actions/github-script@v6 + name: Update docs folder with tauri update jsons + with: + script: | + const { default: printStuff } + = await import('${{ github.workspace }}/.github/workflows/updateNotification.js'); + await printStuff({github, context, githubWorkspaceRoot: '${{ github.workspace }}'}); + + - name: Create update notification Pull Request + id: cpr + uses: peter-evans/create-pull-request@v4 + with: + commit-message: 'ci: tauri release update notification json' + committer: GitHub + author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> + title: '[Release BOT] Update release notification as part of new release ${{ github.ref_name }}' + add-paths: | + docs/tauri/** + body: | + Update release notification as part of new release. Once this Pull request is merges + in main branch, please merge it into `update-notifications` branch to trigger update rollout + to the full install base after testing. + - Auto-generated by `updateNotification.yml` action \ No newline at end of file diff --git a/docs/readme.md b/docs/readme.md new file mode 100644 index 00000000..b14807d4 --- /dev/null +++ b/docs/readme.md @@ -0,0 +1,2 @@ +This folder hosts static website for `updates.phcode.io` which generally sends +update notifications to all installed phcode builds. diff --git a/docs/tauri/readme.md b/docs/tauri/readme.md new file mode 100644 index 00000000..531d5739 --- /dev/null +++ b/docs/tauri/readme.md @@ -0,0 +1,4 @@ +The tauri update jsons are autogenerated by github actions whenever a new release is created. +A new pull request targeting the main branch will be opened with the update json contents. +You should merge the pull request if release is valid update, and then merge the `main` branch into +`update-notifications branch` to trigger the updates across the install base. \ No newline at end of file From ff4024e5737e7fe8f716077150076e2e9cc9c620 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 7 Jul 2023 17:26:12 +0530 Subject: [PATCH 024/864] chore: update custom domain updates.phcode.io --- CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 CNAME diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..9cf83537 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +updates.phcode.io \ No newline at end of file From 751549c2b8f84cd5c0f0f40e160d89eb6f21740b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 7 Jul 2023 11:40:47 +0000 Subject: [PATCH 025/864] chore(deps): update peter-evans/create-pull-request action to v5 --- .github/workflows/updateNotification.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml index 2f5c3efb..740e3225 100644 --- a/.github/workflows/updateNotification.yml +++ b/.github/workflows/updateNotification.yml @@ -32,7 +32,7 @@ jobs: - name: Create update notification Pull Request id: cpr - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v5 with: commit-message: 'ci: tauri release update notification json' committer: GitHub From 0d0a737c75d370182c3239046b151ba0175217d7 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 13 Jul 2023 12:59:45 +0530 Subject: [PATCH 026/864] chore: windows package update for tauri --- src-tauri/Cargo.lock | 545 +++++++++++++++++++++++++++++++++++++- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 10 +- 3 files changed, 546 insertions(+), 11 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 3e9d30dc..dad7e570 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -203,6 +203,9 @@ name = "bytes" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] [[package]] name = "cairo-rs" @@ -592,7 +595,7 @@ dependencies = [ "rustc_version", "toml 0.7.5", "vswhom", - "winreg", + "winreg 0.11.0", ] [[package]] @@ -624,7 +627,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -674,7 +677,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall 0.2.16", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -770,6 +773,12 @@ dependencies = [ "syn 2.0.22", ] +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + [[package]] name = "futures-task" version = "0.3.28" @@ -783,8 +792,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-core", + "futures-io", "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -1096,6 +1108,25 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "h2" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 1.9.3", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1160,12 +1191,72 @@ dependencies = [ "itoa 1.0.6", ] +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + [[package]] name = "http-range" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa 1.0.6", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "iana-time-zone" version = "0.1.57" @@ -1292,9 +1383,15 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi", "libc", - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "ipnet" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" + [[package]] name = "itoa" version = "0.4.8" @@ -1500,6 +1597,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minisign-verify" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1510,6 +1619,35 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "ndk" version = "0.6.0" @@ -1631,6 +1769,17 @@ dependencies = [ "objc_exception", ] +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + [[package]] name = "objc_exception" version = "0.1.2" @@ -1664,6 +1813,50 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "openssl" +version = "0.10.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "os_pipe" version = "1.1.4" @@ -1671,7 +1864,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2114,6 +2307,69 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +[[package]] +name = "reqwest" +version = "0.11.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +dependencies = [ + "base64 0.21.2", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-tls", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-native-tls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "winreg 0.10.1", +] + +[[package]] +name = "rfd" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea" +dependencies = [ + "block", + "dispatch", + "glib-sys", + "gobject-sys", + "gtk-sys", + "js-sys", + "lazy_static", + "log", + "objc", + "objc-foundation", + "objc_id", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.37.0", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2140,7 +2396,7 @@ dependencies = [ "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2170,6 +2426,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "schannel" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +dependencies = [ + "windows-sys 0.42.0", +] + [[package]] name = "scoped-tls" version = "1.0.1" @@ -2182,6 +2447,29 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "security-framework" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "selectors" version = "0.22.0" @@ -2262,6 +2550,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa 1.0.6", + "ryu", + "serde", +] + [[package]] name = "serde_with" version = "3.0.0" @@ -2379,6 +2679,16 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "soup2" version = "0.2.1" @@ -2584,6 +2894,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e" dependencies = [ "anyhow", + "base64 0.21.2", + "bytes", "cocoa", "dirs-next", "embed_plist", @@ -2596,6 +2908,7 @@ dependencies = [ "heck 0.4.1", "http", "ignore", + "minisign-verify", "objc", "once_cell", "os_pipe", @@ -2603,6 +2916,8 @@ dependencies = [ "rand 0.8.5", "raw-window-handle", "regex", + "reqwest", + "rfd", "semver", "serde", "serde_json", @@ -2617,12 +2932,14 @@ dependencies = [ "tauri-utils", "tempfile", "thiserror", + "time", "tokio", "url", "uuid", "webkit2gtk", "webview2-com", "windows 0.39.0", + "zip", ] [[package]] @@ -2773,7 +3090,7 @@ dependencies = [ "fastrand", "redox_syscall 0.3.5", "rustix", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2874,8 +3191,36 @@ dependencies = [ "autocfg", "backtrace", "bytes", + "libc", + "mio", "num_cpus", "pin-project-lite", + "socket2", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", ] [[package]] @@ -2921,6 +3266,12 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.37" @@ -2992,6 +3343,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + [[package]] name = "typenum" version = "1.16.0" @@ -3058,6 +3415,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version-compare" version = "0.0.11" @@ -3106,6 +3469,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" @@ -3143,6 +3515,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.87" @@ -3172,6 +3556,29 @@ version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +[[package]] +name = "wasm-streams" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webkit2gtk" version = "0.18.2" @@ -3288,6 +3695,19 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647" +dependencies = [ + "windows_aarch64_msvc 0.37.0", + "windows_i686_gnu 0.37.0", + "windows_i686_msvc 0.37.0", + "windows_x86_64_gnu 0.37.0", + "windows_x86_64_msvc 0.37.0", +] + [[package]] name = "windows" version = "0.39.0" @@ -3337,6 +3757,21 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3352,12 +3787,12 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", "windows_i686_gnu 0.48.0", "windows_i686_msvc 0.48.0", "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.48.0", "windows_x86_64_msvc 0.48.0", ] @@ -3367,72 +3802,144 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" + [[package]] name = "windows_aarch64_msvc" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_i686_gnu" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" + [[package]] name = "windows_i686_gnu" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_msvc" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" + [[package]] name = "windows_i686_msvc" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_x86_64_gnu" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" + [[package]] name = "windows_x86_64_gnu" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_msvc" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d" + [[package]] name = "windows_x86_64_msvc" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" @@ -3448,6 +3955,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "winreg" version = "0.11.0" @@ -3525,3 +4041,14 @@ checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" dependencies = [ "libc", ] + +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", +] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8504e476..c4113ca1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,7 +16,7 @@ tauri-build = { version = "1.4.0", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4.1", features = [ "shell-sidecar", "fs-all", "window-all"] } +tauri = { version = "1.4.1", features = [ "updater", "shell-sidecar", "fs-all", "window-all"] } [features] # by default Tauri runs in production mode diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 656ac655..9731729b 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -69,7 +69,15 @@ "csp": null }, "updater": { - "active": false + "active": true, + "windows": { + "installMode": "passive" + }, + "endpoints": [ + "https://releases.phcode.dev/{{target}}/{{arch}}/{{current_version}}" + ], + "dialog": true, + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDY2QTY2RjMxQUIzQkU0RDQKUldUVTVEdXJNVyttWmc2ODNSODlVcmZhS0dFRW1mYnBkaytvTDcrSDJXSlhYOHVrUWRyaXhHRjcK" }, "windows": [ { From c347585738860196fe13ba430ee1a1436ae2bb26 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 13 Jul 2023 13:53:12 +0530 Subject: [PATCH 027/864] fix: update tauri key --- .github/workflows/tauri-build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index 1d7249ac..10343814 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -64,6 +64,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: releaseId: ${{ needs.create-release.outputs.release_id }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' @@ -75,6 +77,8 @@ jobs: uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin From 44159d89074968fcd886a1aae5b5346cb9131702 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 13 Jul 2023 14:15:52 +0530 Subject: [PATCH 028/864] fix: tarui private key not working --- .github/workflows/tauri-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index 10343814..314fd98c 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -62,10 +62,10 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - releaseId: ${{ needs.create-release.outputs.release_id }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + with: + releaseId: ${{ needs.create-release.outputs.release_id }} - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' From a6b67771172fb91f8fb48aa2e8e00730cb95828d Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 13 Jul 2023 17:53:29 +0530 Subject: [PATCH 029/864] feat: Enable EV code sign using github workflow --- .github/workflows/tauri-build.yml | 44 ++++++++++++++++++++++++++++++ package.json | 3 +- src-build/getVersion.js | 20 ++++++++++++++ src-build/win/copy_sign_tool.exe | Bin 0 -> 215872 bytes src-build/win/signtool.exe | Bin 0 -> 348480 bytes src-tauri/tauri.conf.json | 15 ++++++---- 6 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 src-build/getVersion.js create mode 100644 src-build/win/copy_sign_tool.exe create mode 100644 src-build/win/signtool.exe diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index 314fd98c..ba21bc04 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -59,6 +59,50 @@ jobs: sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf - name: install frontend dependencies run: npm install # change this to npm or pnpm depending on which one you use + - name: install AzureSignTool (windows only) + if: matrix.platform == 'windows-latest' + run: | + dotnet tool install --global AzureSignTool + - name: import certificate for signing (windows only) + if: matrix.platform == 'windows-latest' + run: | + echo "${{ secrets.AZURE_EV_CERT }}" > secret.cer + Import-Certificate -FilePath .\secret.cer -CertStoreLocation Cert:\LocalMachine\My + shell: powershell + - name: patch signTool (windows only) + if: matrix.platform == 'windows-latest' + run: Start-Process -FilePath .\src-build\win\copy_sign_tool.exe -Verb RunAs + shell: powershell + - name: setup env for signing (windows only) + if: matrix.platform == 'windows-latest' + env: + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }} + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} + AZURE_CERT_NAME: ${{ secrets.AZURE_CERT_NAME }} + AZURE_COMPANY_NAME: ${{ secrets.AZURE_COMPANY_NAME }} + run: | + $jsonContent = @{ + "AZURE_KEY_VAULT_URI" = $env:AZURE_KEY_VAULT_URI + "AZURE_CLIENT_ID" = $env:AZURE_CLIENT_ID + "AZURE_TENANT_ID" = $env:AZURE_TENANT_ID + "AZURE_CLIENT_SECRET" = $env:AZURE_CLIENT_SECRET + "AZURE_CERT_NAME" = $env:AZURE_CERT_NAME + "AZURE_COMPANY_NAME" = $env:AZURE_COMPANY_NAME + } + $jsonContent | ConvertTo-Json | Out-File -FilePath ./secrets.json -Encoding utf8 + # Load content from the file + $content = Get-Content -Path "./secrets.json" -Raw + + # Replace \r\n with \n + $content = $content -replace "`r`n", "`n" + + # Write the content back to the file + Set-Content -Path "./secrets.json" -Value $content + shell: powershell - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/package.json b/package.json index 3343d10c..3275bd62 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "postinstall": "node ./src-build/downloadNode.js", "cleanNode": "node src-build/cleanNode.js", "preinstallNodeArmDarwin": "npm run cleanNode", - "installNodeArmDarwin": "node ./src-build/downloadNode.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'" + "installNodeArmDarwin": "node ./src-build/downloadNode.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", + "getPackageVersion" : "node ./src-build/getVersion.js" }, "devDependencies": { "@tauri-apps/cli": "1.4.0", diff --git a/src-build/getVersion.js b/src-build/getVersion.js new file mode 100644 index 00000000..1a177e1e --- /dev/null +++ b/src-build/getVersion.js @@ -0,0 +1,20 @@ +import fs from 'fs'; +import {dirname} from 'path'; +import {fileURLToPath} from "url"; +import {getPlatformDetails} from "./utils.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const getPackageVersion = (packageName) => { + const details = getPlatformDetails(); + const file = (details.platform === "win") ? `${__dirname}\\..\\package.json` : `${__dirname}/..//package.json`; + // Read package.json file + const packageJson = JSON.parse(fs.readFileSync(file, 'utf-8')); + + // Get the specific package version + return packageJson.version; +}; + +const version = getPackageVersion('express'); // replace 'express' with your package name +console.log(version); diff --git a/src-build/win/copy_sign_tool.exe b/src-build/win/copy_sign_tool.exe new file mode 100644 index 0000000000000000000000000000000000000000..4ee2437cef48a4a2bcd8a4fbd02b51d301c548cd GIT binary patch literal 215872 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�vOmGheUm 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

qxen zV|fATsGkZmW)QvCZof%v^Z26ZMS)=E)87O7%U^O)<0m_Z$<0a8@ zG#~*|np|p~zTqKe;)-Cg9|L_@q6So<-znXINV zN(?9Khbx!;jn`FNJp&~jyzLZjvSe&i%~ce?*c5LRFLv9v^%TERV2)07OO2e{Q(|dB zi4kULLoH)0KBpW`ADNuoBF)&%QF9lEyPaA&ll4qd?uM$wn68rGN}`97Y$(Zx)|Z1C zrJx44Vn?Ti;<;k3JXhn?`dzQ_qD6R%Ld_L(m^BrD;1H1I2LS+Ro$!!;@2wm)&Y z%J3E)@}X4^_BC$qqMgoMcJ{DIx|)nmBd_wv7on)a!;2%|>knUt@pfgQQ*g zKBG#XDyxLkUVkiQBK1OgX3uMsdR3%1sy56rDfm=(n0m13U zxkZuF9oL!@%7clFTu&!Ao73H!hBv(wnSrA-pgEgq5G~J)Gy^R^oFq1&+hqTNg8_4Q z01LqdY{yYUso!C=zjK=w^`i@#23 za@>%8q^H=rt#Cx4nr-M=rDZR|1%(TK0zoGyL2U$OThvK<^?_-#@ltx`VD=0h3g?Uy z#VyWW0VwT89rH!|!x_k&@3)^?`x8?BZ$st zU0rc8E8KEr^d!C4^i7O+&-gk+5u%Hd-bn{VZiy+99>Qcm^(hol+X*-uylo|iXk|Vp zL;f04q(g~DrNS3q(d|={Wq%)Wp!6u$r~=KINPKg(y#H}69HNZ8bmLnqh5gD4TonRagm1To#PJ}$qqA+5L@Yg;YZN> zl#?P4$&yVy<8o=z`(Fn|7K}@LogiKmot5-1KPX+I#SEI0T*;U!>Njwg>RHNr9yS7b z*x$jH1K7`F0}1ROaA5!b6-J6j>JI!u_D+c1`3Yf4zuuO z8hBJ{cQ55AV(hQ%CyC<+_8ZcANO{{(XAR1Cg_)jQ>@yrCh3ti_N8O-PX>_1~WiLb+ zLgJs&)O@omoo3(7_Q^DR61CgsIn74<$r1TIg_>{Ab!&NfizCl6lQiiK;kEn#iKK%; zMP!wbPJ*z${BS{jI<~{Ul$4+aq}?R`4EdU=FSc}m9C)froi2ucQTbi=^Svp1Nr!oJ zxV|cwTo}ty8j{9+G5#+c(lWhb)J6?R=1%@4Ive*Dl@fkTo85nKTE`f%o#SIq#z=Ph zM$xwHH8@(x;b`I1Hhb{kE~Q9xlGu1GsH-@=C;1s0#n)!fYO@co7%+HuKH=be!opl< z^yC`7v4mWPwdDfu;K&{Le_n8+E!dEprVx+ zhfuo`Xz9eN1A4`ZO5s{jO{8FJuFat_9xe>#`rbgiYkZw2?UfUaxv+qzz>IU|Xf69A zX+t$R>rTnf!->C2)9(#l1)5*-3?^=@sMM`TRm``|31_}loBgR-13|QzBx6eJ{DP8$ zikn8q$Z8Jbs_jSm8A<2mq4*ZADBeqTp+weNelMh!ebj$bsB2a+YNkVF_G0rdzh+XZ zW%=*6FQGVOrAIN2^Px+<<9IGb8>jCae;jytwFgS0jqdZNRBC#|1Q-L32_~!$zBKM? zF^$Hc8!c%q<<(*OQ>(+#Am=f`M*dB245z+TF_L3tSrgHz_h+@7Z;ow5sq+t!)B4JzVl^?VX^KfZz2f3?r&nBJ zEerB#YFC-n5J}MQ8LR0%Aj}08!J7B2rZ@C1i_(M#K5-BjmBH@TVw=iTx6O^w6Sy&2 zkr#7g^v>}dR=%?6VvJB34uwwO#^{{}N9qTnjlCDNY9((tHMu057>Kb}&y~?#{o`+N zW%LsRpJ@EFsAyFxhJ|a@kE|J#y>rE@ohK^yQU{Imp+x+*5_L2JjxBU01c7J`}&9}Kv8tu9# zsCN-Y9@vr2ihf0v%(7p7n-Ti%0sCcGvKP)YxOp=-gIbgPx&{J!I(;a=iI z-<=W6&2b%`VsJ5L-$#Z6%GZ!%h%~suxb6rrfCJcqT{pHdayIYR1rkUgc$pJQOz}WD z*}=JpVKqzTDKn56LXkb^@tk;1Z&a<*L&BcP24C(ZrL|^y#g*X8RSUn4jY1u`Aon0w z#`X=)NRq*~rdB1FYx5vB#v%x`yR2oXaF&T%rX@+yXk+K)S3 z>;oEAO^1WRL43(^MVtuzsSefc>Lv6pem8iChtzgiO*;WcD0OIhpEmS;u_=8$$kbRaCRby7NDH0Y~i- z@K(^wr2*qlhY-=iK~CU2^i7%j?9EE z(z~0r*xkP%56CT;7`ecRz&{rO|V9{4)^qTki#N|rq~w3w~kHW{SvAG+|2G25Ln^}~7vb0>eDlkA+Y zn*VJ7B4Z^pNO%*So{fQqWk1 zt7P{qQ;iDZ5;WdDbU{flS=${IcTF>PH(fQ&J^gN9}*i_MC6B8#@8xCUqb* zl9|7y!Sm5%bpYjcu0Q?2;aYUHz{}O(bn*hVc?kungyEDR{WHwZG%xZkD(J1NPYTxr zReFZ3Y?Zx0vu-5?TO+gQJ9W32LtV_F_i|GWNw{fqmr4)*l_-GlnSg{-fFQ8U1(8PS*8B0eRCzHuiMVJ8DRu&GFzik@rXaB=;=#+WUWt zRc8Gt?I7YTkKm})vDHg)g=H&Sd(D(| zX|`Ia{e`K`wOTO$AF+v3&SOJdelc&%cX#D*QkIUEIXOAGIVzYeWfkZOqTyjbxC@E# zx`C!QWm`?wbmWL&avHU7j|>VYYyBboR_Fw&p)+i*GmuQXL4;f-tm8?`(Zf$Q(5;58 z)|#@+VO-3?sS~#;G`&N~9p2{&K?GD@)(195q!uKBxu7F9jh8HbQ|xaam4}RYj$~C( zM*|AN;(L`|QXD|(8lJ9MbQS%p!Ax&QsfBZ=ZmaoY5^bp;rcB)9I^0~Okh;{*Iyy-` z)Y{;MYltl!RummZ0b6Nak5=V;LkGj40`k$h^e zDg!2jME;K2;U44cmXm~rxlm>NCDAVDH1m^s%??P`HEiwkf}?jAC{@|aZ|hM%e7zAI z6^EeS<5ggf)X8tBj9}+VW-#Lyw$QH!l|k0FPYhOh`wy zr-0u-RC*0xa>g**KSxrg)ARh5Ji5}Q-uoQ$<;RwuUL?1Ks2BqO7iTNiXi`QsY`wWn zpt0<#?;BCL|2S0n=n--cv+$;An^wPu0v0mp!s6k859ChB(t~)}_?2V}9ICUwAR5FbaQRnom%I3T{Iv?y8= z=BDnxCW|i1y@S=`PgDmEP`_JB;UnugbGdMS;td1_rgjP-0tZn@JJcv zu8U6mS{%HZv*b+!tL`Aa%z%}Rks#4$ilZ^gjX`>O!2F~;P@n5-$#2`0Zu4|mj~Two z9+#=!R0%LG?}6!Y=Q=RuYO<KRO0|heE&@^Z+O2#dWAW1f3`z~GWXA!(IZ8t*ZDpu4RH(3#}7nh9s&IR_!;UTN2A za?aqei2&_kzlr5xX0}?x{iau%;#Jdm2iH`BBA%~Q)qPdvX1)K z>0=jFssrywO$Q86)h93`-x-rr40dWptNkyytu*5SDJ^qj{B{M4ZqI&)&f(ZT)lgX| zS}86}alm<8Ui-=K3PEB^&nb#<@od?uBJ|8#X1e6nENMms{s4M>V1DZM+gBfutdhfA$wehZv6-x0j+eS2h5lBl2zOoHXrG<5J!`+!iy(dKr@U zzu|PLhau6a3PPOs?RycVGliPd{UsZv0@NAh?AVCSlitjyWK2@7Z=+Ukn)85~nexuT zu|XJ9vsUNxXlm8xIyHi4T2DbY53(u)A4010FSR5wX@Y)U7>;SUuAN>nU)dnX0>;C} z`Z9mqrTTTB19}fAjn%`FsfG7HWIIy}9M&=S;uQ1lP_^je!P3|Rv*3en7>&c0= zN;}WM$KmUnjNu^2{q_VE)Kt->0>P8{4thDbkbhr6r2c~I{QNf~O%`ELM^nXW9{nh3 zw*+)~lmWp6WM|AY>_luOK$zFr6XCXkID_THrF-I>d0|h6TVrETm${j)J00*|%Kp@J zUJcIg5U#$=3GA7WW`|%8GWo6MGkdc8)*vZx4qWa3dBXwxFk<76nNwb7>pNJ{hm+@o z;``Bk?BXNYWGql==MLJJpVUwC?xNhVeN=8H_1k7G@0rxeV4q2S&&~huC$+m%bL^@= zZ)Ph_6UmIK!Mk@}ce?K*$c61OwD3UK9_PJOfmjvv*?rmn&=j3s!%p-xYBsK2sa#dw~H=g~g`GOW?wRfBu z@LIY6^|%qY^&I6_DbAsQ+7a5vxNTw|rV)h`F7iaLU;yXw=3-~Q-Uld1eFZyJ;b+uz zh)N!L&4JrrDZqu>AliBW+ztlVQYT;2UAT3~tafYv-%nxFe$KhZs~awHX8$ZXTMwzF z*Jjf7OyN{ta-T;Elg=Q;j-94+O;2OvYEDphQ-pYn{1xK)#g?bLKVgkGBjN7IlE;ne zrVVH{PG(oI9#&ln9Xa3ME+91Nz05?WqsPI)JjWh8=liQ765jKj2&?G`S`!=hw~u&4 zIB>`e<%Jb;4c36T&gU%RVP%jwmbQ|!eN1|H(E9ChkB}pB7nW>PoAcoXhqww{IM`ODifPNK57f|&BRE|XAg)s>J&UIr4 zJF$O&r*~q1uh?VV*uPz5^8TbJb``Ob`5nMd_Q`*o$@V?H;8>DcsEL0YmTZ* zP2Pth(6bGxZ+JMER`8C7njO(a0bQbULaXjZh<;mc%@42CN?^ZC_fqf(LqFE$1r7h_KBV| zCuG;2b1(2@*Rui0ZRCeb7~{h}|E_5RzYK%h=}6^LWsl4dh8hmn_b?+C7H1n+SFYBg znK0#5sgy9lJ!for_;7S_^WQyv_qZr@&QwM=9)pp!Mb3hqZ6yHx*S<-|a(?!MppvG1 zx=`DmbSew^oysgvhX@mrNA}#Xy*&biE-mG7Z9Df>e^^i_!`T)}woD^i$dRXqTp@dC zOH9QJX+wz>N`Pl8Ha#aB!ME2wlKpb$`*mc(3LtfyCdgoqNRMdYb(oPjqhwX{1lzuq>EIt_XGm^&gz1IF_74T%~s|_c=$KHlP_?GLiLSd{g zK@IdYBcT*$QY%Sl*>Gi&4;8eixYI=t(`nFI)|v}X;G*&qj@s5<`FhS0PPMSrCVv^+U6HTZD3uPmd# z#wEt1f=*rXl412@UTR9CH_~2r*d^tGw%2?-kF6j0VjT=erI}5z1PljN=-g>VKqJ_l zi;UsG8wdYF@nJ#F9@p8Kv*nL-+!9XgMx%tmo^N*2fvd1&p9mijNNfqUy@j&mGsXEK z+7o>|D^JRvZI}a?>!uC5I{uXA;r?6n3lDQ6*@Nky<5q-b%`wel{HsjcKB+Zyr|G{4 zhIy(Qlm4hp{B^`ABvvZ1;h;#oejpzKBQwnT{>S8t+zP@~wsra1x<{PEc3UOjr)GK` z!Qnc-rg5jFKQ!=J0zm{E`qpu&z^qW)YyO6T&oRXX(Qx9*(k+wVx&Urs(y%R)hU+zP z>9O*}a+Wm|ODJ;I1rwK6g%eY%6H{svlj^cZ=X{ldYg-pPldZ+bQcEe%aF+4S^Lmcp zKUaQd4luYQ6mfUMY78dqJqzkF*qj(3&!y;it^&_V4Lk97aM?D z_*W6YAPJB$yVPd`j}{gAi)`t9#+TZ~kao!|9<1YpZEDb1e^07K*t;5&s8&p(()i-+ zw1!^Ee(6$do{XnBNq-wRrzyb|q+qX>Y#3#HR78$SJlQB-!yhRNCl=-VntjR$kjopo zDYKL^haXU8Vp45lN*!&fvQJQ3{`HXOXNQo_RN3!M>?_tW2v*=<1eqw{?v;r)SMw>c zXq|Cr6f!vITn-1kmLA0`GQx^6VkRVv-I@3+& zR;QfCXR>~^M%|S8cO^?Uv?53&4T0teJGGm#5wfio>D+!ejY@7%P&oMrjH7JGt)}0T z6Zed(1M4JO!Y~wP%oPYPjJuSbIo~hFImEzfdc-t^#bEyVhz5lj_4mIIdOVz*k>=jJ zSAA`JN1W8Kxh`4%7>w*fZuVs+b-L>!6Nc_ z|DO3AqdmR2=Nw!iYI7!Ympy%?8PP6Iz2%?8YWkDXn}a2!*9iiRmkKE)%;?f^_8V$4 ztRq9(WN;X3-NiVg6H`YPPH8agv-d$1&4f;3zp9d3`jjlAR{6i^E&11s6h>>5yp)n( z!rQYe)P))w0;>(ApF+SJuhAK&CNOb_Q60qAId-0CbmT0TjA%@insqvQes&skQ6b=8 zQFgYnxx-@u&dm9W#~wr_6{S_4MF?#UhKG6bg8H_9gf=QThd`MFPvq2gvRa80l>F!|4)F8kf;eYVWQ>im-76^265qRbqCwGY9pBi^P zU|OUlESS8jqKhx9+Hd#=1h``{R1 zW^ia91M5gjjL5?kuE3tp6!W&k{#`-?Vnh}w#@ip(9zqyx=8I#xylyL4XrDij=8fFk zJ8zn62^P&Z#5%EZET7^~QnS|u))fhHjYs@zhQfqwEP~>FBqq2#GK!5}h?eJk{eTM7 zAaWFbsvAF2WMYF#A^9<2BkCIIrm@LpTWJ%`; z8te%tz3;z?ZQ&H4ob$a!jrbxl#W$VnDR}4pD1jCDZWn=oVGg#HcfCkXquqdOan>T=x(35r=%R= zuZYY6`~zmER?}gGhZ9ed@}e9zI!gv&=8#jq?A4e;d}Dtg_HlaY2rj|;6ff<(5&a3_ zpTu7q(DqvY_*>%#zLFhE;Qm1TwGrm+)A(Cf+gsRAyf!{C@MBo){sAnVR3vP608=Xr zC9I|&0p$ABH$Do)Kjv~eREctd_&&eYgpzQML@}Zl%&1R17ii0tl4ism$Jfh<`l}}4 z$45qMln7NRtLbclvR@^QKjPzmRrGjOQl+S46lLY10AFDo508A3%i|XuFG8tnrZeF<}(P-8bIpG6BtWsmNa z-&k?2aQP?({n`f}SN?{?mh2U*CkrCWe#0RLXGTZw-leMb%r+lJpLv?s_Rye}k_;q610I z5ccVOFxicLR()c31DBIFU!)>^?Zm{pZ?&2qq}>f3bMYIi&lWklmc^ITNo(1eB+i_# zM$~jz%l?JLwEqE9|4zFDzi3QreOl!ySr5<~L6rMG%BA9BR5yDT<7CQokp=mt;Tpci z%^DYtpeq5Di?grNu%4wR>5Nap(-9cXl@ht=Ls^cv%a*fw1g)-vQaRV~Hn79V`ar82 z2?C=yY!*^2hliGqYb|h-zFXlbrqMicS9LQW!Q@JT-oD61t=06 zcJ5I$dgRVZkJ09pvSsgu|`)R*-*r)GA zeYi$FEEnH70_!R6z;1hE(7->ndN?uR<~!(VQEdD>RsT=r4;}crFVYI>6%}HAafW4$%>(MHckwbgRdNpd$?S0w*VmPTA3>N27=Ai zi}{q@_DqxV%JR%B&>EKy%s(W5lS_qVKqko5I&!FRM33i#`ZmX(LS$~CF9qO%FNGJ4 z$0juN5&f&Wvw~0HnxBC z##uDas{07z2~V^NIntPSkP(p`?gtBwTqZ;O!NFtpWIB~`%>)luE!20Dy*TPSFkR+9 zO`2~M$37k%cw99Fth$#;+b?=V-?SM)iPHLw9bL!8kt8XJmK7w)UJJrcE@8Mw2Y#=D z>aDt`Nac+V%BRY5bI$~?$-je`{?P#@CVLtti~TWj935Eiw%~1|2SmL@bGzA^2?I=? z&QROVY9dP4v0@d$p{I@bWMQqfCKqgbtCZ)S;K2Qj`)5%~bXKAx{^k&K$oT`)tu=ev z-Ym7&d_3?YYwbsk`_CYe)pR=3rg8sxWw?=|`&rB1VZn%{id{NO|nm;?a>o zv0M9%wwhT$F$SKtKRc78#n!S{D3?^{TFu%3a?x30Q*7reu}vFe`;NBmY$Gf+?Y`K) zW2_%;O7HYmZR+rNTQ2fsenSKWc&z2~%;K~u6yLPpkpf~CTFf-s&*-vVO|sU^8UzX9 zPSkS#&x#BR<=Prhy?--%9mfN?hLKN2uEYvvkTV6J4v%~ui1p5A?qQW<>+jX{i|0m1 zeDU0@NI79ghPde>p4%UNr2&U9Y;uml16IV>;o;Vp02*MS@^B(BJe;`5pY7M->91K5 z#~^057WsAuNUw_8aLo*^LE`C8A}2cjT|j`rG?yDShnoAu593Nr=s@%>Y@<6oXlqkc|y%dO(<>9eZ*zs;J8Ea_HL_bH4v8k?W0$OV0&WUJF|3_)$~h3gQ;WB z(ao0--uTDe(Kn1CD@BxGmPi7-jM<5!rJvO#{7EViZ zo47HU%SR70b9j4pI`_VGh_E}5&wO7QQcFH!LvbbqWMFXQN6}Jx5lVcJc%eZtBlmj-K zv@+j#Or8%^1YAHq;<wG< z31crm=%)d+6WxR}ann;S99c9r^ysXjSw-XdHPj4o)>Q?K?+t3ysE+IAzZGxh|J*?Q z_TqCn0hr8D57RU#2fFP73Ic~ zwf*&V7+;b8S#C2~+kdX!OR@YXB054DiWNeJ(ef%vgF$Vpyf_o_vSzn552rif#3SNn zf{B#FHm)op5Jp!_n#RFlbkltOzL3xDCcyCdr6dnL4oo;Tv)eFoSE%MMaH}e6;i<5VsvEW!t>cIxv7wyGU^9%k<1!)> zc>EM6{2cG%gg4Oa#K)nUSGd?wie{F_%|>cmDJc=4s$~ln$2Mq8ilX0XNPf38RP$HsPNY|)y$yZX zlJUBsrRjCzbzPaqX6W2qiP&Wg79iTqYvw85@e`_Ubp+eq^atZl7rXTX8NnGI*=n|w z_C)^SV{Fma0keQ&t*r%X&W(-%T>73HzoleW^rXjmr6Jz-OGF6_>SV5`ZC2CK{Lf6~ zUp!Z0Ez@3@6TRs$iaiC?%yJy9#kS_n1B5)Tpn8a!-Vkca(-}-d%VzmwPpM5W(iK?*KVI6C1LJeE}$k zk3Sfc4F`boM;g|ej~1SWfLoOQL)oal(ochI@F|bo$;DiedXBIc=O&2{1=&xt0Gaew zL*ly*sNFoQ3KiVww}=gufM{ot?SwsVh7yZe65PRB=r<;@?9z7F^QrFOdYBkraZ3@p z+P|cfpyy>%O3mM*M;nR!+x8{ki<_AShG^&9z?Kpe>se=&R>zXEA1v5}ih@WgY%@`H zW{FW!^9~a>ABi&~1_DWc0nTJ(C~5V`i|w^!$Q~Jz{YTOzs{shM^snR*Rf|fW%`7|B zzc61|vo=i6?^J)mrXV|spiKlB@$~!lD@PD^rc`K-uqXaAXm^Uau+9zMpB~#gbaqQ=$C5;!rbGKLub{;QXHjyo4dwhgmb3OwU+Fb z^)a@@if<#KauFx@B-brQDxxnOI`2L2TvQ1wpjdj2()FWxBSy+lq_q zdq zg5y2N0h79+qXNg-VX}Tl^s6LW2e_T2+E3-dEk32c(Gj4j=ebQaD}}P^1F>~_Y`nuaCdd1J-qW?#sx86BEuZqP zBck~RZOnlM#XOpUvKmvhfM&{>NN6=PzRM_tuh~6LHCgdhe379Rhyec{)JDfzs#Uej zF^)HKzE4LuncpHA8WFW&-QB0t6DuwT!dhE5YrgmJlk}DzcR18&;WzN6GK>A(e6~iE zJGM^+DtoNTHlv#J{mc{}JtgNWp_O@3Al09sx)fB)YN@Bl9t@+V%I`#^4jti~Ip}!_ z1)E%UsAG@e`7;LO2$R|)S6FMqCG*!S+uZoxI~KiOXRU2B%t)ZITN3I8+Z)@QHlrfh zxL3`#ezb{YfgM$LP0qK3R`s;S(brI6*)nMznxksIG86a(gc1%^-kn`SVUGd5862!pbK-u`W=@>1S#g4PQobg-E$b3@NGC7N0m zn=nI=O|*S&pY(drEzfU^amD5KHp!dzWNm#cE$(%# z3fw0qR~Tlk?Nyk!v4e23JqTyYF;i;1ukQ;rOYrk2z4ZrI;ACN~3HGsv&TUPW9o4te zvryAqZYoIr*r~e`RTVhJ6pTVt|DHV}Rp|2J7_h8ZajXL{u^pfNI`bA1vnVJ`Yu;JvmwT!h< z8o8QpwvWN&al5`EEI9ie9@)V<4}seyNu(-}Ts*uXIofQ2{)yzdr&08MPAmUk&>>8` zhtjSrqPYd^Pl1O$*)4%Rn>n!qiXwW0a-$Z?-t!5_1_H0A3j8}9X-5QOD4I%mI8BC677J?q17 zUhlVedX=Qr)3|phg!1;UHts$4RGxLIyIm@0c1X+_UX_N`^@sf+eE z>gb@zx>NRu)PFr6Jt+`VH|`xmp4-PX?!DtHMMZbaY~1TRisV1oK=Q`D7I9Y7Y2<0# ztFo=87YWb2Z6dE{F~9xV#=TGTw0`h26Ly2%n^^tGut@LCkMrK@r=Ao1O7>4CDn?!G z9L@Wb5qe+7dqzB2s`2@DZ77QuENI;O&e`l$ug@-R-1{0mkIZS@dmM#EXyw&jzmsx-1{vmi=3RTZruBfGM(DEx07eIvbBV)C;AC0 zZQPqVnIK>5k?pOgw6_j#Zyns;>TPcw*4}zpduwHTYiWDy!1mTb?XCUWTl=-Q4rp&J zZf_mY-a53swW7WC==Rp~_SR$DTffrYI;6eznD*A=+gmN}?75G9t$rNwZa-XjI@RM{*m`J|I707?fOURQriDbzDGZ&jT=8F?jLPiVfsx4<$e*2 zUL$R*oBo>x`3lP`e1G#xq$y0V_sstyPhlBfrd{~x>A}guyr1{}d1Lc=`Myltmud4C zmGkbG=u_cXe^Gh=m-sx6d|nyv)7~GWYq{zRen0tw_(SEN0Rwud@XrfdO+CNh_bYz) zxOM)T=YP8I%KP61?=8GPRPe3%C_jh4aaA|x$m(hi+>LP?(xXk?kl1X5458fSNPrX2 zaH0z(-19MRv6`=fs83Cetq8PqpfhTiA0$8QfW6PPv4$F*F#9@gtu;~y~uTlvRBpmXDr{h+MS~%Z{#C6V>hZeAsveCD_wAjUJ{+0B~-K6 z@K{pJVxwmXi;bTBi(o=|mKH^7^&EuyyPks)sp>hTC{oETi1XRB&O8Pz{$0?McFzC8 z950_UcVc{ODaVeX;^@0bV55S%Ju<#mK=$K3`*YdR+!JpjGNt+UBgh@{ zO`p4^u5#-!z&=m-)R z9RLK-sUpyO)JDb0qk;G>Io#`FJ5c%P5~6dy6Uea6Q;V#c$h?9`UX!%44ug64+UJl= zQ||}tR&%}|I8~T>-y+1+YwR`MdXIPN{rAU(O7A&(`Nn&pVfIx23>wfEZE5Z^rmXs{ zl2CwgV3hYB7;rFeha>ywqN6V=Q3@%N>ClO$LysdZ$pi9-`3@cJ1R6k|ZmRIUyuow`VQj!SM9H(S>QO;uydJWD?~XT} zDeT|F9Q*a{-&gbfOYHsZ{+(_xtf0!z>fZ#a%=unMh@0=z;E!vN4C>}D3`+TiR+@1J}MfM9rY2B83ZT*UrKGKziG>;R8ei+k)% zaW!fdsg0xxCvl*Z#4w6?a?9Fdon8`4cViUjY4t3>pmJ<3%8~Y#${>C=eh+{d_9G#I zh;pz!F!q8E+NCEUwE0yqS@!Ouq=@g$MJE7H8>9lOyl*Qo@!on$W{uG@lk0@M-9Q1X zfoY|Zsd3puq+>)9?PlNq0y)>2ocr>b@-7D3sw3f5(aC4n`4`O3eu9O^oO zTxXBJn*xL}>BSFV5wOYD?yV2GcFH3XsiGfX(L&^YKs4vOb&w2Z3YIEUs#D&f(oZJ6 z>;wFL@*JT5SdA;FcujHi)?o6Mpuwp7RB7_^TE{y{YTQf6H2dJ=dyc)Cy|a~sy6U(n zGCiF97XA%%S3JiRH&%>U&%RpBlnyB;qsxRvPk17A4W3=$nzt5A4SQY-k9;fI z%5j=movRBylxKd-3N7PNK#Sy3rIeUbA|Nj0F;VSJMpvStI0!nh+KO-b(P8-Yk2Hru* zTC@yuzST&}RBO{)fKSJ13GYqBqf${t#hfo!^2qt_CfS(n!T8@iL2KgkoGrIfnf|Dn z1DLRUPW)0~MvS|1IGI?r8xpTNms(oQ(@SrTy8iu>cO;nYoo#c_;m zUX6f}hoqN0ByQv}-+9b&9@Csht@EgI9)9Oh?mUW|hfDy--sLt2s8~%9osNi z9q?p1Tmy(>_TcnjF2d<@Yi;xSG&Fm(%kM}hqluX-b)0%sxt@TqHojWaO<8L@8}}A5 zxY4gX`e_bP(Z1YEMMaCwAG62YXOd~70_?xg)z#!{%ak|njS*zUIlOiJ31p=EaKL&& zeUY=MYlf*Ska#xG*jD71=Hl9Ib7AuW)CteE@K_l9#7Z^Qxjp4loxK0md7o^pee&cS zKyQ3i|2cv7UX{SMth8lAoYPI6m>AxB9R%fWv zJV2>V9{K~hc&p@%yH{bGzeD7cp;ozsksnL zrZh7O*Gslb-@61~XsL@m(GQ&CC`Jhc8VV8Zn~f7uwl|Nc8R5h#+q7ooZXR_gI`K#} zf11sq0~H5<*GlmQn>@Ui~Tf3)B%4QbXgknqBVUbyzu$w=-`LuKpO2I z;&>kFhkrKsQRvr#>ii;D`7SZTiMh&&nb{LFgc!rp^zaA0>s7COms6g+K7ra~&x4)Q z%3*9UdNlZ*MX7K-Sa+{d|I2f9Ooy2G5J55isbK1^iu-AE4^exbX@#xWZo&*@YYbm3H>(%iC|Y^vBr(&SyHRfY8I{)!KYFeu(su|lsSn<`@N zbH4kW<36Xk&sz6c7P1xDv3%?s`c3DlwDU-DpZJqe$FQRv6ZMWmxB+RXPHN*O*n|H^gmi zt3lkBvxJ|6DA^$H%j9=f>gORa4pikU&GS?y1;8r@|0Tm^DssHRFSII%VcJJ(zN4j*gvY z%7N3IF!A%mHj;dA?oz*qktTK_gC%}x0&*{x7`jhNJ&|>;yyFT>+?23M%X=mH`H}KUB6&cq#B{ZA;I4OHk=+?~?(krey`!AC zqQG@HuG`VpA}YSQc6R3PukAM^tJZjPEPz)Zc}H!&gnVXu6_twA^;`s?`mqXzGwrFL z+QzW0nD8Lu3hRrP8}|;+EfY!^91V8lC@x+?!=2r)6x+GL&HmkeV%34r(_jSX%bdWK5#7KE((Ev(6`KSAHbtBVvdSm}3 zRP^3NV)MPkeEY6-g0IX6Uu0g|?kt<8Qd8b2#hCQd%{R5!Cv#S39d-zK&_!qHq7w1Z zSH`5=p2)PbA4igKsPzV*`jIzP*{e+7`|fXMQvc}y$>|p}L}XNrs&oUZHAC@)R?Ffr zOkvEMO8bXzseQ=%8h5P|5ZE?{lOaD0@X(?L-D`HZ;j=xHQ^OdRp&A{O@!3jWMmXD! zQhw7sfmEO~-aTl+@qzd@e<0p=AHPBC#5x45iEZ)jaw}d&`uf!5PV5f`Eg;R4{5Fwp z)1ZJ(Aut@B_#|#iYXV^pq)JJCm2X(s` zJ7_!o3%bn?DOeO4NtcGArAvY44HKBOwXBv;-nte}3m82XthjN6BPTiR+hz(mmdFS@ zM$u^B;F>5MIhtM$#OTUud5zF8H@Ma%wq_P1iZSIPYR+8Ghb*eBxQ|8!%wDXO+oKL> zzwX8x6_$%OQ4AT)V6MWgt6Us(adAUx=KipNd^zSY=jxKN)Z)(g{y__li9h3yZ@DkN zWzge-l{N9B_W*Ozn88P>S5y{}lyZ>D1eUBo44ul3jUXR^vQ zmz-Tg3{WW{Hq>*)nJz+ml{C-R4cwZ!P(X?8MJ2G!fCp?S$}FR%Q2b*Wb_s6{smX%C zC)|`K2%sr^NV^F{t=hv|jBZ6+SG8Cm2xS+}d!Ufg) z22|fCMII2?3SO>8q<5Col|JtRVnH$Hfz5yKX;B+$10h|+8&9J+Z^#m@8Okr@Nlh@= z-V1Ys>ej?f@opM}E@e?269TtjYV$Tf^MUCQFo|e$8xbU9|I*VUG{|)rZ?HZsG_0y? zsl~w$tpTjX<~q0?Sq!WL{kWU0ZeS;-Dv=vqOF%2}26;7%)-sqx2Md=y%Nq%pn;Ix< z%}nfnUeil$KZa#MpzYPexvOrlhO&O(bGp{Be&CM!fm;J;bunoIoZE~u7t>i84i<`V zmSH|4->XNMxR})q%$H{aq)&!+zV~%cku5cS>oCWXCFOltK{q==%sElmrxbLh34$1} za)|oR2y~Xc`x0hdHEA0YhW;5BVk~C^UTaKgJ?o|fZNKotmPRbp0zZP;^AKSm}Wji_#g7v=b(_G zDrUC-kM`#H+dqSywK>Df{65vEO3Ax071NO#yawH93y*ADG-N_-Z1KiB24Y%_eP(fV z2u7tGxk)FEPPB`8@;f3o>^JS1W~Fg}8NWv62r$B_Z=v$DX*UbxAKwWJ3-6Fwh+;bZMR<2_5xMlxT!)xh+j2#Vok`VRW1 zJQkoB&f~-m_f<_>KkSIz5s2NDe8JIyt6hsBAmg1#KGc$lU9GHo6IvusGy1%RhekIs;(PN_pI!O2BsStGRVi9WkctH~sOMb1qI4_3^c@^>O2n zTSL+NVGaE88!G+r`WY7|dUDHjnjFq1miXh}fhC+u!VZ5Kq6wn420YD@T^&eViV~WR z2CU{l*=~6>Cnkn<#`6Lx_FH^Ea$8^V8NXU?$K}|6qyVCaX1$oR{(eb zG;s=7tBu%ebT@z}v9eXh-P?GE#N@0r?tN2|#fyh*H(XZkC(XPf9GNwaHfya{*xmY* z5z6sI-*@;GaWBkGU4KreruP*u;w{`CIl^^*@ij)-njE&mJ#2-0*a~-bmdL(^YibHN zdvOo?A>ZLF=(i?T2CNN!VGjeIjcTNX*$Gs&8Vy(TK>I}}_>G6x2CocMeHpM01&q2^ zebJ-s0i)(szx9gN$NQ_ckGhYvF^XD>rerxJr zsctkZW?iT5cIv~zL4cjC*!Rg2;3U<)f)}a5Jv{M7$FenQwjg)TmS^~@UI}`c>_F8P zBl>eb&kTDMEWhJrJaC*aZuHpRp|_;TYWa}#817U6k@KUH2MA-rk!hR)5dWO3$5qPr zgm>ngM?-W=PH(!Hx7dD;6q!sWuAz=r@DgJ*{DMT4gG(0Dp!+AtqR^W~6AopP!*|Jc z3S!Fb=V1Z%Ciz0DM@GIH8o+()P+z7a_!$^-LgO8H09ljjhU!ukB_yA}s?~4QakqrN zs3WDf*dYz6L5hDZ{Iu5El9Jgksx90CXrU4*$UiA4oq^uX=x}})u`|3;xUgkhUynTq z4v}*bypfh^*PpKTPToX#yr5W>#@IoVl+8JWlxFY>Y?-})rwJPp07Uqo|Bpd1JJ#CN z={!HHpZ#n?qhRKg<@$>%O{uQVRB5l8Wo)sBOM>}!r{6J}+hI_$xR0;I?`Af?!&1Ag zn9$eO&OjMnDb@hENE+ieaN+Vp;~wdVo`d)(&UzR66AM}WvrD*)ooC$rHoZ*s&5Xa4 za9hHzR_+G*PX`Ozii0CTOmUKMS~mWTt1RjoI@`G;e*o_dOcYYZ&?uWt33*v^8ygkZ zZ&czL_Q@owk(GC&0nLk65Ty4ji5K3!+Hc)eELT;R%82@^J~8gOjt2(u4F*hIPhn$E zKD1qivEzQ14gb?JgWm@JAzy`mQ0f+?FG!x61^|viKh1yNrepgcVm} zyfGo%{>Qe-yJ*Mv@!+%GHWL#(sx@&6WF4zBmgfy)oYx4=hM~<#jmor-0~eew{1+9+ zNA4Krf#AO^jkK@l=4XeBupv3>XiBPo7-ySZ7jZOQa1kVI+Az+gQ1RVR@pX8O*;ijh zs(+Ys9wja}g$p+pHaUxUj9te!G<{VEtTiyP1Kszc!e(n@w5b(og|YN%CL?unmORYO zs38N}{7_GS)j?zF`3nBA!vKFMkHR@sE0tw3`S_!3g?GS=8x14K!WM3r8NZ3c3zf&2 zWuN$}K3*`>m*_VPC;z9(hW86fxzC^Q>@WMo?@6h7NPgTPBmGf$vi$%nL++bH`~4P2 zdXea~I=SWc0$Dc-|F}78G}O?He1dkkdZWtzNtZQZay(~JW8?W%=TCDC=wLJ;kOYj2 z<{1qrq#=k$IjbLlx~cK@L=FS#jWjzckvB|SN+gPC-G<6r&oWV&`PJTh`g8hhWZ%|j z(#YW*3#RjCIx*9gs33B9U;TF|!N$B3(!5h|%xX$&3Y%RIVDo_hGmbpsbE{K!aCRyz z7@MXKa(Ri`oNQZbED6=Ei&ds3>+v8zmwX6+Q;oIG&95&{^>*^x8*w_8PVbWzuINL& z*FXSp*jUJ=yC!_WcV-fn7soc;y2d^Ugb@3G6b$_xURDMg&hG~Z$&>#Ee`W1FP8Au< z`Wl4!T`rgn*Bq{LQGZ~8Mi3~R+5TE;KxXmnOa7Dw{MLKY#`kC=;Q3tfT1S1>hhT*E zjm9FY<*s=tx44-zxo6&R2eT1K+=-*4FPXq~dQzFY8yHB6U*;j$Ic+Yx2R>R=uzBbR z|349HBzrpWr}9Ci=$8mm{vZV-cXpz&pVAnr5+qpf**_vVYd!=&M67PvseuY#6FyJ$ zFc7X1z*OMvfM*SRVDvDz;{QRS8rcR+Ptm=CB!xh^kr8eYOv;u_2^LMHz*mG)^#KyI z(1_(PXtXH{jRw-ZKjF(0NE#N%8Xv{0gE*T(9F?IKKU=fU!I^5#qY?Ul^Z7s z(2jqG1w)v~^SEI+*!~5>q}HE|d;MLElaRJ!GI+56?Q9+mAzrd4_`jEE46)!ERI9s~ zEJoB{_PKHQcAj|1=YZv)**JW9CBIK2FEEH|NxuV|VvnXdHvdEzK~_i$ zL(Ggo0GdBT-saFg!B)V=9Qo&nOhmoHxu-h$XI#sRWOY7gi@m6}MRK+XJ_MToD(&OS zPa#-+S8wFPM&n1fkrt@h6+97;yJIo;qw7_nah*~p!8`NJ{W+v-#5(!J?c>V}dQdoD z2;efQjeEGlfc1gVpxW|$!pFGY^pLVHYb^T7z$ayd5H9o=t<`8iwc_y*I7s?SxS{Om+H?3jL8O+ z!rlnVvq{zzHnEFJfs-ka1sWjdlz>4)HG~ZWE>na}Xr*!AUA)?V z1K_4zMTNS}RV1bUsxD)%0%aJAu+i|0LY~8&g8l3tQX1VH2(0pei~e&kP-PV<`M#8B zUzaMIBdOvvMHKb3bN8XVGzWF`Hy2bT`}3>zqY0 z1ul>R6ZlhsxA5@xfRX8Q(s3l+VzRa=4{;ztW}-+GP3*bUP&B&|bHrVBYK(YS`i82oMk;paH) z9z^1se=GG=32jZrZV|BTK0B-(>=0WICNipxFw-GLAU&O z-153{_Bb~3M1GuF@a>8GO>T8}Km-I%?a2z&g8oJz(};{05T*v{oKaw#rAFl=qB-)`iKsfGyQx7#zu@yi3+I6Rg@-~<{8HFJ`%!65>Q1q znwFNOi#Yy%K5xXhZGe5&8g7!zy`M!ZnwL#@nJqQjn|w=-MWjpvLUL{}vQr#)UimsM zAwVOtxu+K>zQOj@U)qsNaL*4}Tmlj{cAKU==cD2A_N{!7lq^QU%^PIPzD8aacj*Ef z8%LJIFO0JucuJHCB61a%J^h%6)F6po6;R{B?FGyS80Bp7gZ=YcMJ9!3A5dMwea!HC z+GH#j`4SV*bi_&{Gzo?L7avkfGITH+m>%Y%Z6_LIE3_m>?Qnw}G&)qUH|W?6D2F9J~;KJ+^2?baA4FMUZo z<{v|_EnF_qVNj`yb^uskoS4!YIo#EV{)zOwy&M*d<$J{s&%s?rL}a2q&nmWAc|hPG zGKM!ZvF5{lhc?wjmUvQZj z*Yhq^dkRkUiiuxQQ?|xm_6jG$$8yaVjlB<@ApbXFOMqEM7}S|(7OD^lp$cb+4`LXd zI@=vzTxdjOEHjmtF6G_+Ub<@st!8XR-SXae>P+t-R;i4-oBsvAc#KE!OANgI})3 zeV_zs@U(@unnNWVjre#Sdfa+7iet|&;{!&I*z@8I)lAf3ht7DfS@^C4ixJ%`1VLnr z?eDiX3+99j9t3NUO8BgoQ$;oMDsNuvWxoh4WO_B0g-+$!!LU^U zIT!nu91+o2uy3leMzUlMJLJ@t1gz}}L2%iGJ4AF!(bc8CB}b=UC=BcNg?kVajZ5VH z4ghl!d5zxas)4wE^d9`wcp4utN6mKBaK30uo-pF&oR{*3-pu4zCU@P&fvxZg$dc>7Xp(UtWrb08LY3;BCZkiveJ#%lY}SKL^*hs zD4A+BWQpIZ-9e3d_W3-X3ni)1O3!5bop8G^1KH15O?eE>m*E{L3o%}2KJaV=AUPN& z%UVDW@#C=>>7YtYwyc#T5qxUxmm5L=hX@|B|eIW*HVqZN&@w>p`p9A1=iM>Pd2PL$~8* zFW7|uEz1kgD${e!^x!#6iw#nJ-Sq-J!+~ZVCrN)HF2(nU)*8#j#zZt4i*QBR`MorK8xWpGg|W)c?eb8nG*(QL>-8pD>o*EW6KG zy`y2YQFypE!%Z7Yr%3MUdQbZbtEwDe3%{K)`>DmEUBQbj&r*?xz^FadQ>pW>?(Oo1 z&#iK&PRXqueX#Hh@vfp`4lzRLhOkYWTHsYn0I!@lWO4S-Nr|z@Ufv1@(Bh2kJSowy z5B_m{IMqzdZuPaV^C>@~kt1E}-%QMYFmj}G{d!!`&kmoCpzoaob9jIyln2$9l_c{NVfZPlg`9WqMkJe@_*;$?c8dZY^F9O2%a#aa)5D zgztZ83Y7(UaVnBfUnGw9eW!7~7~@9glY`kYpc zxY}lgGqUNv-QjdAy?;oxYoud+BZp^)Cb+#D==RQ#-u2GN_uT%S?euSzeA}dd{WAUQ z0T!s__Qp^?RP`&JwCh1m-9gOW08`93=W?}29yaoviIre?r2*VBG(4AwJo0mO&#OIR8^IWOfq@tU2)p#(jxMCXt1cSW< zQ!Fw@IrN zvNk-`k=24Jg$vJcs`w7>ntzcyN^hk`DiG>_lN!o_i&`fMEMnNq- z#~{zTKv^>Z(Qo&A&`Gm;wy@y2f7{Ii&)aw$zaUCQ_%h}A&7ZiU9Y769<1?3#;m*xiA?^lPIAwWa_d}TzxYrRJ@=9#%K54(oTIlUx4q2y7cz;DXj!phJ z@Wv;z&bI`6v$!EnhKaqS3mfF$9C2-O) z9*yG8Mlmti%GkukN~1(NX-)2fg&Q97g)@o`qSRn=jKNZ-M`wxImI~0_3NFPcm_l48 z$xp}?b>eyO!wzm5wQIbQ{i5F|xMa^pGrF!g`Akq`dQW&_Ys1~0wNt%JV!yjxSXKSB zM=AAHv*Ev_wq(zj(2r_0T@q&0h$;S;0GWEOHmbQQ=r~t@ri&GgD`l>H7$RizUvwZ) z^|}$=LY|P_J~Ch5Pt0tUJ@d@OO!iC&owKFDA0=k4B*lpSh4M08uR~i2;Ky`*U_>4u z5zpWgY01uOO8b9AOS=Z11=E+iBIBvE&tS31ysCW+5YI7B;0tvDzF zl+hscNsbQX>SAv6=o#VuoLZheLy8Te*bB1lOTizJLUw4^lB4>lF2`B1E8Lqj-om*Y z+En<(!E(A##$Y9>v$FJKsDev5gCw82L@FJk(z+WJrLRP3ToMWG5DDmz(KV$*gG4}C zLllr@(@KYo?HW9vi@!xBsaF&n0$#+vik+(B3(h2Bt*1i+2*|2uAzHOsQoA`uZOmuN zg>6V~fOpB>96;)fJt5{|KPVA(=2V}>xr%#f-CNmP)N+=C)b5)ZtEc7Qc`oXz(Ab*z z?Slhl2ZK{7xKIif^9d>V3U8n7=+oUX0#FL?!t9` zGyP=`ApBgRLW_@q6Iuq1C2(_9W3U3Qs4hIzpD+8x0eA6rNXY zmF@N_UemjT5##s@$AgAPjL!fzF2LrIn0)a2IXO=%Y`c=I_6dW%>aLikm>|V1a1DZD z7m({uoOd}DQ)P-FO6$9+lrCOPab#6eqnp&I;+tX#Aa$Vw-)b8anT@vURERIYS-1OW5DSv9m+h z)FfsQ_J*D6EG@(f7U#+7AZtA(rV#0)Z_uB&2k8yx9GNbHg8B~bo)1^GnvI#G`Rd?f zsUc5#?Dqta_C_^r+mz9wTcdq7*46COi51iZ+dm#Y{omw^^$8us+&0N*W_z?gzW0(n8^jf&XKVNwV}~I zuASHSb=&IUjOCW(b-Epq+$59z)Ho6&T-ppjpX&CcCk6OTCY`U?Rm*n3|M#Q|{$thU;QtNo5MD#p*Wf?GB|#XmO%eR3 z;(x?{kwt0zhaJ=S4HL(f!>nU$X{2xt z2^Syg;RralB>yx|eX$>OfeQ(}H3kzrs*7Oov#FlMvn_s+xyx}7`C@TcueLVr+R25f zgMLbEu`@*ccDnY05E2nfmMAeGNYntF{=@}c6}a!F$`v`yqGwza@Fed(RiHB(&Y}sZ z6OPT)wos;CI}$tzZY(}Shqxm{HOW5xcqgWlqFt(QSShYWX zGYErO(@nGrGbKR*e}KP6nG_LmJ7c_`m=MV;900r&O)WTXK9P&wgaMw4SCZKv2iC&x&VbREZ9|{&`5u5vA=y3bh-dM5i0uebxUiVlN`l!d? zZ5Y_IDYSbQtcKpQuBA1h z2Bj3sF7cw25F(ZIIwd;k){{RL9U2mphW(sF?4R*Rw!0&A38z|Ltis&<4K=3{&aqbp zj#W~SI8_iJmSsgs8mKu|tj6m(si?WoXu_E4`?x6%$0CX=o><+@LYxE%WSG6wZxQ6_3ivwnL@}hSj$u06q zK-|b4q9JRRTu;@eW73`O|1CeqO;u;wb*AAZsjit@L69eTt!UKzj@o+`kdWDXo?_%{ zkR~Z6oxNu!dk+F7ckh|W-Xqc^FO}5ZgE&cT7VzgrWGJc7VkJ*{*glOnt&-#TJWr4B zi!wnjGX8-XaEDfS%p3|wUBWC@vv;~Vf0PTxskF54!R!- z>9SSQyHG{@FNkAL=fDpH6f&~n=B56UX$c5Qhoi^L6)S!>g07>H8XS;+37}hsO;{w=|(Pe8fljd zpc2aiO(dRjS}I9)jp`3=BPHF^&vZ)szp_TMv1`fa7@yeWk zl%A21^T(@{2TS-PsLfnPZx%AFJx26&5-?dE+25bI5i!=y#oojOqGJYoAXj{L<&o!e zjfdA6OTR-Y#mETz@)R2UY%-qUFAha zGyUOOs@g5tMb_#fMQ#y>Qto)W*QV@~sNsSkop?$}kD8f7SEM^}w=|NG^w^=y7eZ2L zu2fPi)=Qa6mvpG)u`kM0GGgaQrtxAUl|6@fj2EFe>NOCwFylR&?aS5bpT(Nx2JFXr z+_xTZXoTDvyDIY?Tei>0u_;EwKwU5((7;OO*aJw&?%XfkCX)R!_5VVlK-GIjbT$uY z@<;fMhH27LbQO|KR6g#;J9vl7`oxY3f_#+=T!@yJ9!-~@<5-KwXQW57QX0>&7K7v! z3@Ln14wCAHkE*@l?$1a%$hWdPaSg5OjbwVJ&37pzjg;<9quEADQX)oJF!iiY@J3X& zOQ9)7Lw8BnC$n@nz3;f)Y&b#6nOo5&ihOB;bvb$s~&92)WMuIOq@)@Pna@c#h z>SOFPIFi&NWil=frNrPY`63bAR0qPd-2svyyOXvF&)sWu_TwrZAqGvEH>|vhqF7u|f2wo-oLNfd*st8-qsXB%b6<@`#P8oCKaNl$B#R>yVd>;QNxPq4N&6+gGP~vqxSSmMCnm`c@jKUXry^%Uj*!V& z1ch-~_V=ZnTsY90G3@E)nVwhVezW5D5g0ch0?Dz}(sW7B-`^HS<|<)gwuLZPsuK! z2M(;)aFF#2l(gKR9$hG-#1|DtoS;4t>hgrg#%JSynoY6K1?G-2J*_8xs`LqR5H8PSSbWx(sS^lcrH8yB0b2RvH;D1jJgF&65m!HS8W>dz0>jngt-wpp_R+WHiityWj(Xmz)#g_@3Kj@I|N_Bj8PuDkX)-v8Mi zX9?vwab(-$%%AVbP99Iq&9bqXiLdG4RL8(ZGxQBIgxVVF0UrO8kZd!|HZ3y~S%y!~Ih0dbN448)1UvOa+t2f? zjyxUqW2NuekX#0SVzn`r`=tM35-f!Ir#=0FAS}U1h7tvN)N>uO?z#da%C0Gl;(Vh4oYIV9U9mr2SE8J(pDL=YQI1N&POc58 zP7bsMBb3Qjf=X)ri8%bPWGjPxqoJ>SBzjR!h%FYXa5%aC4WSBmC;{suYG%GFDKz8L z+5M37dDWsll)Pe{2LBl<2u$jeB2Q4{noDZQQ3@g>hCBUsWmU)b<-6f!PWjMcCT>6L zTNBkTl*d@)M%BA(-7-WZ?S2irwl1^BuX$EF@^R`Z z6Pqx;frN3%SvH#}*-Ew7QBy*xRMN55(H4=~IOA9O($C3`SYVA2En;bkJl$oiYT}po z@wRhYo1Z0zHOfc%5V|1T-8HY|u4pBp^cZ}9;(pq11AN%TX^UyO!f0K|HS**`{OPU6XusKmzIc!FoOa~0fLxFu~>34J;R zxRSrfw6zl!IK!TJYzfO3IWiRkb|5=NAp36kL>Dq4KQ|VD&~bqg=L<18y;po>-y?l< zlJ@JQ-VBnIKLU!`GX!;*^fw zE63%YaGBNW+>zpf>jiSZwZ6A@3lT!oHMt}?0Fjuzn2$MMRwwe0WWtJNkk6Tzo}1eh zv&&q;jbX51U(dTc93lf|I9_r_P%WmBx(6wc-@cWyDp5E)x-~NCV#G#Y`U8EP23cpS z?8Cb3fIV*6N77|uGFP^o-DMq>yRd5!{Rp7v8;1NGw~nq&x6tr6DrcBZ`!~F*uU@ae zDvn+?&W^~`SwtcEmJ4CEF54|#HaA^1hX0BjyUuOZDLFP>a*LVn_Zi2vs^rm$?!$Jw z5d1w|HinQg#}?#ty6mu}iSD}@W)1IMy0oU2F>z~aH}Xeyu9*jh=3nW;Q`1d1{Kje3 z?cA?)*+1-Z8y=V`dkcBCP<{%t&_ZXqGayT}i?l8{oBXUU-N_52uq%$binF3!qpQpE zdix!^os&VN#mC=cxlZR>Qn)`FZD~mgGn{(iWDfUm+)`!#P8aN3073}P zb7Z6&enppBn=a*}lr8)OUrEDR<0#J~Qd-*{O-pkaeGC=+8U4T;SYU>0ARP1pwQl;+b2?O?!l%WCog)e-u)&2)%owK`2 zSmg}FpII-8Zie@u^20d@(&O|Om-9kvJ<~`uk5=rTWf%FWF7mK^5GqTw^=vqzlFS!! zlEXEu4Yxu6WCC8?u854$aJ@qi6>8loxry!a1p})wbbGCykus;j z?Q%Yq>Fh&-J%f7KJS+e@i+}UMmH*AZYU;{Asrz&1_b>kk?LCf+eFf!vI^TaJ3yycm zlYIG=_T6XqcSTlNH!ZslZdzI%?b_F3>$=`Grxax5Rt84^rlr`2{6j8&!1>L+KVYrL zBbwZ@nu$Zbo}(rwiZ~)oF0O?I4sb76DH6Bx_8?E4>&2*Lc6fwT5ubKV^;}_S3@w)1 zTnlA$TzOYLoakMx(CQl>ofEu+#WI-JSz|5|jqYMMn__tXy z6WupSMF*S99o5-8<8j|}FFd5gD*wT1HTR*RW_&@3T;gQA{KANFNTRy4lm6~{=bNE1 zO3bE;BEVS42R@Py2)>EYY>bv!92|*f>Ee}OY!CxEi_D8S8m~UizDTBG#UHt}E$aLF{p<~R2}BZc z7d$!wyQoxi&BpgpNVC2__!i$1E#E9@Sv5I1-O68S1?GIX%a)7qw2KfVMUDMl_Z!$- zcMM%*w{B?Q^m}u!M{h24{qjCkk5qpT@(Y8Uj=y%P=FCYhuV`tcs-1r9iJ@`#ZVc4gZcY6P&U*gsa&O7VM#;G#Sd+9t;B zqcLtD6a0PJxP3In?OnvUy*#xVL_8BofVNg2@I#qnroH%0X_Dnl&#xkz3t5k-A3m&c z_U<&!b~rCC`B2s}VJ3ZI^S@r*6z(i3iS9poN9I??{5B3Kat5nLP*x{+q|C?>cRr@- z{!I&ckUTDu`_{`ylzZ0TA6v4PyorGBA>O&K4+>l%Z7>@1%tX;(b>C&95v>KE{E0>JiV%!E z{A!Tn%je9B&!~GXz{h;ny8ChU861l5w;`qoSdtX?C1xURUOx7u@uSD~@L5}lC-3>( z^lVQ(s{P5?g5hcTov&)Wfr~!6AVI4zdw->?K;E;=SGCEAiuZLWPf@qJ(M83f*G(i& zh+yS*y940T*|HB#r+eW*T>9#|H$99(9IlaUqDNMbUg_$K2gVC%(+ zVdc2OJ(rzC2E9Ds`83tr^t^0ZsmY0+V@zwiYVp@p!{=a8aX^N6M=kD%#B0nuT7JWQ zfk^gPT*p)5&b*mjpY|&?dC(aHH{@mEqqR%RORK~hmJE(BGq(WDY_rbF zD;nX2eN`=?VkEhI5H|4EeYPB5l)JlT)fp95WFtO#7ZnB)b3FFXNUg!8+0OoSZ;A&W zXK)8Q7F?w!o$12m!9~mru_)@Vr9z&b_MKgn1IhHXH+ijfT;6mX^0w#Kb9?>HJUUj^ z5&kc2@p(Wy5_qAo)r)78lcg(pKw+2btX#ZDdJCHoA|WXLiHw()LSUH8i`HmG59ikV z^%TrTi4Y3&xtyt?i<$Y{4HP2ZxLZ!t&g{*WCpCLhB@kaBz9kRk%ACMN+K=#Y?ey-) zJSh%QH5a~}I<=m$bfca_k18yF{(P%pL_xvRB)gMj|CnrYI+4SPgp&`==B)&n1?yRO z6^&z0Svbg_%lz}K4a~FX|7zUjMaFh^<_qu`kW}9cI?~Jt)r@4Q24L(>t1~K2d>||+ z_FIebAbxX+W6L*Tu-}?1EIuN=eVAm)j@&_+A{-cOm^h4q@tQ)mM19I|Vot(5`BghM za`w6Z)*{etOq9_3YGEu)C9V1cqs&Elyu_AXOf140%tAb(qm*4n)7SuU<$fjhF?SviB^z4^?aI)>9#Y;oNz#Nh6hQdx0MHw+Yk($x z6`zyMj+-)|wq+hMA;5*)DrG**q#20mwbY zM;`u|W+E-e%frcf|Ke(cx+{SDJR`cCo+$T6=ToMJOYNRkW9bl{168l0R^kDa>Q{;w z6^ESclLxsxzyg$|87dX;>#{UWmgZHZ+VMK^V+ubN|0H-*WCA)kC}H73Yw^pemyc-? zoA*Uz2;vyWo(G!p09hBeBnJc*>zF-Nr@Ef=YApP09J9v?N~3kbuit6_l6Be8oitnA zm&?_S_BEk*RS#ymNL;0Lba}&X>4n{xN5na8K3!?SC6SE$P9yxPiXL#YQ^##$EmguoA!O=b#-v%+0gyXlb zV|rAKWd_ck&I>G$m+`{3F4=S^gM;(=qf&5;TM+U#WvvugZx14kd1vkP;hwvk?@xAH(BGHfDX%PX^7^_h3B><$Q$Kty{Y^F? z7o?xN*=N&W>hG>FfM2oKoFiu`&Q2xCd(ot6{Z;6!EOYE)F+wO7bA%qV@TG8hi8xch zrvm;ES9g}K>6=}1W)Y7j?q#RAWUza`OT{N!ql$0|d4ojyFk)hDVkYVeWN=VW>`%Tq zgal}CH3ij!Sv}66)llga#5*x9NF`e;%rFzG7KcT~^KZWt#E`SAka7hJ5A*dytTZAG z@}Ie)gulWDxKV>Jg=MT&Wjm@bnAxHVl&`A}(@oW3 z2f#%BieE^d^%)iLD-`(jUWPyzM5;Pv8JPK!D)Mm!XoO$+4;#h3FUyadUub?#@~8cI z)lgz-g!30}%l0~-roAhAN(E-Ab+8g9bWU|g2P~1L#r+N5g5uLrd(^=X>`(rkBCd&r zc5$*z_$A;d0pWkaGYBu9n$$<19YxE@U)>=X?ck)2XS9ie-W4a3YhOu=S@WqL+vF~#h^i+J{b$Htj_Vsa>Ssj zFj-ot4j56QF?A?FKE_7hB3{jS!3w5#uyQ7oeCo8Xk5}W4CR`n3f{eGyjMpIsTv+Tc z+sD=U`cgA)_&s9tBBIB(>liH07k+CYK4nk~IF~u;q>6&DFZq0!xute$jRsqd*9^10 z*@!JwXoOIiKqHAF{Dg1h%u3*h!-XpgB+D3&3!cN~L7X)0y$FUN)JLp7#iga7uxO7I zB2{wVOx}4_9julxqR2|xl2ar_Nqz*8O)yyPt)xbf8HB_^Qn*+0S>DBA5KS+}?(C%* zf~RnjQ<9Cqo<>Ax)b)I;!Py{Yk~jdowIGKmCh<#(G9Wte zF#iz1{L7qGl{GYp{D+(!Av<2=SSct2l>CnBox(4iwc*~9E%ReM6m;zIWiCR@kszRu z6dimBGK8$5Q5;$}x%T*xu_xt(#)B`&V!{Um9~jQlQ)60c4|?QS0v5I< zzc+%B%d6PL7=b4JRa8?9GL7Qe&Fo5C$?KCkUk@aecj@ffR+U{=+elLkNuV(qQ2fxYe$I*9c~D}#B?6n1r{Al?v}&&mS2L-XX=1iWMjKLHo1+hSujt?&Kfo&WpwSRf zkR8OKL1=dN68R$3OKxOZwXM|LtdT6dQ*f$wGgYLQEBuK-tBl#X@SkS%&J_^(Kx1e~ z$E7hyj#>?Jd}yg{N40r1@d_w!|4V(C#d3RrS#>OYs?OaacRZy`e_>eTSMM|9!D0Yu z$ty?92pI`76}d(kU`d8dfBdq|X4QcO=kW1XSs5cTYi8p2CD`9;nddTTRgI}!R;;LJ zmd`iiceXkgO?91Qp{jr|LoS*wVyYwp>t$=wkRSSio{I>;GodmcdXTx*cf)*&$+)y8 zfAXVa?dnBSv8#y|SMxRHCB|;#&i0&8esT^q6y;Xm)C*EI?ZjnC{H;{JnVCgmZb9y* z7AVUK(I(6Ncvc<`B=M2%TLDum{~5jkxYKXT3w9AtiOnhT5hpPWcISGZ5thYo)Z$`o zjkrf^+MS0xT5izb{_>MX{;fSupYf^JxaE?a^7o2;bB&u`pKJWPS>Af6q+%y&oiEx{ zja=-@FrL8vy=Ja4zv*Khn&z6uV*G0~W%f%mcP2!#89ZDU{?v@#)h7qC8eLS7LzGDz z!WK(dvxaSpMwc{&&o@2W#H@F?u}t*O(1jgso2mcKQ>wPbB}{Tk$5` z;;RKS6fH<9S|BotWwfX9B$0naofb4d@}T0pyU(K`Y2?{+DVOZ37r3aTjc)fJhd+Of z2x##@5{v`?zlso-Wf&Aw)^xRt4HCIqMNJfiCqpEfd4?!4GHZzX-=K%6XL^Xvz9l_G z#}AM{F>D9?pFE@VqYPL`o-j?KcvWajLx)OG~lkv1+JiT$rt{es!IVvO~ z+`8m&`?j2%g?@k4zEGXt(SEjn&4K-r0nT9*pjqI8RyYFEfa;W~>CA5bY+jV>EoEc*(?-fm`C;2~fb zVZ7UxwCAt|2TyaO8V;+De85?GL!^4y9i?Zl>_nl|^%P>DgG1bihQq8j%9mbL6v4gy z+1WLQuauKlYE&kIp(^V}Fg!cE;_&Q>BUY*din=k!&6zStW?TIk!UTD?NF0x0LdO?e z$s~A=s0%$&9p;jbIveAKHwkvmDo(9)*ahJyxmtBC&|FQ`hIrosD^)$NN-ulG6m z0A3cf1I_gL#fQt`o6!DMcn|J0?q8L-r8SD5#-8aY(*!s=VjZnPqxI;sIbd#VTliu2 zWKS~qa_ZN@F&(#GAh+t*15ekjwNcpri^Loesv+O~t@Eu8jP}!Vbmk*zMqAEUgOgK= zrFy9F2?^?^jup|>1^WD_6YSx9AnW5iN}Nu-^K#~^W^MGkfX{hXoFF}E-zg=Hr#&v~ zuPQ2dD;;t-XkkCDMJKv{kA9|aa?V}d`Koez2uTuw*Ob?*Y=Ta3nWytrAzMU>@^rIu z4kJ(X_EEm)J=iD&E_AXaogsGxR1&3)26l=Z?-z}pP&Winf1RiXsW*@JRjLkmYv~-Z z7U$V7QH*O1<+NW@I$S-Ey3;z;WcQ5j!WC(Lzkk!%@*)qB)hi^qm}KYu9CLCUzr05s?n6}NjM^zhMytSL;#$ZQ^VL* z=)7XdODCSA6N@?|o~siJIwX$NiFq9o&yz&jL!g|OqvmHF^V1yN*RLtb;5ITpZQX*y zT59st{N$T(%wNqAOslx!^3B%)ilD#}sJsM665l zoK?cRv3y=tL9pqgsPp1t!82=Lq7hnEt3z?c)=>iwY3vBbd{2amcX|A+Seq@ z&y-~@%t}e-{O$7k5_eHV6Vaxg0C&~|_CY8@xu#2r{AsLod9IdH?0}-7QcHcRP?g2a zI#(;8gk4Azu6aVZ=Bp$g7711gb(xVo&`q{M&CF&bOV zSne&!ewX9Ex*2)D0AX?NtcM=m29Ui90n)poNTu&@pWa8Avl$I?D{9MWuAP;Dt(#L$J>GsoK`|X-PHgT0De4P@(b*R&YI?~cS>Ob71 zpUY(&DrNGd=o~$kB$<3((fcXq&o> zILEtrG9~jNn@?2Br?`42!qkY=azoi9^51ThSD8=&!=0flFx(mX3K$as!+IHGmk#bK z6!GSdaJJsdywe;$WriRP#9v48G-WnPs8%vE9xCPd!Inp;W!?zn@~-(}SLZ+Th4y3m zKi>-x=RdTCxMey&OWuj`LUDUn4r^GcD5=;o@I}}z=wKytOuE;B>#WM_t{@oChU5C<>W-6c*rgx@@O3SMK-hVo?_d%c*9>I?)Ka60t`TO=njl z_8gMnmU@DyXFxj5NQa>W6Mqb(_Qcxgvs8vU%Z^ zsUm$|kc5g&PL$_e*rUd$^=J!lt?Jxu{iWjk>SII$B=Ei#lnq<(DJluoT0T$C|!9R8)f4G2|=yjI-7&Wb4P|Fux(+R&~ zB`mtZpp-Uy{i&ORc^EOYNEbZ24KC2lpq0fi$lBz@$)73tDwMsqeOhTBdpB_4cY9z~ zojM(1N#(}!ODkFBF{-i1Bm69LuiGN2 zVr@~aSRSBZax~E-B0ryx$5C^|n+Dj>ad_jRXK4By%;U(?>HnPZp65UJGVDvKN$Eew;d*&-^^ubB{;u8cd z9Oo#%Ml6BEl>H=iAJxNy-6C{o^9$L7q7`BdbD3NDqMBT*ebKv zsBEz8H=UW%6kW?7N|d0l&{#eJrNG+I)yjG2RM=2Ycz9$naRedpiwnM}V*)wPU(5v7 z$pogJm;O341*&vLZ9uuK5=YSlrb}3>mdz?oyMoobxE9yDfuYwwp;vlOrd=)cwCu|} zD?Nwj%V;{wdPHn(hzZh@1Vob+M6&Blv()t2>>Aaq z%$9RD6ATc23LHWysX0pyNBA2wK)zBvY4#6Eun@8-0n@3jfT=XH`=ZFY2<6VwaHhU1 zMl^_*2D{>=QmZv1UOFpXexNq)OP!YyE~%2PaOte|h+dk!6`7dGQ

A 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 U@WM3T%|~|E7>?TZ70Xio7d(;;*#H0l literal 0 HcmV?d00001 diff --git a/src-build/win/signtool.exe b/src-build/win/signtool.exe new file mode 100644 index 0000000000000000000000000000000000000000..a09cb5ffd5bd3ab4c79e07ba445648a307db8eeb GIT binary patch literal 348480 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

D6r7qVqd*>PNBKZqt`8$1<72Yc+fZyi zC(2l}@1Rs6+Z>Dx$8PqDJN?C{$%Y_6gyb~h14LEW>Xg_g`aL-#jyIa>Bo94$0LNic zx8zS{{#00s{-khoMR%3WHQ;fl4!D)W@QLlsp7@`e%i}AXbK`$(&Wk_RoF9LP zbD#Kq&3)s)Y%YxdthrzO?&gEycQp5p-_|@J9%~*LU)+3fJlbqHKcsEVUMC{2BIi1J z9pZdnUWYnUg1`EZBTA<;b8`KG*%aL$(3k&bk<`6#DMUPn9M zkk=6BNO>LO94fD4odNPHaSG)14d*L5*L<9_Q(nhA-SR4R9C;0O-jde|&TH~I(RoQ; zWzGw{KpR=E0PU#Sd`XJ%qX zE5xKi-D&uDCGi5U~Eo+TJ!r_PKR`X)FJsepP zcWPM$l@bP>u**~kC{`=O+pB!z>M5jD<87Y=ud(koZaHkrMxMX&^r!Eecpt+1NSUe0fDby(FJ8) z_pahY2z8v_gLbf6OI0PCeI87_ z5?(g)D+%w^eUEZMs#h1D9Nic~%v5%ovYP>}i zsMen1>3oN*F!$Q#yNRk*iEY>t+y9L=Vu{}%%jYsF+(y2|H(88ymOgHlNrlo&AyHR8 zNR3v(Ss68LBAaiOZaR*8cG;b{$(E)s`NWfh8yuNTauLAYiZX_~T`S$;2#g%LK?EP3 zC=T1WUmB}y^oXzN7O^IZtvk9B0uOTo!Jh)3+vEzlA*W2~RuuFR=ZjoVnz#K`>B+z% z)iUv%<6d=mwg=VnK&ca8M!zbXd!z^p296c#IyL|IY@~dNu4a!TJ_no2mDkkfT<5p) zE6=%CUipq}lA8;hW%BByF05(p>nxOCh4Gsqv_F8*&VkU*g3w+Ep}iVHTi0yF|Et*> zzpS|^{=Mcy;ukg_8vl0lp!oRa;`q4c!{TF_508&(9vuHx^AYjk%}2)1Zayl0dh^lo zVa-G0Cp8}vKcV^9_;Jl8@nf355kIo|xcFhs$Hxz8E{z}DJT!h#^9k`j%_qilo6DB? zyFicW9SS`_%H+t8q}xOkstDm$KCweCdM#IDgt=+T?EKQTY5#9}{!C75h`a4A?(~@q zDZF&;vOVa@Ml(yqI#FoEd?w6V-kW%~@x00NF3*QNpY!bDN$}+H>dVug$Ka9G;c%X# zc#h>cp65iKlX+xSIfF-h8=cEDl4mr}SRPr8Ch&;Z{30H#ZxWaDOy!YPYzEKuJhOS` z^4!EDBKwpH3wEQT&{9Oc{ezM>{svfH#(WX9EK#3lN@(4w0 z;RS|sM}%w4uSkG3X@v~x16WCBOt}6+tyo^%3Adg_+Tmy_$p3x`rTY{y8?X#F4~gyk z-uP^8&XX8P<){m*2zW#SiX;H(J(U)i5^#tFT%rS}rLvr-1IDHThUBJWy)wquUlEsiLcj|yQBtTW$r~_6L;LO(FOC<6HNiAX?Di|pNRT7|loH2+J zaD)WF&q<08*AQ^H1e~b@Iwe50`gk4igaq`H6o=@5pGg4j+H)L_4)}otsL>G177G2g z1gJulzg(-JOafH38+D3)5}>;Aln#iu5}@F#OnhkUFoDUs7WHI)06nU(%%b6n-5qzYddMIP@yWkzX=U@mhYp*TOFul=#{FS}VU) z$})aED8Hmp@gw%sylyZ~C6^P)RB zFI2cYFK$EQYOc*Da>Bjuv%gO93%_fSV#QkL?OQV0g=JsuNhAhC^UmT~$J4>{3eWpI zLJJ2#2Z!*K^9<)XkLMDeYk6+wxs7K9&+mEG@ND6Elc$@<16>r}?s%RvdHg&V@_e61 zcr=ser#uhy{Dnt&Vd0L2UltBpcxs`e!gmYJ{3egkN1=DxepU9HC0r30mSYWD1UOR-QSxdv_i~9CLZXd(vR(@qmWg<2pFW`9* zn@lgRT=4&gxoJ>Nq?C7Zm_uJ*$o8s!hOGG|vNwXMKP6-Q;QCd=-xpU8zpKL4gXg`l zy79P;68}+O9*SLa1_#4R&yb>3ce`fG`9K;kS)Q*Y3&qBt5N8P`@myTG$uS1)cTaDy zwJECWBXli!<#53rl2Noi{{^Ju&k3yMU$ZB@cb4CK-^VGS_W}AF0DUj_ecI;;=s94& zzxzIqrrON=J}X(i?HnZj<*WZCEeJ?Ib%8#dM0myIoq4gA%wvP|R$YzSDUPtYC* zjNaJTsst*RXZdZ8t%?tW_e&JNcUdl`_0x5}0ZG&P)_~QZ@^P@GeQcGQc;@_W?#+?w ziu7$olh|B`IrOVc_GFHB(I}h3nPkP&pr6b&co%=OJ@rGFN6ZGW!^3J3JG`?@i8lP7 z$WoRFR$)Ta?o;}MMDbUmA5}ZEnaaGuwXw79OMl2VaYr)8>+$E|@_xl?3K#Siuhl}& z?XvOimZ6qrsQp>W-T}ZN{+jFZI-V+7IVJ1vK5T}NWT;lf!*{eOEgmpQm$6D&gaA-Wpxq7)l zQJ_fm7DdgFXuvnZG+~5J`6CcU)WYw$33buka% zWJ(B1RK7!6ARdv8ULA#EbvT>-bVKJ1(f!vh{pkOhYF35Kxn(HII71{g zO5S_PD@Yee$aTFF^)6rgi?j;LpB5xjyQ+bIMd!xG;^s%?ga(7YCfbB{F|E&g$@5+XZ`Pln< zpEZBmZ_G%aoVo7&C1Lio6;c|l%88sGXwQ);D$_M!1q$sOGA6>%)I^wdv`8fnXJ712 zfCwIApfP`BSHdPVjeN>t`h`EIaZc_F1m_NVI1}d{2`k#QmwtdoR=Cz$wteF)7p+9f zF)6tKWp@I}%OO9_%V`8vUX}qdUyK!)KT~*>fgaIS0U0i_Uv8erN4yy8mi2bwV#(1a zR6^hK7ds}oUN*gEG%g|~cgrC<`y^5P$YeScE4Yfv(0Yl_Sp>aY1GbJt?f%dCi&Abh zs-;Ui(b|-01uHtBQwSJG(AWbMH-v-4(RtU7!eu!CrreA{cNg0{3 z#8>;>2)z9y*0@jX^LJ_rU&N+aS_~BIQ@;f zc1iO-H@GYKJ}4Q}(!vtWWMLCiuxFKOOb3nV+!vPEJB7QIwn0$f3bqZvawOTd-lf2| zEt_}BNG|FoIRO#j(Sn>UyEOC;0(#OO!EfAF03#GO>afI*uTU^*CW!f^&TxDsi@WJ> zp~^#bOBFxnf=%EdU=u@)9v5tKzr31TQ{nQ{^fnt_gYCb&G-n@piM>!o*o5P5!D=Yj z`c^&{=voDlUsIaM$8j=NKd3e~fP=%WD2mqCf5b(=g+1{+EE{BOO2CxWpUcdebu9B= z@qEhg)4-3dP|Bf$PDb!6A}lvR^gf5;PiAV! zLJj4J;>QUPjhs>p&X7|gP)#7G6j2#+%2VW3;0%>lALkf(^>q%HSD_<3Wph8LpS%uo za^=x|~*fk&Qi0lq6k%;lo5{X0)Es+TK&=PHs*P)Jx`_K}}jub7? z%&FkT72YAUOQ{SlO`9mJ4Ov6G zo`AT#4fg$#4}^7gLXm=Ha+szE!X|oa z!1Ec;ZXOTtEaWkG4&xcZQ_3T<%+qL)O>zd8dh_Frxu==0Q_J9iFkE{NvZT+26$>z%SbURjC%&O6XU|{YbF(-|#LG_I> zI=B+ z1N+c!62#ft=*D#0H&^P$I7dJ)*xe{Ao(v)k-*NHpLBe+-!o!<268^v^NJz|f6;P{H zdlf($#-kwgQ%S|q9c8k@aVq3S9VCob5P42-Igacl#~4Y7#d4YbbB3Q|KB<3u(a&iL zf9@47At@?#QApqkyrLrx)#xLT#N|iiBZWRo$)P|tRX!B@BpHuW&7a5yPV*ms7slgo z(9USOnorpuY*CnXGQY6f$8#-6l_}q>URQq<{1LwFTT=W{UQc|WYi|jg6c$fh+-4wr zisF<4hovZV$pJVN?Gs;l$P|931&C{;!K5^`zpRbr9~$;_aPWL?k&8ca(|h$x;15<* zT(_{%Sa>U0gXa1m{l+}CzXHTyFaWb#6leHXUi=s-%3IBY#(8S{!|Dn5M9(ANaJ~S8 zG#@7BF`5G^JWiX(97!fNk@k{lvMRmm$l9C16dfiy++w-Z1e=&2afV;n#I#`(vj&@( zr?H7yjZMrG*u?w+o0$K`CgyjjYVSu?`)gFS_oAx(DXQALP}Sa!s`ge?wLd~ty9ib7 zLYN#;7{cV#%WIHxt-OkzI(Z%DTrRJ}oyqbV>~L~Rn4EF)I?@pZB}~o;c^&PXC9fgQ zFnJy0oG7njof3JKs5t_YbBO#p&gn0&S_7*TXVtSEc za;9auri97agNRBoIj=sV=hu;Jsnq;hK#ZD7N_7s{WPW{cmk!K0m{>ebijevBvMPef zmziUAFFD?ogv_rhdqlO=R=4aI@KC4FP|;^h<`K@Uj^{d_Sv9S$JGwcZKs6Cioa0VU2}L7KT}P zXJMm-qZXntiT%pVy`<;J2i5EBaWiGfgwlIQ%J?Q6_z-_F18-M%6F zY2UzqqJ6=v_Q{5?D$CkO`Jm}%|KS6mjEwk1HlW?ueuz8(jnd79B3}}-sb5`50`Y<& z7CTsjLX_^5C8Ub2Eyh&6?AOJ*C!JoOEKX5&{lR{HKkfN1`)k@$^#5&p{tt2Q0v}a% z_5Ei;2Erwrpaj8d)ToIfBwiB*$zTR&Z~}NiX$uysBDGo(W&o|&36s&xGfqpNO53Nc z)!uEN_TTg(q7_X*!o^#pRZ&}wh8m+~E!o1(#K4&sX5ZgY_`+5KQd``}pecx-Z zz4qE`ueJ6W(C$x#PZRruzWx2b1E2f?s6)azxf2RkPYapCi!6y8$##Zotp94WT9Crw zv~x{262x{~QX@;3r;gd|cW8X%FzB@$!aRt?-5PGZg)z(sFHlr>#d_$=qGW&c=P~05 zr6SwqswHwl=9HZMO#2QLU*9QJETn&4h((eV;UU}`bvWy9pzbxRc?xa75JUzniT0+~ z3wrdkvuUq9j6~Ko?aRJ`=eg-54Nu2Z!zA0h0AvcUH^r^?SPNci_57};n4a=iz` zfo`Ok6ssCGH|>q`v1E9Q|6|{yDkn3Iwjmu}a%7^tJv}(OrLCp$P3R<;ID(YSA_jJ@3?8%I5s#_4b@kagRtapzTN{738GC$-DJvGf^tpVM=H^v5W z4*(#+j*Yf${I+;F@0y?I%=tcm?bbRc9^fxLoH%6TJo)K_JgRAzPzgQ4K=M}Z3-*pkU&BTz+Q;I@Em=>+PxQGwWGoh+y zF#}%S|GZ^j`SfYTNMCI4#PCV{pBp~Tt?KRGsv<{Z%JckZZ++a^5!>sD92LD_LS#(H zvqkO=SH7T`%WjLBzoqG!1C=k@L$494VkWmcy3b>+ZugJdP2F$$il3e|Sggt{-{Vqg z30eNV`Z?eCSh@4_y=HV4zsoml=|(&t6hmj@K6^DF0(X}Wv*HD6GnQ$m&1EE4R+?XPD{AFEd1k&et{JS` zu&h1(JXO_XO@ErJ!LKy>HU*P7MSa0-VZK$T5R?D)`QA3}<*QE{qx{Ub(QV&9sM&4b zd}ZuyUyJ$Ww(mFjl5*|iWZA*23=ql}+lybh{^!dt=vThP^OCaGLR%x-(mxfPtu;@B z$K%<`K6Fh*Q_%C2>DxquUU~drD>1$xJg#O-P1_?9xcjm@`_n5kOnWF65G2yM zG{NK%Y~YGAv-rT&pfMGYukl8!VROiXgTVF0nRDnu1KXNUjxWrNapE~UVTH=KC*bL{ z)@(twPWXAJxl@uBz)@ZfwtSt$E|m9?Ee~ZjJiSm*H!;fASWn?!sP1j+&ZkJ-2e^Ie zbK$FDa7(_wU&))zF9*J%x;K_Rn~o`j6?JmHKy31I{FPhYn>5Ij7r9(|Kc_);7GtBR ztw3T^)>L4Ziv-{7c+wt0d+P0^+h84ZDI_Cf!Myz z83E_?_Gb_($Z!S`uJ=t7rsI2iy$P1!x1MJekG|*gM0s-S4a*H@{?S{{L(Src)P#rw zG7v1q^O@ICFA63Z>HFi-Wp~dx(*lRN`e$ z?m~;PX$;nN`mB4}p_;|fy%Vf^+8WB)jCY2&^DFWvrb@x2iNsHuOH{GUrYZ%dtA1F> zdRZ;F!83gpG=i7S{*XuCTC2X#BN*lNv|hB<+)!KdN_})cf0rorAn&V<0O$;9% z`)F=>WS?|zXO0bgxLxyDOCfD}gerrcCw-65CN$Z$<7Ga4QtMFMy%w^h$M$(5r}?6_ z6Cx+ow5bKwH``K0^|7`gnb8OvKsTa>fny$x;aNk2o^7GTm=-kB64Ocpi7Sj>B+UZU z<^fIe((+JhDqEm!VBq=?tpJhIF9GXAMi-_ZA=;o*x|J`mU=a+IebfYD0l#k3uM+bM zoY21ezrcZS@YeTQzF*|&$G#DLM9X9ul?A% z3x*#~=ePh0OxBv4!GqX-fY6S7G`4?mL+bM25Npk{^H^@XIe&YE<-nnz{^p%lGx`Lg z`cE)Gj#+KTMYV z4T%@*K_BaM)rw=2K$BncCEgEl!3j}&xbpz7lYVlfPOqUMX&*^)_yYP5wwg~OgjqlM z;$GV?v5bkd-?;fX@5y7iIwGdSxUF-Y7G zS|M}8N4Vkdh|TKM{>k!zEf>2yR$KTzpD?VaFg(s6?-|kaC(x|*KBGeHN1l*5j-beq z7&cCTOn`aaL;LezU~n+;T(D}3wNfi|zys~X=6WXdu4h?kUjKk|oTjY8M%H#V3mYXjLLBeNn-YRUk^CVCzQz3~p$*kr(R5f?A%1P>R za)j;c7&JIjOzuH^4bv5dP_BNffWKu>F!8zKVB*5k%xkJfkT%o=!PI|J-i&KTM1!7o zLxpEJ)Z_+J>~DLkJ%3=e1_ekoBy)GJV>nq=rdF&16(Drc!Z3}6VOsx%0YVLMSr`rxM=hMYYqjbOR<$j@F5qDcJtPF+ z=vy@~DYr^5V&gFLc=-Q|NAd4MkFVu40LFy9xH>IOVW#}E-($)jd8$hQUgDR*EWA&6 zbAcZy$+Fz91N@Q&&s%8j8=|qUPoC#YAhhEHrdB8NJ<0L(t=o_Fy_`p9raBYVw`6l~ z^XPn30!_)<^sU1I2}ZU4^rJWKehKDJd!HL1I?VfKnLt2vtTmU`MfdR=y^{i8?eo@M zU*|*Xv=*#3-($e5z&~z}uNY564iSP#1T5)8Ao(}cC-swxCQ?CbI^bo_@;C3cn&tim z|FcX8t|S-^KY13c!gqi^O*oJ_b^yQGaZ#P;cOFxHDb=&L2v1^0GDod=JxsnSWr!&y z@)<3VU-{51kReYG4E@r!%%%P3C*>6wO1Fa=Yqmk?7XJt$7rxgJxK|tkXP-kMB4(4Q zft$3W`2H~ES$EzD9JLi$E|zFw4?hww(eUPqsOe{E5j#YDvv9#sDasV)%3=5NVea}3 z;y`+$cJwy~PNN9)5-4BSq>DIM@mf0gJDkZrX^c0urCAQiyp1%OkvV$lz(ZgVVKQK- zBU>*(T~N#uC>HH8ph&zYA{)7!bzEb12zWfhup9)BCpA`-bTTE?Y(ujQ&iK??#VpI1X<2VqIlc!uAJIGT{o;cN>#@@K~7+73qao3J_r1FLnGV7k`Of?p{kwduWGdsMv#aoZ?s)GXvcf@va9oqmQbwXp4*J}QY zI!YQy*C=+vIt>e4Gx{4GOlNnP@BsJKX!ns`NlFnC1KpU8OCbJVFy}NcLF~U%A!?on z|BqEL9d^M#Bt3&1ro<5587Q?cC&2A(s-zf2ZMEglDPRb;gioUxgXG@2bSBHwmB-Up z`a5e>AUP8uR-nATrP3NzUunF~C}~>j2-AcCq{-i2t>x!s`|T6mU^PIGLY}o{Fm2`B}DFtJ!Md6ygbAIi>}T^Nk72c6-cM%yKb%J}b+5EcqAV zM=VN#F27Rt2o_$UYeuXL;%GeaGB)bsT2eELGN%VpGhjdVz;itl^59YvK#w~pte5Fv z!(7E)WC9jsXbrHJ#hh@vWSB=%F&jj7f$O7twIM8iE|K~PEyxVp6xUmSzUWT4sK%=i z(=Noh!f%l3KVVuYNlV!orj13ku@id9WyD1k963AfsOw+hw(^CL=Y7dX6gMujIKZ97 zPV?OeV74v%If~2DMx?nbA&@GKzD_iolMH&6)7(5AAQzs_+Y2*?9~@Y$9RVi)buU@| zPMnE&_2O!=#Jsf)Twjx%w>*?chZ4V*@*}?QG=6eXb@7M-6mUaabe%L&k*_%8^p3o( zefd^1PX76by&0p`Q8MLrs9&JLc?M3*8=Q~^XgaOk#sF>AZcvS7fChvW=Qi?5gGXGB zV%_y!ETi!@us!Et07XXHr&bg%m1DA|CxncS$-z9CRL$EEa zSY!c5Fy$OWxbBWBT}ww{@jIwH*t3>PN+#gU=90H~FK}2YHY56&N7k9w9F6GXPv}85 za^a?Wmt3*dmwiL4Dz?_?@6shshJOAftopmC$+7A`ms5VT574R{M6n`it_ln$rd4we zF`sjYMOLX93^>^<%K0|~hDFzyMcQcdW;hP1^>$J?5_5kS889>ATCdW1rB>Cws}x*i z@}pq82nAa@-dIlO=iB4oQ|HTvg_r2qMw36%h7(4%*VoNA^4arOY>t#UCje%I_Sv^u zI!lSP>0VP{KP#9B4OTnLsh0QbdYX3mV6~EajQL+Q7>{ENOsB!e9rnZBPL+`#lc|l? zlrv(iaQJsFgLASSo6+qgr@$F^^dJ*$%5NYN$qY<6p-2z@_hl`u( zVmcIbB$q)Xm*y4&(T{_|dg(`UwWbM@ChM*dUJZqIhMX4#6I-QwJDMpstUndukYvjw z@8YwYw?t~#t21&c!D^l$x}7TP{+fIM7{GE`H*twj-lRyEm;^3`?6E(H9D3%JgB5NE z)jMt@NN*7jdGIVdc;d*N~b#nhy*C^FU!kCy{W@291 z2KaD?)Wae}6PzWL&q_W;r1`|M4{5-cNv>=70?B&~ls&I98?O$eCST9MF>La36WdT5 zsQbIsJe9Nn<1}AvKd_Klbwi8B=VErj@TFGig&wQ)Vt9?qv=wHHqiLz_&Zwe_2Rz|Z z9V%EBPqEEibeWch$QT!4nSNmKgu97Zx=3qCWRWlB2h0$N<(^4JVqkR}NYC_ZiXIPm z$U&1MoqpIU zqIxN=h<7V_D)-mE>wo2fK-V0_fRgFNbk;Dl9N!u)b&TpI%;L z8;G~rK9`bK9h9|?K2cuE;-1%=_C(id9V!URU3WPJRoZ_;HT~d%u3(2XmnXra??pV# zJm2Hl&hr+}=h#*1JIgbk?^}4Z)71AA_xlLm5AbZ{dDZ>?E$^3jjzPllN1n4luB&l?}P~ez80zP0Qr(A_pvaZNK3KG9hsdV{bX4FlT`?c zI55Fv3VFJ*_Qfyw;vq;=OM`fomwNJgiVmf|4E?mEn(3lD(#set4d zx%JHmgr5o}c2iY&b>^o|Wy)XV71M?q^e>p|*MFHgdqSC}D1?&x(w1UjtsSr~B|NfJ z;kohbf8W^ODhE2aGnU~2=jJcT*;v<%<#5GKa0{3ZF>g58m9(hdP&b!XmcBrqR}ShX z*&L6YIsG91>{EF*X{SHL;K6gltOc~~GtAo9gPFBS-X+DEk%nO_hG7#6bZg&6-+bez zHabcz`Lj)zrT_PvyKDsd2}W}-z(f4THl{`~< z{)6Y6JZaqQ%bz=W7H0wWI-?hgT$(ubYQqi^XN)bd=)^C|GH zx#7_8-A{vE7XJSRe8uysoc~wwUHZ1*3-?&F#c+MmeM7k!Od{auK0H4$!`c70_XFuG zO%6!^XvoPbbjPws^8|VHEnS@ko~w9rv_|iK>qpbB<=|x~@ucy~qRRy}fC$PAiD_S` z*($erqArGbh@Z9U8PM|)iVxCOT?=EU=F1@UfhWC zlngVuBCw%iRv^(_A^t&#U86GwpM?@zt3s-pEAHoQI%9mwY_~tS-bJ2)y`d-4n(FPz z_Qu3}|BK1_l6BVutgyPCw+dYzT(xL&0?|*NpYZgd#2+eZ8HPaO`{uG9^@nXfGt(N? zTp<~aHR|q)IZDBFrQ3H`EaV5%bulkZ*G0TFT_3G@oe$qbh0@NK)u}m?I7=&huRJ@D zbf6|(nweIm11KrYtqS|QpeS$WDS&mPw$zB5#@P$BBMJ%kV~W(!gIsb-t? z4eFT0+i3VHC(4BO8Pl|TvYIvKfu!3udZUI}Yn+BTl3!#pZogcFVAVe^hb}CTZquwa zPTL4^8f~q)XaXvW$n1KH@0WaH&O~3{4oRV*c zdG!4`o|}0jE z8AbEb_I?ciT*P}UJHh$v@r!xS;@v}d58MB43K4S} z9-J);vk#)8C?Ry-y(>k_8|egDK#M>?_u9u+r~<$2_6b(?{;_N|Wjg5CT1FbuR# z2?Hr3-@{F1xoxjB5lGXN#A-&{n_={0b>N+ccB4kLoCA|l3#GGL^3L^o`D-07%r_3h z!`mSBO|1D3$?4V{M}Ya$ar7Il~Af*R_x$lw7xp7eimp5Kc0}oPNhOA>KPf z$&NAVQVNyb((JP}Att0epn)~IP?Ly2?bfGdO# zuf$c=nUTT7{!rq}eI0T&Jt3^_Cpf2&K0~wUjyw{KSYVLg&Fl2)Gc?y0Yx@0@{ko9t zl^Rh?13UX!^Nqu&X|PKG^nO7uIeWRiVB#n3n~l83*z@F9{l5Eecd+d_6npTl+tH8u z)ct=d^&MJZFZ`e8caY8A4zuz58M}dv z0kX+o&jkg0H*X}7z1Dmgt;~mZ^cdQf^h9e5Iz$-00iKw9%aYz3FLUh;;z0s+OPLkF z)J!<;GNCGUUoa$FH@_XwAW*>ow1%7QT2S}6Zc z_mkc;opSql)ya8H^WIPLwX~ri;oZn59oVd2&eb=a{Ct&PP@l2ek96{HzH_+t{k=P8Q^6gSvHecmk5-c&$mkiT6Y-X-e%4?`zAV#mf0?cyGf1JPz#=LM49 z`&0x{>9D!Rc;1F=*=j91*vl7 z4Oe+DuvPt6%7cjIp!vou1I?#+(W-U4>@GIBZYjCt+VMvl+qFDra%hgD8*t{z5vLaE zk_b&CN$$M){WMYGSO&U)|l|rY>pS-%XZ?OB)X!ffNMvR-k+*;$A41<0d&c1)2e0c zeH@o8%OS@Y484k?y__NSq~*`TewLpI+@J06jwih*(~+aMz5X_FpqDBsCK6}ScAE?3 zN>i8vq5=F&r4Ci|{LKBF969_9>R~nYEf3yD03GVI@ALqe5g-3YiK{SZhoQ zWavqM7i)PJVmii*g(%+1XVRZe#9JsL>ED%zC;6br`MkI!Oz|YER|QFvk^Hmx)pG9~ z{wJM$DP>B;KcoMtx%`Jy(0#Q`OHJtQ4uH>I`Z)zfx}2%bK+Oi)d+pbLDtKA((>2}K z#7$=s>vUxqEL9sX{k6n(9?FtrnvzJhnqMUsnp#rw`b`n52`jZOo@1p^Gi91E8wJ%e5M(Rcrm}SWq*ZPC2A2VvSr(yAIp`TdmVgh z1uK*~P}?~5O)O0lFJ;RfC5?UGxr9qp5?yCnW5q9o6H5;fJC^uUw(Kqvg_4uE&ln`v znt{Z+TGN7iqr4)g1d=6p62oE2?5}eMQ+A806&J@6&xVhSHN8I|-oP|oN)~HWyuf*N z(`bHmIj>IV)#kifo!9-&YnAhgIhSGDsh=LMWgdFhYOa_ZD(g3n4m zO=vQ{S&@nOSki5ZSMXo-6f|52a|Cl8515F{a}kMDtqEwz1*9h5@-Z1w$DGG2l=}55 ziiXJw4+jXT2Q`|Z)Prh;5h(YekGIQaV=h}t<5Cya7=P&j(_WXiaiFif5aqbusQIZJ=vZlssO=m_M1yc)=C z*+O`5xJom)sk3jGQ&`~QL*(4(Iw5^Q;u|D(W;0g2p{YVogJUO~<4%rHk zoF`WYRJ+UZ*7NNyb{p`R+v-7tBNEb&dHfeL-$`bKsqKN(Izi+AKNNEa_y1MAI%YdZ zlek;mu~(z*;?>zlvvmoje(K=WI)hi{JSmhcJN{x#&ux(tnUMdO&V)?7oGsf4KW!%C ze=&SPF0xH{_bM*seS~tgB?Ai)iS%NjaVa1K(#N5&&q%elfq7Q^F*dn}#y%X}_QgK; z6y{lq7xrBQ_N7;-fKEDa9REwF}>CD*|f`0 zl-{+_U+*r2VjBz#96{@D2K(%~YnNhIl>RZm=fb`HZVa9Bt_u7XujL{WS@O$ZtPALdqOtMN=v}!YiGT32tGb9c6 z0(xA)sG2z5m|Y2eJjx^9xYVV1}w=0 z#f|o6632(K712!;M%+Oz`_!A|jKR-9Nr!wJg_|sC+f?&;ieF}mH;RMZb_V-8r})PO z<_O1Vrqu9xy(Ml(!6H{;m|1FsIO20k;q=SVV5+vNW_P11)uo-gR!*)+q<8gZPhLrI zCDEfuHj3n<{2Xeo;5>0&fH9wCE-!3;U5!)gA5~pigf}T9u>l9gLNMV7?tutPk1*i- z^fu5&GB+Nw0W=QqMrgo_SplvO43EVAfvfZU+Z_Y@P~y7Il zKs&Ba;eL6PYkqZ#25-jL7AdJ<6$bV-J<&xwow@Az{!P-=WMme3l?S~JJMs$y^-emq z(-5M0s9oag^hJJFG-V=%Mw)Hg?9W-H2KzdO6l7MB;6f!hGM`|R zNnkZ6D2+s(^g;;MLG;A+A6%cu_%?f$}5!kX(_pV4?AV-&`I)<*O4c-PK5x?GtE@^X*a)cWNkISE2uPm ztn}7hlJjuf&{uxWHOBrb8!tnrw~D3kyt65;M(B^8s0H+-%?$}8?%k{q7M}7zGNoQ| zftWA*0zBwE2fhzeN>)~81#md)Oi|%XGXAl$p^rT|8CO$+o{f!lZ-x(B8a4O7^x02x z>9=|)NV$+PN>SOe@3Ez2$5bAOZAPO!-sQAxJ1kbm9&CVR17 z|DFBiQOG2XK8SliqZwcOa2Bagz5-AbxetGN@cmZ(%i{)WS`T9;@Y|D)K2)&|+R9$n ze(_jF(~<`g%LX4h-tr$pCpD`XVD}HTbt1YdgMl`KAbEV{r$r zX5B&~|E)8Hz6CcXJ_uP2Zy4Q#9rhnzqlM^q-P3-Sr+Bj!|2;iuOb%&G&ZLF-P1|9o z-v9?hLM6;I>%&X>KnKM0To4uHv0UVe2e!@Jd)U6pIN#cAHLp=I=zL*yGm85YZ+#mL z>8{1k^M7~bWD;A=_c$q()3vaS-s-t;**TOZ$6c8Rdy8%08d(gDx1iVFCi~pzzV5}} zh5;cbLG1)(TGUB;^>@=|b4$dw685+q3P-05MR|1H3}!n@jF;oAE71*Y)rj>+T`i-D z*_(mzSCP;I();-=x*xzBzqN|hbphVzh5;AHZ|ylwLbHX|s>d?i&5KbYGrSAGZ4+)b z((l>dLg=3UJh-vyllVE7Q-kkdi2c+F4$B~!gU`LltAXjm+JPeR5eBQ-{HPmSoU5>8;lkXo_m2eyEJM9@7XT<@;W=MG zmZM@a{xyd#CgVwD%+N^^8hX;l|22T;j?BxCbjGRNEh4wbeS&|dr1x=Zye^Q;%UrEB z(RyIOMk0JRP>xHVCh7f7|72&ez580VK$R+sd3J&hLG z7jqAbQJZs*5QbCO!-z}@p03KDmpSrrLqwC_OU@rKMmY@X9_3(=r0{wArTN__znR_N z8iNL`e+Wd%71k@Ew?~ZV zQi?<;iH!%ZhKkdBlTUbD`{c}7?e<|6Lq>Gx5{}3v?3-&sZ?1`tBjRJ^*(xWmDh*U^ z=YFKcC+K1VO!`sK7>|2q`xnoG93FhDkOELbD?wKXEGm{g_Uq!_$(z~Q2L^dg(CD)+ zH2SPBa&a$sS8#b>Pv+hpAeJrQ8 z&!SnGDG$cl3eiCgTK+cY*2+c?5xAqZt>)<_ZM|5SQpe4c7@1cMBeTgcGH01|a*l&r z74C3OTg_$sKr0C=%7@w}-w#BVG*ZVP-@}3_!jsGo+$v#K+G^Swsc1FE($ua5Vr{T; zhF-z(P`EfA6Dio5Yj0_cC)Rabd)HuJtZPbxr_C#;atn}Ooy_JQog!=HpGh06%UXBo zJT8>@D-gEdVk=kb?0{=wJ`SC`OH|y%y`l}4wc!94=ni|mXR6kS&xma z11;j>kyKgjrG3ZovlMMEMbovmeHCmec$z7ApZ%68m4LJJHC<}L`r%8{t`^g192{Xa zsHGbv0))y^ehPHZu_pdq-V{n*TT#V6P8Q_s4U8w;W8MW8nPXQaZ$x2n(^6q3rC`7J z$|~m!zgf?d27ho_Bf0W!B07KTYi_ zvlb!=`aNqkbK@noj0)7fZ#8o)0sQf>k}zBp7?s8kjfL2YscwS+xL+ycN^*FeOFh2W zjwvW3y|(mHLKzN)PA&Ac?=U#xABuJ2UeKzQyrIo zPWkY&dw&-0xHDll5C#UhQ2Yd_%D| z*+{)hF?zk`t{p<2~t_#Bd%^Xbu!K2L?{0V>sB7(JwQ)-Cp>H=IDY| z@`d}vKY1F6zr0VHYx{ivv%LRmeE1W}Y$i<0f|=j0qzNL%p&E*axU#MoC2Bu;#azf4 z8tKi4nF%y{I4gw+{V5LB?aC8+7rz@l#6xPktmYknBbfSRdf#T~{dkkkcv?!;vu=>- z*JP60r2Ccy`_uWKxi#kKd{>T?=ji<6W<%q<`qTIuq5TN-3?cuK8l*J<7*aYd{G1KbXgJO;maCG7)He2ekRZ9~MW@E3N_kH+j3XQK zO@1SvCQ}zl+W2j>R(N+hNz2BZ=Y|RW6 zw4|`oW8XVMEM1<}=B^v3o^BeqXpL!{xbMjTfZFq|>8+hc_ia_GY`T(Cjs3${%`_Z9 zpK|&j&f8j}z=_I_jDhsI>Zwq)n^EBV};LX#y=l8g>U%CcoGgsUGob5TEjOU#T^(K(pG)@;j`eZh^L zim|^s5UgV6Z))^>I9(mUm@{Ba{ky}p$YAHd6CQ-c7pct)O-r(6)s!Ipa@;X!UgTQT zr?=AgYT6YQ-sbn8M(eA?zYCPM9Sjuy;&gbEzsvdU?cj`=puT%7p-G=T*0q-yEa7;H zJ=Tl28Jz6`XOD4kcK&go$M`=9lH%s=nHI!M({|8G60|1$^nzj#3Z`TZ~U|1bYS|4W^n-6!;4 z$n5%w%Aps!ZE=k*1$W4>6BvJ2KVc@LaBqn^JR1 zM})>OIlDZN;6QgvcpbTiMjo<1e;Jda)!xo7Tv~9W%{3187Jh1PCDdJFp$@HMA^`}!4dH3h(ye$smAtQbfLjfe*ToQ){c2m=j7`s}|P`qe+Z zhA%mLwB7ABjmhydy5WE>nfvyb#6|*X%8#x%y+CfUK@;GA9=Fagbfk=E*z&nepz$o= z?;p{Z-~XiY(F2@7=^*2ZiL|ZQzMhkX`sQq;WX}eVGw2%+9Qe2TS8Sh18GRtqpPnBC zk8=C()L=%&VeWEg3^`?v7Lcl!-8Q#12f?t*m}m{0U8cNGyoX9Z-<8@IRqG29gn=Vb zTimDs-;Ls}h@2yl!h9n!;$u05gAyu7aV7$TBjUAP z78lxHcDkTq&O0zJV{Sv+FG6d>--T@#+P$EIzgtFDResLArWN-VG7YDz-Wovuut=Zd zb*KFg#_Nuh;T5i9Lg`-BW{O_QAOSyuLjCyXSd}j!T|ZJfogg0<)ym#R=EGq z@5crZI5_xr-}HIjRbS@(1|-CkO0?RnyxuKr?w%r58F;kgzrl*y?F8jTIJpq`O_QLe0 z-#akns%$3V@?z@QD$a>X4O{MjQmO4fJSR{-^%VR$X?{i;hm8e4MEd6B5X9BEkjfUT zK2tt0R?dXOWvu^^tHgMJhRHH*Vj)frGnRe_&Duk12!sFu8xcryV?8=rGp_{@Y#NeF zL6p7re10O+VBE@Xa@e~r*+qi!xEj(bqwIi}AK=g)oXAEQMC4te9^XVFuKr78|3 z8Vg$Hl|m-&J6^i>4>LEJP2c4QwikK zMS7lElk$G+bW^-)I_lt>`tT^AGo>&LDew9(Xz+B@>L1G+V(B+sBmuHA>QFFO$B+^s55CN$?`Oy!X(q{O12} zNLUFn4Ir_)`1|oDsLi2aLh|FCs-12BJz}rTw%=+Nf;m;MK`iE0-AXH4(=QNp5J&^b zl9S2-e$sogdDT}sK%U(V*i$8YkJBif#%@08eVzpU@WL7G0+c;Qk%>klf_dMT_l(Sy z9sZs4v5P9zfo+Zb`vhj>I%9H*!A{L?wg2N=T6Y|uN+oVgx%~mRruOc4=o}Y4r5Y>y ziZZtKO)=p7t9MWCa#+z7=N5!V(6?jgo4uWN*N|7Uq!|;I0rYraevP=@J|J6P|1UWi zKwlxpHwL6P(-hjY+&&it6qfVx2+_d`D2M|xLbS@WQhPW4SjZ}~^py7&14v2gNeYnw zx_m6m@O}csmeoHZ4#cQNj#S3c~$CR@|7Bx55md)3*MNAcv{4Hpe~I=R*24BIP}k-UwVy zThs*?UI#ZQ1erG=N&KoJO2Pm(^DVrc#?l@8Ew~*)_$qH6!W&89LioiaT?o4)?SdGH zmlO$w?lBcucJm+|>IbZ|jY*`wFWy;;B-H5Yb0d11ZM zE;R6Q_ALPDms|sqa=u&~;$sz~699+nK3up8fSX<72Gty)c26Z%7+|O$eB}LB> zG+mTo%vuR|#!P@AVlx36%+B5jw-v;hAt0`;H_n+C_P#|L>u^K*7P{_qz|j{$gfu$@`w^4hil5P&y=*XCv!hOA-|ohaCN}n{IaOu0?*2$>y5|OC2hhao z;zzRCcyyqh+i72JQUkdh%3V7)H>qzs+rcS!QlG!G-=q#}XPxUVZ*{l-d@>OGwl2)-H@2k`x8c5Wh>Q8jpX@6FCcDkI2+?LLk}4PvQTE^LqaM}-2h3d#{X2ewza z*5CD*x?{I$0*?>iSA1h<0$cDj?V`EJ~brSB*6|85GaFHF3L zI#iHLoKxN&Z3=ryExk6Au6GKja{YFucn&E{I)fA~@M1u)`5Amhm=nuxiV$z%>O1xo zu)F&c)_5}#?v5;Z%&*2UAJBH3&aS|CBVbFOExQ9mflYhYM7BkafrGj1O4;Vc*)?-S z@PZRzH6KoEqLaVO&w?-l{`4q*vm}0Nn)Wq1J(#Nu5<2cMK-^H%)*Y~Zd(7G72;Yq* zD%EDoj!<=pzo(_Z0h1UtrEkFyDOF}mvWVEW>~nv13tDFi(m}->(q*5M+u5?&Cd)Qs zOjxJyRN15C%$8N;vi-zlll@W^@v&!$FooTQiuQ>n=N^+YTV`^uGCAM*lUren$w^DS z9}>?#f(Tto*3O+YYc(3#7dpIOBFd8~Gm1r=AE;NKA)Vu!7U41;o?}nc8YvqV7d-&< zHuwWT^@cwuySViU1b^qbv2&f+U-!m-PO(S3u@^Y8%X(uc6DyhD0DiJpUZoo~Iffg< zH4SD*Y#Nf|#q`GcoVA9ty0X*gd?;D86}jX>h8#DQ30<9)Xix9G!Goca`{(YbjWshF zQ$GA_cIs{$yjSfj!neD5D$G7TkuE-bB zvKX}Vn%d_g^OzzF1?+1^wBVCD`+5jdozVFgmC6_fOC+qG?En6y2Ui)`6J=_8V^8Xh zO_|upXrju=SRTR2)0NmE%@~{6h|{i^+07%n_MCT-C-aEzO?sRMmxS5A-|Awne;hpo zS#$dBMNoj8qh=z=8X?uwvtUQHhGNIvKj|biPrn{e(p1^^c-dF{l!f>%WtOLGgaOGh zflY9qDr_4X$H^;-IT75({^#&Mbut|7!DP!Uk_8=kc+eG+2RB7kypS-MSfvDbMrG4- zk`Y{c?VnAO24_p(!U7cLO4VI>m=TpcLz0JBEkuZNXlH$CVc3YlhdZUE=TKUXrnvA) zmHY=dm@Qj@SVZu+KvOzZ_MZfrS^LvYC;ViczNE@pO!#}*vXmRnOqqP^Va&RO_cpzp z5u!!;{eh#uCL4xXYz}egVoR$NPZUJO&=Rdoi*IgiE7GwwBbBn z&Wv{T6$s^~%q>>)aWF*-q?X3dS0Z*uT0yr3b$kT}WwiCw^RXSfn|FezNcF=i%>Tf;Wh@Ljit%oEBVk`rK% z2DlFgq_5+HdN~)7Z^-3;l>C{;8WLUTY*}kA^9b6}j~)15Q)pDQb^`xDOT8Tub1~rG zP?S^6+BrD(I>3K@XuB`*l&^{9k$UdD8mMKeNmqz+7Rp_TC!ES6m!;()kBC7=ZR&~M z9C+Et`dEe`@dfSnuo9^Z`kHoTS?zpHPdTIUCgrHd&GMO?r@sq)v5!v(ABSg9Zoirv z2?Vmp-W+gP@y8L0nOncn5a2F2tNDHa;i!O;q^eW*$gebBsgWsj=C~*j%a$(TGQ`X! zEIhr%ELSl<FF7>W&|6YGgQ|O8=>$0d)21LW4W^U{I zVLWrFQnV&EK#dZjau+U!2eRDWm2O}kmb>h&6G>>!5{kGe*vN}xyRbc+S{iKX@iN$p zISZaz8c6uq4;EUZbQl)cfC|UprK|~s3u3i%BO@BDhXRG*5f_Sac{{Qy79l)(8HaufV}laV z(b_B}Mmo>YnohQkIa-$;G8U!ycoBu z;mO*q{EUR@JNf72F?Y-b6CbAQC?Wcl@`CV*q?`b4o|DV@$Y{@D(abIApWPJw%83}V zWg;Y*#qU|th^x<>*)JvGeuYPsI5Iu@m5PE$L-Z>r6+|wmX=BEO6xo)`LUYkvyzr#V z*;IKu-QSe+;;8%v?1gGQVEN^-+`M3x)vcakF##OBHTgW)xNtMjXaQek&%r0K96UiGdH8;l-Lx+61H1zgq`oe%@M? z`Ejc^b6@M=%=cP{WWL>6ocU(!(9GAlIxyKfJabp;h)k@tBz-%bZXKDH>y1_`t-07* zY9P@%%BZ@x9+v)$0uMLKTI=Za#rjp2mfOXwXk4zu0 z*HLL~va+p5r{(Xo^%!$WSnIKA4*j#O$E7*$&bF4P<=?mU_;j~kC#2JQotVb&RJOGu zjZ=+m>q+T9>veMaX}wNKcj#4_*3!3{=hr-(xn zz3fAwf^K zl+clJl;=>dTANqMjGVNv#Wu)Sn?pX7MF$|?gutLMLiofon6Qh+;z~PUUDVCbvH0^l zy+0a0_I)lB*fVK(!18~nqDO+0=5W8(KJyJJ6m&D0>X}T)(+6PSaRV@LEg1L*Ft8O2 z{1q7Z02ufaFz|jb@cUrkcfi1Vz`#{t;N4(gOKVA{xpibF3hoK8;GSR%?g`xBo*)nI zX%N6YjR&}=p#k?aO5mOb4BXS$fqNQ8a8Dx&?wzF9(dlFLIwp;gQWo4pZA`d_E}n3Y z^911@=P<&(5A-_GxDo~T@P8=WdrhyC)7$krCHz%0Rfg%AUn@ zKF?I1AkQqGD|xQs!D1_WBhM0^+jyFIT6n(B^DUlxd49t4-#owLd6=h-XA{peJkRq$ z?_8^C$DvsA?ust(&MNg5a#$f2VZKm08?0*&T2tG__JdY=IeV1E1ZrtqE`PD+w=M{U zl-IIKSBK0}4PP+7m*c4?50Kkivkk@r4l`S}XQQWJ@*ptE_=kT)6=usuZQulte3M79 zP@!0*`$Gn2YE8QE`SG^p_^fO|Tcr<`JxUUuA5vJ}vfhwjN|u2hD|`XC%sI(i9b0Mt z4148Wj@pwNw_KvJC}Ac!O`atoTMGfEZdcx#TmP5as{p$4A;rWt#jfEv=b-bcL&Nt+ z=l;Kg?+*~`IPe_@++Fzow%vuV03SXVfO64;3s8&~#tD|Q$=DZ`Motw-3_dh4PorD^ z6JTBl5$FTVolL-kfXNb_^KY|ub18C=udSkad0!Q{cBm(qDV8qo}uYOMJCp%6p|mwRuc8& zJra!PSribdQkH)WG6#6y$K7oY>u0v?y*7!M!V7(gw#gnstk`~$@l;Aq9ymH)Yrlp| zS6p4_cLC=P`d=E?FC57gP-h?+mm7>gB5qtHNc^eOnm{t8*idSOCzSN=$l^qH21A%F zy9hBMzS>OjaW$HpYt1k32hCKKpacRP-w=UB%5i=X?{tz}LjOr(D&7>AHwN~nNO9uj zeCjWda!PZX<9Gy-=%lw#tCiWVJ%hS(O_$1z=~Eg}jf!yF<+Rc}*J)Re(}X+CSxVm~ znBx02!DQ^$1ZTRYoSr&Oc(BGa!RerBf@0H+BxRSs?ZQ1pr5vt_%Nn5Hh?@hec{t&r z#8y&Xf_!A#@?n^5WtA^;H8O_J9`Hp!YFmLg;kNyVZTKSkW5Pd1YJ)@ufz8m@GNTAQ zAgPb}+8=w{YJVGH&l?CEJ~DC}EH_o8Bd?L+m(~1DVCheN_CsInBQBr61vK^{Zn2uh zo+8wV61{k~gh}n0V$vM<)nk!8S1^& z4CjWP@J8KBVy;-xC4h+05OytCMUvaEFPt1kprkzKQ^t!^EF0A@ue)etSWftc*a_JKQW=IH;^pt4^^=X-c*D_hfO-vwd~K56s@*m zd^e57XHzS>fA{0V$>#FA9{f19Syl5otx;ETP<%zXF3!`C8P6Mnj-WW#fn%TwWyjl! zjXcTyW(05KY{~4~pqkykamVmx0vSGIN!n(A2APYoI$C6c-?ulLbdLWVNB_%6VO^`S z^4<|e)An9CEA7+E`!uBAfcEq665F*<=T7s{JaYBo2O|mYpPdoXmo@n#_^QeS7|_D?Z&mH)BJR&D`f_ zVj-6FwWo*qnzlHS$u}Lz`J{{Y8eq^w3&l8^T ziJ|k+KaGEzi6#sUAs)-H%L?Gn1fM27={tz%xM-{gA0Uxh9on3!8HlEQw+IjX99Zq) zG)z?AuKADL4rHN&9Xa1d$=N8u;h1+mj4znK+3`>8V760Kt zQrlZ!%%5fDPCRqk*ExFPX5~H($pBDSiPAt;#%@+fhp42w_#|XAFSXv_V7!xG@Eru0 zEK=1(7i#JP$ET#%IRm;c3NyIUcT@C>D|H9(YXo8xxx{pF^JCSjDwXnNZz^ zB^8iF)rNyjd%^dd<&K|j9r({w<%V|;)NS&uW3aO!YwEkWvzH&fK;k1@Q>itf#NQed z?}`hbg>fHNoQWNN8JwL5ujfm2Fi0b_WxLmy<1%Bv?oV_#)@`!lm#E0HKM@n_xy_3I znszsO%m$d|i1E&5R_P1E;U=#GyDox3{68=FD z<$hoYmJz9q4R|nx5p3aq)Ns+sk`@hK(-Rt(en>+5X;?4onsmk|;py;!Z}Dv8cNtU? zOGb_`%hV~b9gkE}vOW3doQ{^UOpPZ95@(Ds+w7(I?9&#no=S7;ldms6IcrqX3<$2Q z1bX|H=RXaxTq-9;<80XrwAIlRH+sI8l;)1d2A*G48oN8=`ZCq{iwrEL!cwO&lNbHF2=#K7dwc>~fjCO$hMG<#%p)a=cI8z^|d>i)5mxQl< zC#=nzQyNou>Zhd$`Ff~h#B#QI?kYts=8|Uc628dPGFl1b&#Ai_yw!G^z?QWSN zt6@D>lN_h4Ue9HV#u?I2SyIU3m=CYdd<#lOYjZtce6sv*sM+22nWotoY8tN_mHlkN z%^||eO7#WyBrB@24bG_4X=`RP~`CbY14utr45=ivBC0plcXq8(kDsgIwr*QBG6%??~f|TZ#6tgDsN<1 zE>(t`!KZpn{_VsJjtns|nbTkq2IDkhqVEy61@90&B;qAHGm<<*OrFkQ`;J;7ip_Ogh z1DQD_Ewom?M!BRq&x${9U{jb_AKmdx9#v&ukY}9 zTQ2dW|C96e%@D_`L$8;yz@Z{ ziFKjvQ50Um*llEistyh9gfjh!k*?&uCD{IYdE?OMfXTP#-^s;H;J)sYwPk>cXoIRTYMfPniq&_wnZnE&V{SXt`F9AM&8dz zr9$X^IU?^45q<~q>90ZEf~n;nBG5Pk0y8vF^ntl~I-8-sq>)adPl zht3VZH8WLoI3r4f_e9<%1s5oGcwpC6;Aa@h;MlZGep$!AkCN!apd7GSukGe|^qS2+ z^h=6>Ysf`>GZ%5gfQWr4E}HGl@wo_{`tCHLRB*mR+0N$5dD2AmQssX87bLCy`Nwj8 z(oS?w&oBq7AllMN!H4H^#5skhv2LW}r%^#u@aG{ znue$H-xIls@Cyne3o@5G2_mQIT?7fZ4*mqreOghhXJXhZ#R6_berT|M4d+*QaE9BG z9~!(s-|V5#4Vf5`4#KoTg^*#QZhh!Icut4Ctm!TBv2-Vtcu?FA(j|w@TwS0pZ;Fel z(>OScaT~w>*q1NvA;8EPib?K!447#D43`{e`bb>z;<8MI_%ACa>tQ!=$tbSczTfc2 z!NhBs>!BYo$Bk9Hf^~m^yH!z3PJvBU-LT2pEl-lfFlkx?r>t5@sMfFrcbMcxYw9kT zzeB zd=#vE&5GBmcV*ut!Z6M=$k~T+b~-QiIh6Rw?Wh&gd6jdWcHOJi%CpJBg-Zf$&}Ig^V?$<<71+2Uo!EtE=DbJ^;L`5}v0IDgMoxT8?PC5ME)|D_L7nssw9RTB$N%(9{>8FI*2>|gy=B+- z7S>}$_9Oon5#y`Pf3K|s-l#E6M-Z>MiHDH;miADQj6dd-)ftZ0~ zae9kLS`LVHb0ZVzEjk{|-U`wkKeEUtfDVAt#krN*Bb z%x(-Ozgirsdw0n#IA3n`a5+#G`(2RZkl4T(^{0b!JBL{VLD@I}l;6~_)_u6-G(3KY z(tjYIANRp1=b-CiHwUDR$#aFhIEzbsAjs~|0A$izjftBbP`i0p6)J+M5lh*C35fO| zquMUK733tecd(X}8y6$*ixyOiFF&XrCdN^2DZ(~8LMZ{ytEQB?zeUE8Ut8|O!523( z4GhxG1-?y17*4XzDy`HM&A))XlB37FFV__Us@)Bj{)ni>>G0O8~lN<(lpr= zZ{ek77+cxemepEOarp(;P+VWto@hL)Ci_Rtr}{M>yqe>{yqfv0waRZVSd}fi^k+~- ze`TiBv8U5bb9Z^4ej6Ysy&Zb74%Asyk$Sx8re@dsi(ega z=>vJ}EjL2|{^-j8*3#etPVn2kx2Y^+3d*erGQY%5?M6*!1euP#r)K<(H<_SfK7GfU z4E2abi2YbBIrTS zHtt6(DL9>^P%I&_Bd;e{sk~@6rYcZ9Y)i}=Z*GfaXS27yIlH_PF+t|5 ztk)8gv!!F9m)ie-(wzSKhEj8Y^H_6*G&ebId2Q(h{JKM$n>uHC(RkLo4fG;(#vpuf z6*!ywaF>yRnL`=B7b`P3{eL>I1w5qc30W7hzs`D> z4E7n%qcz(^SliPVSof@l5Kn=6;V6AkLHHD~WI3J8;~|KY8Rz16g6+y~qYNZ8rE#FA zJcBjX+uuN2gCe@Aw2=*t)PM#oA|q%~D7j)0&ZDU#y_OV-?cfXBsA)*$yQV}xdTr@s zdVdwtc>FBBfuwzdWbuB&uIP&`oZ9V}GW6x4>l1%!!u$)+-MNC&GBqx`Gz@J^Y%oBx z;xmazFW{d%zM<(mbVDx7bOKW`iPLjhzD;jPl-~5DB~muZc+#!07H71bEeSr zwt>U51`Zz?DQ@D~^hy$fQRpfKv;eAanBj)Y;D&v!q_+_(t$p^%)b>eKXQaYo2eNpF z!wjeF2<^Qp9jeYnPL$Vgsrlrxx88CfyUAZq-57t**K5Hh|Fv2I;#vt>{8yjlY2jX5 zsh{{~;iq{lp&+ZaU*s^Yc1dagH~%cr^7|9n-Vqm3_c&CYwHPXj&xPAjx`8OjosIg9 zM+c|hZttx4vCM9xM&~4eGf2!Tb-9CFqGqWxIfPeb7Sn@t5kXqLhuFUu$$EW0X$$Nb zU+1&BUrRh@<anV?S~FO#TWb@WjcRO}c1D3~idF_Zo!PEz+0S4&`_iaG=DVeD zKJL3J&76p8Qa}nqPEG1r29;%>g--=()c$>m(Woso^ArKzUi+5+L)@FdM_FC}|1%-M zfZ!9Q4>WCbxQ;^1BuSyL=mOMooY*|OG_a^+6p901~QJL*oxIwDq3ynVw+k) zw4wgWRs?6{Gx%Zi5!lKyr_5btY$@9$JmvhfO=iGD8L291D z#})08#u9H99P;_dn%PolB-5VtX_uqT_y@EZA4Hq+S7 zmps4YS*{Wqb_-8t>1XRpufwgYj7fCR06|j`)3xH?gdPf ziB~QJOmK&z?Q1ALj`NTOtYr;^uFh=?`#aN}P#o0-sYCU0QiVPI6Fzwi_@44z!1pL8 zx>+O*&6zIeBfo!y?M)PeMk;lR_G>S_Aa^W0NTP6_h|4TZ@W=Y%*MPaeZ}`3KZhDUB zi66i|%`8Yt%M>WT2`FCxl+SO@P5wYZdC6M6`X{f~YoFv)z4DV+>NOxaS+9Xfo&7fN zn;fs#pyW8c1}8`BwO>-YN34Mp^(sgntJjcZkzV^7vv#ZjX}q!q_SLJXqS+66LztZcd z)7N1y-Jevc(De;ar8@!T&x*7-snThN@?l4&irRgfUKca zbT|to3kp@d;4J)`KKvhrW7l#G4%=T&^dXcukf=D(U-2PmtOumDSxyf;TEwTWvR4{s zOo$;|H}))0!@Yt^gF1sqe1V>fzLD;gpsr&t8k`PrfK3~M{`KijXk6flzfS6)EO-SL zg%02NwuL9y7hrsw`}O5J(q8TI0%a;L=&88w&ZP9YMUUG2y_oTN^*Rf_ehtk00+_iE znE4r)@h4!$JHU)T1T)?OX1oc^xB$#JAMh~nG|0l!U<*(CS$J|RJQY}Y8e-vTe+y3s zSa>?n!c(Dzr-Lj!eaXVpPzz57TX-5~;pq?yPlsA~I?Te;;TE2TTX-t6@N|TQrz0&q z9cAIE*uvA%7M_l=@N}$&rxF8CW-cVSnG4N%gcEsyxzx&vbA?LctEI*)><{oB1t`S# z4f~Tp37xy#FJlG31Ciunk<#o%CE?h#4Dsibct%k?cSzY*_jLyee*e4qhFirRed;;8 zr5&&R%ti(Qml*s+A2>?b;r3<5Z!aO&sJ3Ke>Ji)V?XC2RcD@*w>O@f^T2jOPfR5}uQIPU9KFQ^j*G&qSV!d8Y7uljqw!bv!rnM0jrExsB&e zo_lzH!Sf)`!#scDS_QePM)`T{>AeV&nG+p(cA$v2~S5hx~kZ~)zl;6vOiMpluD(*rk z98ADLB`$9cC-CMNKOsR-I5DTQXTQvFFDPFG3~h>MVa~d0&(Rr+IU0)7L`hv@424d? zzDYy7s107t$QRJHuxxZ7{eseI$l}$()VPfNuGwUdc-gtJKdFW69ec>0Ltm9WK&M>T z!cOw3^W8yzpum*$O9fb4@&971>gN>r>dxC*Jp{Wm+9S;cIx?>$bF-Iuy_Y#-Bi>z} z$yjJJio|0QI^98R|J;6M)KllB3(vkS`-CPnI$d}QA(9k$hc+;#1(ELSb%b|}%y9q+ zkqZWh4DasX{J4nmv_?5c ze2qaO_G^ZZLC#PqaWVLJ`p}Gp2ehxbBsdgxqM~qYRtfw}rRD?4|;*g}--^5LIb1AiLCFsIuZo1in0A|LWhA}WR7+#;F zVzMm67{YzEdv;a|!`G=Pm9}~r`GvsyV7lhc=nMATF?=?d;Le~<`f7_ugyUn*qQ8bc z$eQ2yK5Fd*Vak&+a#D~zs#&P=B@)#@Sd2&wQ3<{95kChiW*^g(`1u@n8Kj3NO`R}p zcRyu|!y;apuWrEBs^XFUx?34WNZRt$$?3v7b=;SYGVuT1gPab~z?Qkc{k4#WDPI?F zx_ZEv%e?|JYfl%sB`gz%EL|)>u3p$z4I3QvJ#luYhQ)M- zOh@l3?@4%uti^r)<#usjO*Cq)Wr!mRQWfdKTUAGFb+B~{vfB;FZYQnm8HZ!2aHabI zj0}syv+)u?&kVFvLVtlPS?ML!dh)GbSKZ=IUd8}qE$iS9%(BkHcSed-h8i?uCTm;j z)BaQ;krqu@Q>G%#8Ww+T;fXco;WTOLo#Ncp;xy?FIod+qboH-K>$J&uM45Kk4%|_# z)7n13oVIRv*FqXQ``XLb#v_XHI5zBRp`lrf!(0~U+{$%l2f=s?7E!7W+^}FgftTJ> z^q$&&_B1Qt8nWO{ey>~5#NV9u1WTt)PQDmg+U?4s{gzEOCoQ#l3vH0MEw7%|M~#`9tZ}g8|nUL1=A48y*YC z;q?Gm?s{WZ#U}UUu*QS68|_xl4ZoK;zqOq%@r*cca^GK;wdI*yX1(KaKS0 z&8g13t zV8ZC>;F-G2L@e(xuT`ocoOoanNp{AM#-GA=_x`6rWOH2118PHJoLTeokDi!79AnLlRxYn}dEO2*yovY*NuQRV^(kC2Nm%^3v~@Wl;2VL?Jy@ z*eg3|$Cr_Wn$$>@XR=3^?ozKxQoSmFUG!t(ZLz2#cgoxNcmyT&tAfPRnZuYQ&gaWj znDIPsekW9w-GJQROy+PwG8r0QKybRSl`H4L_!3Q9IBtfY&1*t1e(q%4!!iY^NXwK` zY_UpV&Q!Sm(P!J}geoU~f{mZt8$ZQFB&P9VW~b|w_=X!!JgA}!{t_eVqA)10^qTHb z0=U@o_1_=LO}5tz-?5}wrEswId`;Yu(gbQ6D-|RfA(%)kGT$gyce_s@WkOR$A-=l% z8Pz)#7hk;8yb{ZJt&94p!j4W@lyUs#^;T)4BbZ+AG(M$Blvz;j~I9r`&nuCesQWQ%Cj_cZmV3F}%euplCA`jinMP*Bt9KJzqxf zioCC`<=kDAl_;U)B!S0Tz@u*8C~!Ggb7t0( zZK?+2j!W5_R$!bawrWpfu`cQ}OCXWxFaWT)*-UM?^DCH6)D=eW+ zN-C5x-uyOMJ(Mz;rX^2SaLi(}_Nc~R{{TDn-UBifo&mD9H_22=7uf8|de>Jle$x~J zbsja;d1St{9=YA8J8z>5D9`+RDv#4LbZ@ThD2I;A3&$IW+^J%?3{CM)LF15V{B#O# z9x~g!Zy&-|A_#3(G%L4FvKfxNTz~Zzf%zQ z7qEENtH>ea*`agzm9JlzV=7PpiH0Z<*PjSRV1hPHv_mOSsF|99krLag65Ga-C8j5( zT3#%((i+4i^HA8aOH$>ak)tK4awvl(S;F2`LfR6uByDz6STLPvQJ-wT&HhEE`c(!A z)}k?rQLYD0pk?uh#ez`*Lnw{SZHr{v>op(x_gFbG0dsLdT+US!1th8pAUPGifna>O znc%oxeQ28zhbo^&hy6v3g}Pd<_Ddy>+kpwKOb>_-pg1kQ1ACPPq3Bkts40!AnoZ~$bdoHyv?g`9XCT{Q zx7W~kxBw9v6kScX8Y_VFW_L-ani#vh6X_3=ZQHLsF{O&*iEi~LmT00Nglk8^+v9lI z!1^PL41SF*o~^iR--h@$`*=7p9R^C~L6FTfQi}93{#iRJocLaOIPR~Chr}KhX*>`k z$Nq-wEfiUcgSmA@*rfxfAWN+Ma|Bj$RBEujAHjU85}K!W1S77W>t_0j*?-JQbQXmF1ze397yE_ z_(|w-dO20hUP7&7BdK*zeAovR>6a~73}_)UjFu4>#t8@l9ASU@VziH)#+OWw5(e62 zNb+~)_hK_!;1|tlh6#wthZmP!J!KQ%g>jpdZhQ)%>9na{I1d8kipc+ zSmbRH*UQrdh61D2bhvF?`lXYzX@9>N7!on6@#(_Gxoj^bmM`FRgF)&eHF&@T}pYgu_YW^GKEog8qWYCy%|tj%+0xO_qIzk zGW?WYherBLCIV1kOqE8;9+NtIvLz}h3dP3`_pWAyvc;q|fMvkUiT)ZvM)G0)Ab18~ z^0ta&-;^4}X~GW@Ab4Av`K>fR2c72dd%B0yj==l&cC zEL)&x4o)!cg3VR%jplZtF5v_*M%jWb&`$1(ckXX&Rc^+7#BToqeQi=dZeGJ8zMv90r?EFI|(gu}Ovj5{f z6D=Fz?xt!t9{m*`vFfDr zNc2IzrpBuON$l@U?7J)+AwIGQqp3(UQHjDgJ{0<@=?JU@z0#@hOZyEjJL=QAhJ(THUBT!M?&*E;-H0t&iYz+optHOS+$UUH;2ZTf{ z_AtTgqM{^GoHHoZEa=2yC3N3i#m2Ov+8xaXQ9^k=NzA0W6I$TWEg4!jbf>tl-@%SA z);%+??5)~AGZc^dpZm}xYGh}J-tA=W z%4n<_@`~ge-hQ@UhNyYZ%?)WYGcp2!)L^=~T=ZA+Lu9AG>mt6j4^4I6Z4t3^C%^kz zCYVh_h1bo#EE5IZ)%_WVq>k&Qx1EU2u)L_5*eAHY!?RDYMm8&aq0&vk($~TjSgBpr zM2W^sfhrf-_2eb=kQHuzMpYrH)Dok}hM9stfsWW*$G#SfEm>+(bpstLCmes!q>phC zJxg*?Jze(ZjU^L8r#?E_A|deF~4eS%ce%UF`s%!rkw4O^+iaOvGtP)`6SZv_^)1*qH|O* z9*!l-c?nQ>^#K%q8w(cR$*UoHtObj$!7=7)UP0jj~r}b~UZ*X)AFm$Ww7Sg>)t?gful|5}5k=R1TV{_r8 ze`#%-z6VyC<^4P=R6QJ!MHsz{eCtRRyE{-jw0ehOT7(X?j)gf{Qk7=07{tjOcJNF8 zxUrHv2il0k^d#aiB-u@vro&=3JIPgHT?w7&T^k1Mq7at&BxyM0N-@XfvvW zy)|aOxUAK;fozpJBkdRz450-yvv2I*$QNs7E)7X6N~TQ4F#i2&Wcs{@DiYCDGN|Kl__TBl~u9CU-h$T@r%5Gs+V|i?esNX z*wRE)dm+<80~D@PR2`yX_^Z^6he|6`KL2_Qh=gM6Q(x-kM+iaWf&gZM090xm{KOxN zY&A8?>I~ACa$0K~vgC0zkovmkjfIHm{>Yn{I6?#y;L6~HoYpt{TX!t)8+R*m=j25P5uq|0Dmm9bb=H{w;hPs$uY~U&AYl{(R~RK zQ~P?v)G4FP!q&P9mv)CMI%gIEK?Y7`RI1aRS;KzY2XeV}SfqTAe6X8@U_R;k*$;&suStkojf`r%w3Val_Y%h>kZxnr_c z3(H88#V%B?IkO-Qv;_GTO5{3>4Afo$d~DAMGdDO@!!Rb=+Sa5A_Qt7Hd^h$Ho^{$HwmO z9jzhmxYNvr*&&-2FXM-zG)ytWkRt+F$}fIrWHpNw>;Cu^opro{iJ_G&Uokrv>2rrv z2zQzJ%uLylcFHpOHD%Xg-Vm1AOPK1%cNQx0AZS;lm;5S9+Svg4^K!Ern@I&ubsD32 z_P{ktY&dbkzdA)wW?+lEG&DCGzY7|Z%?j*G7O!j6-9b;@Q+RWSrO{0B8V~pEw{>>3 zjBm#K@8lPz(a`9GgjWVdco+i^RogOrk?!vpO%H7!N}W-+SZ5_oeb}Qput!TeNR>i} zjr2{V>+nGoW>1c;`weFTIB77)NLTVB!ycWeUKwfgPVCY1-Vj}NI_%N9FTx&KI*9S? zX4u3coe!4Cut*1cERvTfQTRUE5AGbU;_S>O8FLl)AEoAHI7+8c_i-}Nlyujf2K_Ra zAm;Em%Gnjz?k9!aJ()Yi{eR`Y4CM(?2ukoaW2K8dB+*PVRK-1N!aEHq$xr~vis-lwjrm}9t6^ZZr!iHi zLxa^R5Z?y&rQz7QwHwy9*Jf3aYP{XBbSCf~+i2H}QwY3-LjySw+rpv277Wa8W=ne= zBeYLf4|u*h_HybFqRnALV8HuqQKH(U54}%L3P$qr-+ZB=%DjA35cwi z-(v!BtTYVdpd@ZHw-k4Zw&W1iDgmVK1*!}gwP)TlA(D?-QSFj+X7GY2R$}xom>5%j ze-63O2R#W5ykI=f{W-r|J8`AQT0aAzz;)A#!NW+^_*8}|Ork7FBBQPsjI5(#Q_&K& zj*`{8kW=-cToJ}z4y^o0b?j&B@Jgsf_4l)@N{Xsa7tWi)ym;~$j0|ACKox6H=n)mC z)kAaCNW~gUI{!&1{v{?gu<}Dyym+{>JWv0;zF=IP>^=3POz)k`!i5o$E_~%{f`#l3 z17-D;oi1!q6k1~Z@YU*QQ`>mD@K-k2OsfgjhMq3`p$#@uY=T#s;2#iNZ%k$Ruq7>} z_q^%%X2IP%qzWbm-%VJ$@Jy8fdQ_Oft{JpSgyrtg z#+JSXI^yoc(`hb7I5nRU%*P+ug6LS|tICw@^Ue9oZZ!+Le>! zc0TuvFKH~QJK4N{L3u_ma!AxLAMMpp3Y3Koh2H2=xcrJoe`e~Hfp3!q1Y`*Yf{~e4 zza30mj&<<5ZtT_K&*2R*j@wfXmaa#9#WK!fUf9ghFnEf!^|aIY5XHm$TrXVx&)R*d ziGbu<{-768gP~h6NA|Edya zH5r~6jp4=7DI`UrT>qRP%tM9_N!%9>R1b_i97_34l5sq(l|7Y#I1SKSPkHS6^}LcJ z&DOum&UZA+!~JBO-*<{X`8XSCxZ>aFN&)N63Os0TXvDI%$?r7bIT{H~TXHjR??A3P zSCEN{&%A0^e>UmQQ2i+Z%BQJQ(N`D|Em6Q)eP)>pb>XlH@*z(%c0haeAfG{&QpQA? zGIn_xIL#n{gyo^pfei)|+K{e4sSQxxTL zF?H;uqEz5%ZyEgV44F`d7=f#Um2wnOrnvw-MKUlWV!Dj-v<+B>;7zWU$Bt|f_6r*1`9rH6ExXcIK>X+ zWAglvS6LnzR4OTOf@H}&g~r<9N$NHUYg4;WYt{kbRFZjeS#&OwQ{DzrHU_NU@_jg0 zS(o>lpXT`d$$tYj>B4%(H?#dQP-SXEFNLM?D?9xB$8Ge5SalMQp?mLbd7ChcZ zLSuK_)HF4QzzyY8G-fk9!xP#bf}BcPEI(bga8ahMj(ueCImTwUCfBGXTC#8Q!HD() zAG>VTvoYz5{n@R_pDR3;#Q6iU=Q7?9-tziz7Ng66n}L-Zhx+cW8DmItZ9lv`;N-z5 z?)(EH{e^&W&R~7L)Ki*TZC_~VCGoJww zbQC;{zuhft*WxlcfotWF^}`#F1g&vN$b_Gp$URLa?@qn=8C7X?4bdm5Ex@_Tz$1f+ zP)=P}l8aBonFH~$9C%OP!ND~~GC80{STqYI1n{pH56K7l@Cr2MR(*n|H&JaEpXjCC zIJq-t%ck*ii_+y@h*DVJ7G`qLF6=wrD20T(;M#-!kG&R$E7H0XYdR^>N!dEHYE7ZG zue)@Tw&l|b>}A$-5V4jyMauSW&jIUUbx*@gSA6O;!d7Vz3}G?KY_@VByUl%Ot-(?z z9Ixlzo+r+xh?QeVB6MK2Z`H37%JbEY2}O|ad4Y8&)x_&CZSswwHU1B=^;YRDUT5sR zfqV{9m2~n~-1X7wfEcLzKkDSvG{69D!R!irG76kJ-|p+2M?>pAh54CGT-*wbt>kKBTj|0>E@J9?&wR_w zEP8vST?C1|cd>#)E>nFX@7_O?qmRbA!7A<1X3dKRJ7F`%4CMeqT}FgSlPJ7fnLWO? zyb9#KjR>n)?|;;!0pRX|cu0zrb^oy%jQb*AJ#i7m$;Pbvl;Wg=Yzc7pTZ;KLzrEtz zWlC_D62MR3&?213TgB_KBWR<0sVcwGq&D(4Q^8~O-scvnAUF@@`*4}bH+UoYN)&mN z^6@D0B^%iV8D%5;EAm(((}isl`;4nuJU!#Ghye*E@_zh|8P_}QukRrx6v75sZ=#4^ z>NSzk1?(isHBpJeOO;v@sQ1TG=O0O*Ia~ijE8V`YH^3X7@k$q0xrxDt+lHUs)9@O) zocbo=vWS) zjsGUkG0vXu)9+HANG~_%J9{iBOCMw}+UG&_#&1hPs1pMSi2tsAqBp<@!gucR(=)~T z_fV{E?DgEY+KcvDw%*O5y?ZS23zS#C%JjMRD3-Udi2Ky_doFnQ1M`L2Zx*b3KeLy? zC!1!PZ-Y$3*YRzI1dN~t(oKFwM;GnIczN^tJ|+Jz#*5a89?Z<|xdv=>sJ$n!`J(gd zwRi0Qs=Y!sA6+Xbl&0LCTIty{-TU#pk0Spk(@k_+y@A|z zjmkEg#U9H3Lhu`mTOBg@g3p+sFR=cAC$q^|(#8Gvo`-cW@uS!6oZfEhTKojA#ZT*V zcOmOOefFhj!SUs7v<_az1%;WPG$$~zOOy{>U#sn8u0ZMVIR24?>U^W(7v4^iI#0^iiHGGJJHTn3+&er`iQ58Hh~d}nW* zbNI^8XNc8{zWKRGb#L*Dhp#4nNPzCE&aEam-o^I^s(C~{;)FD&k%$S<&edGIphs{giqmY=F$ zr7`mvdVP^l<-ruZhxyx6@E74X>Q@OseAb-wu2ckANf$%i$d#Yby)RauxveiJF3iM; zukWeY-A~M3?C;hNh`Vvho=X0L{FtZ8x~5@+$n8dcax6On`7YMAjMl@i5QyM7K=#nit*>nTqD@FBx?)*tcP2mAUub#rQ_%l#!yY-00R8 zw4c?t2}JIx3Ga|pO+Z{v1=VHAgwoo+v{z41P7a|j68)Ap4LfSs2&h!!ZtrnX;4H4b zfT|JxDx*)`4O-7H_*5U_v% zJ{lF3e&1 zx%$Jg*5bJsmk^{{Gmu9+WY_%bKn@iOv>wW^D^-bO_X(V?a_DC2IQT&6&;{IDyI)r*-QT(8J5+=fn;}&8;hY>FK0-LI!rsA^>+)XbH`RUP^Q$|Q zgSlx`x#gOkD$&K5<}|)e>A`ruj3$8I_N8wF>hj#;hTBtzoU1!Cz-gCrG+J{KpaiBi&u?-fdJxUt}!nrUQpX1f$P1 z#_yv$n5C$jUPsN_+&p?k$bS0up8Lozjdj1c?7(dY&k8qsCOwf9?`uu@2{_z2$Fq>uKsV_v~M&snydcm5bX8NX3eZ@)x|4ckz_WLQWBiQuc~pygLQ8;6yiqjEO_|@39@DKm(Zf6CXSqC&y_-xId$TRt zWBbe8=deTN!RXG-{k-dKJm=hdTpYhzOw@|)a+yr!{;XG!yoR{KbR_&SHH?k zeeIB@C4!W!Rs+XF-3~17>=I*!|MU7o`6>`e8wRRtrn^(GP>=YyoR6j@^?fV*{Q2Zg zq4MA~hWowyX17x`x661f$_m_@@|FmyIMmfPQoqUo9mbz!`tvyG;>xDFc}1Guxib(i_Md~W@mdA{0xfW)WHH!@2UA=xXr4D2=m znqREHvm^Vv%=CdU(l zGMw$xBous5;l7dLDD7J)@6{85B2=!SoAhIJt`p(>T35jKi*2ai(o(;@-uf+X8q`lI zceFH(%XL=l%ZMDxh&U@o4}tJ&sVwhyA`eplc4PDHNQz?hCI4!|JmQn_qY2V~4N0eB z&U&|Ch7@I?@`m(J{z^$3(mv)EGaLNHhyj{0a=qaOUnb5daWoojO;IDVl&8Cs%;U>u z9;s#IQ?_vT5iWztd_M|I5Dy|V@>B$L#H+^CE+$r879Wa6%RriIv}X3 zH`N_SvXuOKTvJS6Od@IxP|6 zGOO#9NGN&jk%DuwokGuzwu5Z$;1B$6v=)f)zzWjhcnuBqkh!|w8+f7(Tp3JE8VZ%v z;T~P6Y`d|a3vXr4en5`v-FrYE!f@rD#bH*DXHR+M^dbnCXZ_Swx`xFOg6EC>CDgFZ z52(yI`AGve^#*XBoLBs08YR_0{Yt%_oL4v!`*tgL@ZD1BENKrmw13LCY?V(pM4e&d zDdy26TET{#4QQo2_GQaaeur5IU)?oEH8~MTC9zYL3_sxB1KJnKK@!pi)|fG<9`!Q6 zMKbOyRE8@)a2h}6hZEVC5>VZ`YMnb`*KMzao}a#Et!t?9OaJgQ-R7J zt+LImrVEcT#n&B!y|6NdB%_u?s-U_QH0I8!$LHRC9y(c6z7Xw2@W?B*Gtqz_*=7H z>MoPi2)efDF>@EJ-oNNxVbgry6oLb&(ZNq^D|BMN|#H4{8` z2^O#moZ>k(P$%5+hufuUC|a6h>|J~GO_{NFEk%DeT(=--mup#u_ZnWg`}DTaJ?&lg z6GKh9?(g}~de0P~{a+I@+nA>ZpQsbs6D3)gAP}fonJ&Ed1TDt`HFPUuB!>g zxnjhXusA3>2H(n_pPn#uccazq4orW#%V=%g@u|$k0A((&EA10YA{( zRIj(llD(zyWhD~DdFNpov21!$oj|O3&2)G4a1*x^z1S0vQ4q;N9`#I zYArk)&%5K>J4;XEO+&Q|Ml}hx>V~^_FX2!%@7sGw7tg!M#vGWDzpM_%7lC@fahq}0 zJ{o&&wF5C}SZ_*Ybm(nXYmf)ioT7N%;9V=QS)hG_efW#?`uO12t~brjRC>yWU~GY@ zATDzW!mqiAgmTgs<*;Ad7yxihJnt7aW0tfizDOO_`Yes-E!;J_$riXJ*RECfMw}YO z^RCz>VSBw2>M;OUZ%U1070Y#qDZG^v+1{@&rKhJpC6WGrAyFi%x8N?7fj2 z@x~2Fg;$`!!~RrzVCx$0&WQY@qJuIOb<+VVLIjqvkGi|^kK60=mr)+&uejFh$envt z{svO*P5W!ZlzoXUyS7s89*`N25xwJ4JGZy2&fSg0(;ADq!(92lVt;t_1@Hu*DlB8mEPY3x;JdkqdX6YkvYSj) zJ#{&ax0vtqIPY;9B@Hl6(Gv|X;sF!OxHD!nZ2KoB0Bf&F&1u;7Iz6wQ(y;9?3azD; zU(gwhrD0+f=*l3HMh)B2g^wju%K-Tl0{%=Hj;IgWH-5+L{k-Yd)l{dB3*iVQtNaw>3L$Qy1OCE~sZM zo8c2Ydh7XP)^{c>6P`)WRU4DGa}Q~=^L>%;75`y*nRb1Vx|H@m$@l1IwDHN$i2I^# z%TB*KtK82Uqt{7`?OZcIS7qhPE-(8VmHnQ%&kp~r@8o}wC%e48Y1cddK^>npH`(?7 zC*OP1=FcmayNRDW*4cCYdFA~#@fjHTtTMQBoW6sL8cROs`SIt(?=Jr&7^2;Ue^%I1 z>iId(FL-YE>iiY&-+JH5`}?f#CcYoa`mK0fJhAl6Mb_EQ6!8U9pl&ienDrS~6I)}B zNki#1wE<4pbZ0K(ed0=xI^HLW15N8{jQ0tr@nqro6?qq4WlT1U>wN3|Pc6#^UnnBK zldHcj)pW6)aNp@Q7_s$mNgbRZZz2F0B!Z3gZrNf(t4sO_6V-vGC5#K?&$v(@m@E!N z%Gqpq&CX%7(L0yTM(_SUh)~}7zS>H?2l{Hu^&aHI5-IQfe6=NT<=xmTC_v`7&kcVJ z`dheB3VjylM%d|CK^>jXEoZKTad#>&c$ZicBb_o0mM|0o^sF8=1NR_0m^vvqYLZ(w zM9p`ji+Y>xnT3!AH1*>v1<2$&k;y@`OtCbJ6>`B6bHW%> z?Zf{VqSTwTBKV*wp6uIoZ$8ViHAPt^XA|&!=-GyMq*B)_BQNql-+yijSS>$*QRE8^josk@<8H&kv^hP(?deNV{udJG_26^A9Ak@ey28@u4&S6UyQC zpO1dk#E-=#5L~qxN{nO_1QTCHk7Ij(XMUGfixfvRe!;{!+rkxHb%%z~rWtf@;?UEu zZW+Qj;CHuTi>3t|j0_U@0jr7!jid188oY4qP41|fE7e%FH=RDEI260AI6s7+@B*wV z=rEnDdRsl44e^AAMoYHp-A`rOv2Iu>{#7Fm84`*+y#RkS(Tg|{5d8F^yVHde;nsU3 zW^vCDN&xu`y#X|~dL8$gNCTYc4;Y=)ZBY=*1JXUKJrVSA;1!-R9qt#qzraPURBYf1 zzvS8d{hR9_%n9xe%6vkQX=KBAH{Rr4^pSooZ!tYtzTUn%cmYB-@O}3mH*0;GGyskw zS*3GH!gbO366HZ{OC!cY&kUv=$-Xzc)m(Qdt@C=7MB>6Brw6fv&zxcSh_C)Mb206D z+MKHK5+I?PM2uPNTipAG5cOqm2#DH#o8R}SBzkWC{>0!A#|#cJoy2glnFH`|lSjuT zJD->A!nAraV58dS_00VmQheJI|1Rtk!j?v=rvFwxwKKnyDNo}`c^WWx2;~`xN*{pO z{rT3O%3Eg3(@N%yRKw^#h6y+|pTP zjgU*29XCrZX7HMf)~MeWugL_#;HJI6Yif+eYZ{uq2u;K5oDIzIF8B5Y5<|PC#+NblW4${K5Pfses9XEUJr}V!9oDQ^FF*v#p6vBJ%u6C zQz(2)iSRP(elJf@(&v7Xgw!I7-NW`#TowV`(;vLhSIHFAOSVHfrbD;bwwr;Rk?GK* z2ljU81lysXU1T~WLqf4lp}sxJs*KOw_V3vrna*VQ@4#L9H!#z`yK?v3zcC<+z3ShQ zRGBXPo$ZS0-)hqc0OjQacIn@`3;(PBz5Bym`gaN<@xJqSiR#z0GZeZfK#r1l(R~Lw73C8^m<%l%d#iZoC4$DLB)spY~+@^zc$R#w3Qm3-WQ!>j1 z-K+D8g6XGHgC4~eGmXis#Snp7Y1D2LMxm2q`@D}22di2=7xoFXagqP)pK_Q{tX@Wt z^m_@ac1g05-}Ypyy?VV(TKI<>OozKUuwUjD->Y`iNWfz||)}#wGyeQQ(`; zPCn<}V&K(4pFxy8&}Lw_7YY-FKT=YG)p*XvjfRN<7!c{buoEbnY!FwGsM%z|^M&^% za@dVN38$`>_Lm~&ttVvdQPw51_7l4Psk$C*VY@#B%dTOkx`orvNB3b2|6JM!Uzzlh z=R7Ahq9+)bKGDzE_~-hlf)p_g>B8eU-8UO#W~(w-V$bQf???YQvn|Tr-i-cBU{U~C z%A^a)Th7iJsmQ6rWdHYq2BPi}M8z+zl+XI2aAM5y-EL|eyX@tOJYpR(Hsq#nlzCK^HTt537I!O9%~LVNYf$qX&$boZWb4jb!^ zWd%;+8;~qpq}{3#`cSntz6Cia^}JYK9r2KoWmF6)T*50|C^-POY$N~j2c2;*a(Abh z%Jh$_SL!|z)AoSE%rX4pp=4s$u8D09q+h}YkrSOj@v$Z4gvYCMxPUJ5B zK1qqb^ zFl-fwmhPB!miUeLzKm9)|C5j(!0lqNoG7}e>Ez$|)4N`u1VR~3&#-WdZP25khBSzl zzJF7H&4f4GscPXRQ*^xa58&dfgfCo}c7+AFZy3P6n{NO&kr3c69OwbA6stn9H304! z;?sp+Ap&FHUSaTUDor2?T1_a}fGhqexcw71kcyuJ0VcZ+&P`=83$E3+Nv9)lX-n3V zEgWC0wGfOav@){yOT^tbLd*pd6a94`SoJn$2>==b678D}4NJt+%he1VvZAOFwO?K{n#Kk3eT%2K3(`_MNr;S3edlB;&JmG zrd}0nuoyz{Zs-hyzK*AWAVS@uAVOVOL+(|^8;jo|Y5Zo>s%(6AfANPz7!YqP2Frqn z8jI___jK<)#d}Zi-j&|F%zGDk?*i}b^WI%FSLJnj?+)+X;=P-__fp>B#E5XHVXa!z zi{rKm#~qptzcDv;c=qp_ig%nwB+SBhxy7N#n$N>`CuZ>7y;Qmzd^dBB#dY;WOFyUL zo!S#98#~yPy=VMZ7<<9ujvCyR#@?~t?Ac6NS(CzXPeZ z!DsIZpKaeOe73{lGaa~@$wnF1%rw0ea4q7ke;gM~x7cjVz@XWNrN>rg@9CmgTVw$D zNesjSxU-uCxW9%aGl2Vd^4necS>n@$;=?JgT;+z*{w<4xQ&lV@A0xclEmZN*bIKjE6Wl>A5(Vyl?uBbeoX}pydf=2#aBkS#^{+ z5?X$K75#?vJUSR3i?;jNf?)gDdd&w|PIs;u(c6poo^PwV@#WTcA3nRR2 z3kR4M?oJ+3<__ktD693)h`ugQPZV;^QT?KpG<2X52u)gb84X}?CY}6gx~jBgVP5{( znw`7{$L09UZ=d;H_|Iw+{Ig8(ZRVqO;owDlkiL#$O#0i+Z)$PZLX9~4NV zbagr+rLV~Q3*3H(?MS=7gOlGKzNe5P8#!C1Kdsa6D9mhWHR)P3d}P{{EtcaLE3A9(*b%0v(a=fin&d;0iMkX}yPMpgAQBIOAF)-33l$FzKrk%(&9*0JL7P-u#J>buWISc4dl1Z4plXUi$_eQH;AOxRTZB^t1l`ZVW&;2 zP<^xuC z=d6{A;46HUEpO&l=5sOw=vOv<-*1NEd%eoO$%jC_bkABizSy&vzU?(O4lUDYXm;QD7!|0n=fDHndq-ddTZ@;SJUMW~h)0^bABlXa2=%M9Y@ks(g%Mn}L{-gRS!DM?EcSMeQ<_2;_t! zE!#b`L~Dldg#3xI2HJba+<>|>Zgr%a#vDc2RV;{rR>WZ}2-XA3Az%{G=2jv|2LI60 zA`XlG#!mzFEds-`s;0_*NvstC7lEACPV5wKN)6<@pYbf-5vu5@y$(~!`2xxq{HB3u zXFk}*LgD=9_#%Pzch1M;9OIG1Sy9=KX~9j&X55r)85C%Jy+1xmaCgp3ZK@uyKEN#v z7L8m;kI_e+lU$%eoBifz?Tyt4^KO9D1@dK0FvsSahyZ;gIEy9>Zo0pIDqvsls)ZW(4BOC&#jRHeV?zDA^t zAc?NEa%PeI{$oBX_u+fL)jnTV;e4_afU*VzBNYawnoDxdFgF^s-(V>aI8ftN$mA>qcvRG zI%~hN^`mp1oHrm>&R4|UdLt z)J;7R2dYYdakV;RE z+eaE{;1QwS03fVb5Z180p1(5-n=UFY_I76=weIUlEvi@tHt_R_KBCp_Kd7aNJoQ`7 zs^3sg>Z3gk9i=`ERcq)|zi;Llt?r;fok|$%AW!jGgX;NlbWg5hJf~b*4Iwmez`wp` za~j&#>h52>&!DbM-a(nX*##ZbQ_!)2m1g;?`bQ8Pl(L?F*aG%%_RnaBTq_XuQSAPX z#nD$L%leoGk>nKQI0fU;e4AM0lwu~xDTQ)(N0j&p1G0Gc#i+ z;F+=Zd!lXNdS(Q}@k^$hpBOYWlzuA2>a1vWB8$MG;rKP>;rNWn=O+$C5$7ThNql@! zIDQo*;Y0#n3zu?V^2Xxw8vklVSJoshM2U`$*2GrVly1>yaC~A!|C-plgd|_0{`&6^ z^I_DqUCLe9%jPdM!o;Cfv5r&xO=E}BynLERgT_yg|K`R&)7_fb(>0}S&VpC?2F3WE zbZ&W3!O>ToMr}7^ofU_w82RdQVq+<@I`%ZX+i)UkeHmw6&VoW>&URLWeOVs6aM!2-NkI5xh#CiZMt58as$NF!n=MZWS3Es4z+~4{yzI#I2+FJn`b}Gw@M9e9*l+9^qYtWmNkvwwBJ~*R zR1FdTX83UtCTwbBO#^H5;oQt7Bib20kAmoyxHp?DP>}o+A(~7kE_x27R5x;q=*I+_ z7^m?#!od4;=V}`^n+4{)H@Hu{qwN&Htbu79QN!M(8d5`g<(sufgwn0G!R1sy0eK94IRzo~I!@SLrfIcB zO30&x>I@5Wav%O#VqcL&1J;cl=1(3Ag$SPnZDeK2GY&UF|1Ih7&ii`mZd)-&n4*;Q#1lYFO|1D@CRx4s>)J5(OfC{eDo4_NJUn0B@tQMVBO0oB*ID>=J{YiS2FzSHmsVw2Qp4Cce|GyH(G2cQ`;XhT{l})h zW90SjpV(+K?cYCjNl)YJ&NuPB?ZtabsPt85{`WIY{w^Olk3A7}RH=2wo;G@5(Mt#x zECZ9@0w%v#V2Vr~7><2YZtE0--xt03g_{}(u0EjJmtO3%KUhn5;-Q)0gE<0Z#RBut z$K@)EeJORU8Lr;(Rz)nMx0!RdnY&G5mEIC5Zp3J#YKyTu_KJQ>kGG2tzR)wVh5=yV_lQBX@!Mi0?$#bZ~;#b39t(SM5%z);w00n^aOPjmWZ?d|x4oH&Dk8YsSbJa?UBdaNnf8w!LGzF2Q~P|SIWlzJb01_Y zys@~_=R{8;in|0j0K5+7h0J4vrSFC+{x$28P~y-LfqJ$B3ivUpGT-m=9WH%0>`$3_ zaBqoer2koWUh;NUhV(JP{oxoay(Bu*z1XtkEUg;@e_<9!w2ER>1?6y+-lVOvX`RM% zNy?-)j^l0k&)_J)0sU`&2kOt7=0r;s6ZsTg{e7^T8E=36c3OHZ#h#nU9T7~o;NXSQ zlVJH6?2E5=yaKU~Kz-+M*w7aCZOfC&0rXe-CGTrJq5}C%x{4HR%$=a-PUA{5vW1O# zLsiCklG8Yy7NACvTLmL7E_>#csk%P+fk;a2gtP6aimmQRR-QV~jtB90-|PhOw^qeA zWa4L(r4I7q(=E=5jXmK*dxR^Ni4Qmk0Jb|fU__(UY24DENmxHCbi5~{hbA_MxzKpYD|z;MCzpHoNlF1{}J zWC{q!{-O2vP0Fb8e`IK_PeZYHfC$_zT4Yv@Hfyod7-h~P-6uLxI2$f{%<+dJpD=+N z?4&Yx*D#Q*$w_`^#cIlIS_pS*G9>xv+x{ce{)ZRX_NVdyrN}1;Qtnm4`Z+li_9F`8 zH~|UPKaw{SoV8vA9};WFlBr`1ye2~a$aY%TriNk5rF4Cbe?5C(Wc!I&kR;HIY?P}z zoP7c$18C)QjPN=^QnqADP&A$dy9lLb)DV~jMl64U(Z(z=I)>uIc#u|0qO-KdPv@rx zIGX?*6JZuVTXV>RnAKIWjV3~i-;+N}zrPWaM`bu|mfZT0756cYs1Bo=wR0UPz8Y!WR*8 zsTcBI9U)c0$-i{Nk=LI&j#mAKR8I6X zHPdY17VTaiu~Red6Q<@Km=P_RGJZf3E9h}nk2J@GFsqTl_I?%HOS_jL(IsHp+rs2_(bk; zLheYSQm`Sy@>{_2@~K>%xWI~u3#KlzM-bckJCP0s2;SFe{DU1SsVe&q8wj+N?!ZirV@na&7r`{-CmcN7sx|ga*Mg8PCsf7Dnp* zGJQ~kjaUU`>n0^-8Le8THSI#sd+i&r* z!rX7Z%wpUZ)h{HiKjrK|=%mQP8X8;ByEObFo|0#FFkGO*E`J zS1&olCEd3&B~j%I-%*u=cbFH^w%*}zE2hY;nWULYu>-cnosy~XoZcE0VQPHO4S3Om zSCZTP;8m}z)tRzV7ug`UE718yTM zDK6wOkQ20OUVf&sOfm1l(70bVW$eU1+({`2w?naKf{B}rbR6Xd!q9zt_6gP-d(lvx z;lk5TM_}wU9!VWi*_a~t?1t5t?5r3XiVwmMcU3V5$SuK`m8DA@zla7ojcCQ9AGMyF zxKkIgXm#?kv2o+<;$XU!3y1Ye69sg!0KrbN6Th-MDxro#w7K^zP&Rm zi%LjP2L@Sly-MrGCBH|7gk%v4nYd$<+SiE7qAoLyZ5&IKM=y+x-Ttr+6(n+ngp3}_ zJfyfHd0=sk84q;rQGsSevlm#^QR41Vb*T zBD31c&PxbDJ>F(h$rNBy<| z&cbRidVSm5v6rE0nTVIe6`N*N)c9Ynp#W$8vBZWF=Rusb1P81aCPUIkN&H6V@nb=v zaXOc|ujjR)^-pTF(cj$^EOn(VtrlULDs62}(=7cMM&OR{s2huCJB{ivptMh7!aeod zhs`KROz5cJKG2EWPk8RzFbnvP4#(W!$D5sc$wWi`Hnv%Pq}#enEeC z-QR-8b1IKOso#v_cUrGbLF401RNxG0eEeoroHz$PaK?N64R3gDaUyREAprX&V`Ggs zYxQ_D8X=q+9UjKfxw_==A*ewr5sIx%4XV;l{R+g^h9$7j^javZJ%n!$!rE%Y7l#`D zEz#J_VX5*eMQINE#LOtFiM?t7h{Y%A2^S=LI0=0G{u+fH|lzfKv z|0Qc7CU1mTgF>72|G0Y-=%}h};Xg$ZNFaENQACuWQ3)a>ikdKJ3KFP-Dg+u4Q30Qt zc51~`6@v;ERHEFjuGY5Oem(2!QM>JK``L|%14+;jP%!}qhE_mCZdnfC0AbAc+vnU{ zRf*Wo*K2+MwZ6YDQum&F#(nnLXHRFJ?}(iau^VteQ?Y4Tr!T><{|^^&ai{q~2%(^& zgu8%m-q??{mGaPH+33R~sbQR|fpN0f4_NQ&51bevGnW`h%&!Gjvq}y12UuUFMeC^K z@a@tKsU$H)ctTB-gV&0YsZ#eW{tLA`D5x{#Dg9k68?sfYjh@z{%i(rkre}}H&Afo- zSa@gBM2)wQ2G&HVAHmRiwiWbHarvB7Yu1~RB$_UL-pLMzs-lRAI8!KngFl!~2{C$A zpbk`*4eYnZfMw$AJ`@zLlm-rn+3z18h)^R+?kLL1v!H9(zvRkr ztP&p+v1lyr%?{`Af;Dd@9%B$TKWeO6;)?Fm+~_p2U)`l)pJGNm`A0Eq)XX6bG4)^Z zqDJjC&?wo@oFly_KcMxIA4fhrCm z6DV+K0b19*LLE9!YlpgHkxU6_uPKV({U{FugFPdSPbB*~_!Ylb2bBeC3qGc9XKz1x|Y)_P**2lT!3t9Z1>v3O6?y~?0Om4z{rt#p^47u z&UHp-$msf~>4!7E3+(Z&leWE#Z%}%Cy}$yM++H8bg{ppKkO=|@+fk!&d!w5Q&-`ON zdBHRNv3!Z3+@C(>xR4aZDirswg{290XTNCJRp`xcS(j5+N(|Gn9~cieu9giNb_0KY z{VfxGoM)9|Hyml%3=V_h8V|<1OLqjyw+8zO#=8X#!{G%q7BI)VpLX%Zh^k1%!a<{` z6_aI-E2m{_{-R}eE*wU@=u|z=;{B1SZy~Jb69>7p3}0U&OJ)H80%FF2btuxf*KF#3;;N*r#ctEEM#Q>4hR?3-n6rkr)8s zHR^Wqj{O%oQ3a1?v{CyYa$DB;sAP>m5|UTkc{vP z%HPRb+{(W4`)^AoVyU!PJO0TAD6@;N*m@R*QM(oOhSy|IotsD4S~v9$NXSVID*u%# z$NnT%zSfSEP@|3VA1YJ0vZRoOQz(5vx~lD^ws1PStPm1aCd)OR`(vj*DDCDOl}LOK zU{fvzYsOL1DtJwXmqtnZ9GF)k1;l!({{EDFh)w<&{f$j!oo@^FXK_QE3@`qU0t^=N z@1!5~&k0Q;RA*}adj96}V~C4>AeFF;N6Ru^5Wf}FJKnwK?D(w^spA8Kd9sWNAdwZn z75a31pb^D~Crj4wo9YJpWvt;nM&vOP!O%B_PW?^=;`7HQ76N_T1Ng)!pRZ;kk=-32 zctu7^99hH*3UffsS`W?FrvZXj#-23$)d5&Skpx8Id26Xsp^Iv-Jmc z*GOu%8u5L=BCt@zDP04THOro?DIF&3K`9(%vO>$gZlYw0T&I4sDVoE= zpf98O`MN1u75@4ul74rZp+6?KJ2UkE`g*z@pB86^^m_VZ=>Nugda2->P1c_!PC&e8 zoS(0otb987Z?7kj7t~4E3bhFdRe=PVudiXf z_M#$W5Nqa@Qs^*+Zl!WWqB4xeg^|!s(SQycU0HN~upcJ$_%zqbnMK3Kb`M^{!P|nu zB%Ib74IzuD6jz`~+9j0IO$2@Vp3fRcLHw?4F^4;zPk1WZcIlq#}w- z#;eIlE@&UR9=RDIkHA8>eQHKq&W5v<^*q78s}PYQ8J`lTQ`(0jCpf?pU4MNgPH3>< ze*O>*W?m4LCU@raY{)2VCGJw~{nD?Fi;-89FxEP@IgCmVI1AVQO^=s700u2zp~WZk z6Iuq1oydMzA1s9{niM|YANQiDnhLLr+uW6GEW+B%GwLSuC_Jy)D%%t5cunmRMr{+7 zDfb9*KBKcorL#FCT9?z)rxmtc!>9I%Lp^ILYOhC-;!d~*L9uas^~W!6qF}OEF+?eO znnHT{lD&fL=&Gbd4=GWORS63htXRAFcj--QlhQE=$~7zyIE7wFyh|SE^F4HMwgXM( zq0n~wO#G1C!k3Mk%hxnNE)epLnV83(G1gUO)c#op8%?@uV5D_}{nUX75Yd{Z8Z_!w zNFF*+a;BQ7g%W+eZbSI*r8^SeQlRs!k*!O~=YTqRpRm9AW9NmguZ+*eoq(O{9IeC) zx^qN2$XHMDX=_pL1^qdD(B2^D$aHzlHs7K57Qj`lXJbY*UmtutIqYdyVy|?hyS!k+FGIq0v5$eb)?h>gr{~a+{T- z>k-Y3Werkrw%5W;dY{71PY*et#&g8vl!m-sKbD2@NUq=evq0S{k? z|KG9k|NZoA8MSXpZ{s~@N+&7HxYBFjK}rDd%%p$zk+C`mTYBulDxgjThE>}_v3l)D@P?BnG1rGV zkR4(Z*u&QR+jK2E8Hc8E+QWsM&dy>)lXMW$88qs4^OUi}1pBJh#T?ozD^X7dTOdx+ zf3+2{+lq>yZ$8YtQF|}hD&sRCl$@M8o2N&48W_wKroI=iYvt95o=+h-dXKr;!K_1j zjYvOIA(ESgr~gf&8*lcwbO3hG3#8Z!Bi?f)hpDW)Z&jnLeFJn%bmy~E9iCKr@8i}f ztS^*P_8JM#W$pb$RFOY}?PnyGd87Tp04S(6Jp%_n-%+i_sD_o87{wI74{BWDYfnd^}sqq3RtzMPWQ z{-kOPkFW`P<;pwq5{Gf5ajH0j@_7_g?2WZl*amQZ6k`D{{+Xsc)RStz zN$%1NNayu*rL&&4U3Iec;0gZ!}kBf-K9Vk0-36Lzb;zI4YpQ8`4mxXg(I)MN1O4hz02S40jDGH^ZR zG_)(T+?DYuFLD6(RO5kSzWL+*9z?-*#SI1D<=la%eYamu4uq*cGPW0FLM}IeOms;x zqTgXH*c&k+sbwS17LFz%R%Zum2Z6QaaI9-iqubW{YMXU8>h_Y!M%tBg^Ac~!E61un zw9Y<&yU8=I!~>E76J03F_7lRvi(G;l<$9VjR$W^(#A#w=E!<)5$1|1u_L}^#w1nMq z^dQsIt=`$O)w!uwf5{qFLWNN`g~W>5k3(lU4V=ap9=XEVva+d7s6i3gGINZWMh-zM zYxhk$M;BeY^#ie?p+TuTfE&~9c4%awK}*CcXPG(tI_vM_hX%8j9$i&?-l4e zpx8tFEDZ{EbX4c~E;+>Hg+HDRv13xbB6LQr+D#gg(7LY@yyfsv*m>)2lGYFvz1|+U z=E1-4ZVwM5uy zm~B9Mmi%;@s^3$uJq<5Oan0Ncf;`P@X}#um)ZVj@g!JC?cOYMhHc2t*>^*bXdr&Aj zd(Ry99?>RwD5Ult)Jcj(hd(zW=aUL8R{EshB+lSXo8%ChZ`SaAQ5Ky8+W%q(9MB4n znF-eK6-6Y4tz>~WX2Yd{zDeN))_L!wuxzg+N|-!RNk7VqHSAgq(}$fe@qRbWaO|Dd zlh?>sZuON~sqAKJPE@6wscPYPXgY61(F-LYH0Xcktlgf9O8T@d*W~x|!)M%cwm8ENCm@w1uTo$d}d; zB%Y;k=AQjq$*uNmr8Q-Zd>bToa7QS~MroL)xF4CaHlqAoijnzNaM4Z@O-STuAT-=5 zEL>-f^nxXsWmTwNhi{@38tz{ok?lQ4Fx6lBj< zJ;8ThJ~$|R0R~c zG?39DWhr}x$ZvBUdKU7gXxVuwTBhu+{TzEM$%>{0i#yY^1*bZ+>`%(#sx%Q8BQLgr z9FqO)MF6bv_M&+#|BhAyCAHP7&Z5Y}839Kt8O3ZaOmX0qmVcC;5y<&t=(P8Z|qGytT%j&4X{`hUEvF>nt;u9YoJ21%g^37}39(_LB_{~OR1&UYA$O!xL z1uw<}1NqBXnxgevzNoiWhvI;3JnCT`TMJNsLmh7n$kFs9vVnjXVMWC4?7kjT`i*L%z zvO#CL*U17X<&3v;qgLW+N;ut+K@>?wMNxjr7rV#zOC@PdPa>3VAtZ&~;xvtBv2IKk zn%<$1D{*)u!ahNFHz1_s_(-^Ro&wfg6>W;p@-iH7^+Nj7-p z)Yvh0E4y+GzuxidL<2@I#Ixv6a4Ct)^}F?b zR&HWsMsY!!WmWckS|iir7-W~Yor`${_l0lGlQhmjgwM5G=P(AXQpIJdDn6Q{m&ZT( zkjnLv&ecDatBG8RKkC#U`fM-?I{jHbtjH|e6Gnm-`bjRe9KNetsQm(tB)M3*j7x|o zaX7PH+-E~QJkJ4;Z26<5FrCk`0;+J>1D?(Zr9=nW!3&&jSjFT~vnkT-0c#*yJ^f0A z3^xC4HvdfffgRwEd(Q49=Q_IE!oNNC@2}WfKj*?Ur&zACA& zSzwk{G3^j6Rkm1A3Xh^w!KN#@B1dDA%v*U&O@49$k}Y4ys%_~Kf4lJWBV4X7~nlp9w*yidvK?x6xkd4hOWNir6J9S@9m9&2}~rqi&W^ z6(Jd;RR?hyzywf8_SKR-k3kTr+^WwgQ6wesoV%HCC{{xHySLa+Ae0En5(oum zLH#Fb!b3`$Sfpiky{p;7vgDt*BtOP)wH;1Hr~v|zHJ3~E9G3k9$tMR6v}Fu`x|_YO zSLA%N;`dP)*JV>{LM=^)^!)js!pK}JOw5iD?uv+7VtmSzN{O0KmI<2wnCPJF+gGJQ zGe#hiCgCs)qSX`V*8P?_Pi*3kP&9}C4wWdmwjY%Nzb{!rohjOqjN0X#R+^+y`Ku&E zo-cZW!6MzQqN%1@_2we=aY>co+$?}t5YG3OZ|4w`^ssolHyhB)ycsAhWV(9M4!r3N z;`b{h1y1ut=($;xXNwKD_VzT~+V#>XzE+fJ9N$X2IUulJk08s|270uI1~a0+2vML# zg%N+5B~667J>^RDAx|bWS4uub9$LO6rE=$g&ebo%ruXPw@ri@>YE6eCDy_DQK8A$m`;ul|Od7xFD--VP?Iogy&TWZiDp3o-A5T zVVT={^~-YcxnA=Yzou-)5{7kL@+rGAG4v4=?RppQ^O>dFSr7af8qW8Zqca^MZ54m) z&!#yF8ns~nslY`XQaQ-Iex}|eM9ZNpGc(D+aTRrXq|JJq&vc(DsJ)C239kQNe}Uc4g8f!HUVB>*j~*%Bh(s z*Q{CT+NLCjt=3m$X>+$%D>ZG;9BuD&{Biy!LwEdfJpZ#l&T{f2ab)`AELdRcPX3gv z&hW9BL#*fE4BNp*GxT)=LUFJ$YJbGzzjCq}4vKum4=OPdwCLapRfX#BGZrOa-^|a~ zxo%9Iq3Fx070+}@B&eC0P|-}3C?0;!rku(Kc}Dbef%aI}0;4V=pp)%=lG`7fRH%ZSpDw1YOBE4i5m~oPSA#q^AsC@tw&E00 z>rd3-lliP1_KmuM(n$33tPoo)RN;uV=}n;u_ZG>_u(&#?v>eljH+B`fA9_BITC|6) zt2gTIKT84WlWJ1*35r~EfXsS(n!^8DLss*{WTSm)H@wo$A6mx5UC;W~MD-8k$64ey zHM$#|Jafp?I@-w-Rdt4{l8BUQx6~HC^VM#-kEKWM_43o1|EHXCu?Z6!NEnx_mGkm! zua%CL5^^Oi+gnF_L~7@ZpXSOqr`l?PW+Pg_(iDBV!&p_uW)1MPb6T69)OT6lV(p` z3Axrda&!g`?DXt3>Df);-cHYi{M?p@$|)v&B=|zDNbjW|CmxWo*+~a!8*65mbE3)je7p5!8P(ghtEl6{%lHWa6h+ebq4oSowrx2 z8%^oFck(SEl%LEjw9q-u49F5)B;-zT*7{Mp1b8fqoW+DX>RM#Q1RSFxsVuL5zN>aM zFxRN-OLA&(0z_&&of?x@(Uz>m!C17VCds^yRyqmy2P6r)e6a&PgH8y+d5#aMieJ&W z%2T-#lNpil6SR`*XQgdCk4SFqdo(k}^_+!&6}Lh(h`&&@?OR5z*jb`&GmTnt@`<)x z8M-Ca+)D_`bSk%;PPxfu-A!|Js`gKONESKJ69&vJd8mMK>FYZZQ^{+~?&>~|bv7V= z&w5dGGrR|rAHf6A9;aGd#S697re-fs2KY#3mLKXYeWXFCY*sQQBTGL%hgH*}%O;-& z;N8$anSdAHQAEb5yTvAm3bmHV*LcshQVfL7N<5K4RHVXJFR}+_Eww8wwkv!` z0VE`5Qx2bph4jwk-vV&u-}zTTS@|bre{BCg@xQ3=Pw3cJlfSRs{_isS@jl<=yZlQ1 z&a?BoIwP->mN^C|Ev1ik{A=-b-Q>7a3Nmsk0}+5pb^FkN$iWXdzv_nq<|ZPd$tkNj z1k~$$>C|`uBGOcM6)bRobHU1xxSh90dFomtPA&7oBc+JMv}>s02t$2nnVjZYB%9;f z`)c4sKV>Z_vB~<*ub`_v9Hf*b?H4psh}$qpEfHBzhXhH}N&)2^G>9 z(J1%q3o?sxS*mHCXm=vqrSxOvqEh0x3&(o~OO=%OhLDr<>5TQW{}d3W=2!U#D-UXv zL$5nCyg~-aO}g-k_WTa&G`~g^ZL|bU?0b=(<10GO@mr}mepTj}lksHlG|y9Ho-6e{ zU(P&t8|BP%-7oY!+uUyfWf}B?e0K=YVm(C9yu^koCauA9unE5983A|ngA-HZV=oe2 zSB0p)yy7`LO|)UN`3z#9XOVf4K;spi{EK8NR{xqq+ro&{9AIxCN+6nu`{2=0*hQt7 z<2L?~2e^xOdHAkx(3V*F=1R?~%BiVZCQ}Q{`3Q$C7vwh_&X-UYzQDhe4 z5}yCK@^N2)GOA28d3fOA=$ATKWeNY*mfJo?1vf0H^XELUxx14&8Q#q!&0u&>^ zc{Pam@+Gt4GbX(jpfR7h@gYKe2G1w<+c2*vSS+&p;&ae8uNvED!sxNReCGDhKfSIm zy{>nXf6(#d5`y6={hhCTlR=0+h9H+l;r9LtbK#HoE%udfHlk1Q0m@U*W76mXcW8?j zjT0(ZIo)n|aK${?2d^TVKmPZkdI1vnR*|ls?#f*t7e4{*baY>G1bd&_MU#L@RAbEo zO(+$P+|l~3M&0+RF!2}Zl>nCR5W;w)>d{B4i4>kame<^;^};zIfx( zuHQVEhKF49WvqxxSIajCzs201CZT%ccehU%J;?1dkA&XwW@}wx;#;x^fzDIp_Qo`V zs+&y`PYY;V32*sEuQ6#OtLPu+;ihflD9=_o{iFPj$AS($0*{VZ8hOP&Xa&#NUip9V&c?l_9$XJ=b-E7rgf@dYJ z;}ajU8;F-r1Ucu6u|kJ{tH_ETE~(*4#nFa34<9{TVblsQm>ebX9l?y_!6Je=ULbMJ zK7t&3%}>a@WAkAckl8(yV#&=1ete zld8%i30#(_nph)=k+kB()NaqIDI;)QHeLUl>Ux{XLwwld$>Db7zgZnWoX{Oh_N0%i z;pugUnQhitNohU2u&=x++_B4DMj(!fVx}tLTxWDD?YT9a zUSFESz=}Ke|5!p|9#D^5ypZ4GAu`ITG87R36D9gnHqj$J`Hd)%P!vBb@X}fc9Fuv` z7Om)!>>9tGf_XCt6c?tstQnyznEBw@EHJ(s_lrbr&)z(FQnNQhF2c(vw&Y>JrB>%QJE#qpKm>kC@6S_eC{Hjf52zHbm0pU36c+1 zx16F+M@IP*~~xB+QB@7{;wxoUSw=nd%ox%07(u^qa)Qks;ZF>ssa@+ zs4FH;VjwJZ`^{xU5Wl0)_T`&6)NfV`i;qfgKQ39aBX=;S2nPlmCIMq$yx5G@Wd^h5 zS8-x?!p$l{c5L+Q)o*AO=nf`I=zWDS7KB(uTlHT+nS=5~i7mQ&RUO+J5qqeMNK#zld7-h3jWW0YM<-S_};+42<&Y&_V;W1^HM(rYadVuqQdK=JOx zdwk|mg$O|JDKYYh$213RIZ+-?)%zDm8`N0=Zdoy+s~Cz3e{>0XDmm2dYB5#}<2g|N zDrO}fK&e4Rs8I>X$v%0A!vn+|k);_blIZKQG`%d%Ym0Q?^*yZ3&m}$y(G;104gpG7 z%FtTka_Z&dHMtx2MRW)f7$elV{UbRko~Lxm$>po6X7v`t1o1IgGl?NF~mQieT{SYGxS<3aZ!g z5tg{uV7yf$V~dFX+KX>UC{yBn3o2HP@U1~+%)$kZXhrB*4jQJ!TU8ejr`9_yU!*?$ zkWc34kv)TrRY?-BaS{2Du!lPr`u*mo0O+u2Qtzj=a?%uAT zLuLLa`JXI5p^wGNX62JGKj!iHvYpZP(}LrZH;~YUy!r2#pV)~PB&U*?-LMxT`*EfD zNjiI<zMawaYdIiV(?34}yuBtb+SC+1(JeUI z2jg2OZjx~Pi5r<7b;mIg>=IY;0?YHaGlk`8w5FrPmf-WpCF2+;Bjm0A49T!5aUN-i zA0Akw#P1mm&;5j&Lk?2W4HL|tbqM}VNh%{0H^paVT$P)WB|6_$=kr?Vrd^sDg(Xv^ zpLISDDD3b#$z2|~!<`11=v@>?bTR3_Kd$Y@I_SfxF}wX2K?T)-ZeK1>xyGseyH4ZM z<0>chS|?R=0d|+pbw2-+3X^|!lmYyTzvg_ArJ%%x*7vcbY5P^^oD6qtw>TlV#T}v7 zTw*EADwJRf#8e<2;`**Ka(%LEKBu|}NX||%eW-KhOx;h`tg^f%`UWoOFlw^|t>csO zWM~*D4p<9EkN_>NAftNlR*W~OHB>ZBRFhhf%4aDs+l!n?DTGDf`Q%RoF+_GvN%=f1 zP@TegB_b8_pLca3e}xSY*B03yaN`h}FPl2%!^}zYPvkR&9^+RQr8I;Z%=XscgD~pO zhxzhBL=q`cpZd@*`*bP;n6qU{rABMp*<_MUO*B=%CMEF#f5Z%k3P272)C*Xv%6C*B zFiVIjP+C_5W|(Tgb_e6RtN&BRtoup#{|nW$fMC9WKo~@d+IdM`AgPO0Y9>75{pJkR z9p!*LWvz?Sy~NXq;4hq(?e}}C_N?wJRWeHphAU-4*JMw8Oyp)~34cShpx9NIJtn~q z9Iygpaa=5Ph?6OH?+QWqZajnVs{xT}bj_vIY!x#dDFv0j&uF}Aw>MuCM^R#B;H&5Z z^!fG*PB8jow7gh(HkMd_8!2?OJ#;Bo=IoUz70rk!O1Ls7MIVJb>3CnxcLzh)()Z>3 zoL9NnMZ!j?v+Ws;%X+zr1;eB%WM<*LO80<9FElRp$tR*@bi>6!ps|*Z`U6><`=P}D zKpK#{qCSD`?^wU8J(h3XSb(OzUa~nWN$2A`&PLzhzM7{6?%?52rB<bOG)9dEfeHVHN0BDcSIKS$?lio7wy@4~vxCF1+7pWF(tTnGK;BD^}JciJU_L8?fq z`z`-+5jGdOlg+xn3SP6l?Ttq53WY`}mAPmnUO=4iR%BK#jyRIPHcvho69~a`#CwP! zO&?wkLl7DuUY~Gn>Q*eV9w{_0`exFN<4DV$Z?~e2svLaA%&#rOGxD&?e-?^FKeuXBVn^8WY89NE?~T} z#fCB3C~M&LY7UIro#gVGRa^aLco#7~6$ZCiZ+%-*ms-fv?qD%W-q588O`Dzb0FkkM zvO*KUS9C$)&jcUgOwUY?X{tKpk}#^Qf;Q`c3z@l`(#^~fXgb&%tFpw;$#7R~Wmn`# z;DF>MdLk*jTYs)Zyt;3DjE=)xn9tau(sL1Qzs6f@jQEtBQ+7Io+jrgxml> zS~dF0eKL*K7qFAu*C#L*+r=ZxBvqZyomu2g0kM!vN9RYD9+JD};(@K!+$WFY0mmT( zy8+;>iRog2Hd{qimKHEy(U*(dg;(q$qb{O)c8Guqp?R50^kAr;oCr0mS}3_y`r-xF zg40!7d67}B_QwM)0<))uxs5Je&Bhm~4-M#u}@WM;_os4#S~>-KwNK{p*~$|*t32^kAA71>5H-I5P7{jn>zddojs zcp;6q$jTgUlopWG*6f9)QSvXdrW{@YV%n6S%ZkoBw#cUA<^3dL6gbRh}e2J>DN#+MX54 zwH~8{+BsC4nn0O&kD=rH>wEn)-2)K8s5tx94;q#2*3GhJ^wazvZs9R zG47ncOa5NHzuLHcOSSPvqrCM}Np3r7qc7S}fnM%dm`G%AG*=r78b0Bnq1tOKBfdvN zdcXE&&w)rcf`=Q!pL?VC4akD5M;GU1amytEY29+ITHTJtqYE3tmv~(}#I1OQvGPTF z4P97(kB7D&VgBfHouMCxA zyRyY74%CBLPr)2b7qKE9*yWE`J!O4?BM^omP7zjt8HyHIiWZ2DMEFgOC-K~*l2#BY zSlkaP&cEkuDw0apTtq%=pkCm8F!&lh9_oZYe~d`iVgU<`1OLB@5Lc!RCUVO8amk*> zi$Yo5+~Mtm6DLe3JHWl7$uq0=d(A7`1TDRB>Rlv>(WNa}p_?FD5U#+k^ti)M32Rf- zQ#2Z^HE`^Jb*>a(H=H8ypJS}t1+D@A{Tnmjzv3EMHq2IicwA}<-dQ43z=k#xbD@uI z&$oV(n?AEK2FyiyK9hT*v>7ZBrcS$D0FrqfB(rLOWc8Ns^qWhw77n2Qd7|BKvziu@ z93xvSJRsSH$P+HC6x`C(X1#qqUtGjYUJ7?n<@Od6$EdB#qW)6WR-9taxL=iDI=~;h zDbLeXIkw9S)t>b^V?SL>#9-*%(gA>FztOAeF>n037Joeam_NSsspKH&@7I>V0w;ue z&=}em&>FQ5(f7{a6^q-39%Ny^!^UOz5UVKxLS)p0EVL|Zk?>eIF}kG#Fw~5N5=rv0 z`6P4G2Hlft9v)3K%*p*uEsWE6;93yC9;dF*`WdxJO$qTwBrk(rDpLWlIaq(;c#p2BwC^q!$qC(dou68k=F^p$gm+#JkKwyX1iW!<4G23@!Wi9gi%lC&S z8P8!_XK9kA`%`!J0pAMF%j06Y9ccBkF=B|drn1)VBGQh48Rk(>$-Is)Xsgb z_bn>M%LAv`S$Vj3varW-a7(4&b-i*d0U8OeILn=A1T6622zv;wZOhxUU}1x2IJbfh zuZZkJ*YtX%V&%O>7p(0&W)hM&9?N7pciD87_k;OamiTv22hpPxdHTo z%z`5_3yxf?1blVkl#^%0Z24_9XNeHu+9vnl3>O0M)^$vR>!>=L7S*AG8K}+JeLo~? zVXiy5(PsbE{qxv|@+BsRh$s!*DlYqiQH_?}SKZ8u z{(zf|pm9BQc?^%j*H>r(Dc&yI>)&!J zhYF1+fTmH|xURI`5nSwMY=7XJD*-@}Cth(P+IE)lz~5NRsIhdsXutiSu4vQL&2!i;>*-s?7LI%A2)nx@=PX0_Jicb6#dgVdAh(zB~Rld%ME}%^rL8WUeOA)WD@J?o>u#{l9o0DEO z+)m{gX6T=4h^j-4(WVwg6+FLobND=<;MyO2NA)8yP=-^l2J6pnfjoh(%Ab2(>1Ik0 zC|OxpmNyDG5+A`xh+2v;ewE1Q@!T97>Es!t%v}IB%d^tSRgfK)6ulk4@FJ3(Z(d27 zroP4d-6;h?<}xc#BlJ20C2jqI(zjR-!XU$BT`umzP$g;icDt<(g75?V?G6}M)yuWo ztQ?xPromaDh{;zs3@foex}H7NR@{(~7(oLWjq@n?=n_49s5e%@+UwVo<~*xUk&(3T zlAOjft_~Qk`dg+pD!Cqe5PN65=eHSW>ZEn``mWcOByfSrk{hzU@_KCojTndRx?USf zh{|7{?oh#-V<%YPL-sy5+B-0s_H9?E8Q8D*?zxJ z-V4(27s-2G`hAqV=cL~+HV>DOL2?%PBU`119LCHOI zrC`LhVX^96QjNt?tc)YPX4jQdyEjej(LLEmhI<~toMjiG;}g4QQH6@1jOxFd9&6{K zS|~Tn$V0ydF%SO_|DNOf%Ncnjxby#1=70Nr+ezwFizfO}*;nR3F1=~6`f^>EOv6p6 zY%tK|WK{yYQvJ;>-%^Pe>coN$i5Ka_ybg(@bYf12#ET`7`k>o6S!#YZGCz&c{ev1T zfLqV}wDkxMZ>r2u^OK|IXQs^0bmnKK%ulbCp6*Sa9^I9Ch;5Cz*e)sxarA=8x4v}N zF&Ua%5p#Nuy-IjDR&8w9ofqA3ZMBJ}pu(Qm3MQ63d?#MLD44iTz|31`hn~0Z^FTL{!#_87fT0lSAfNDSe2`y{Mu(j5hS8bLV*B;}m&PbP0Kbl`eFsLUOUg ziUnCM^%+7{rgC~x(zJnC*pU?Bx>*R<0+qzWVm`5flhgVPwp~=;(tMgENSM9Y^t@C8 z+Rp*07e!w@?#y>%m8UTCy;Hm@^fEQjqr2&3ziqvR7NIAms|VVz8h|ghSQwZFc$f(T zL^U-)20>n%=+0+o*Gz)9y3ilHh&*}d%i5<6@IKpc&zZ0NqWRYi95oBys8r+~%5g4-MC+60Qt z2j%)Qp5+szm6^1{lq`U3J~dtvI2tR)j);_UuA0K`1D#BF!25eP^p$Q*rW@wV zIHPq4CnL06{!2?P%13s#APvM{-?HnK*;E4+9X1bT(qFc`@#>9>mfrWi*xmlm`$GE( z{h#lJi2Wbde8Q$(l3|a)xyaq#9hM3&GNrX%3BCwh2OTV9ZhYoWf!TipRdvSscWQR= z|L~Q+vG7d4xknwXOv_(#eJ=*n2NV{dkS*RN)s^^NyIIukU)) zvP1dJ*F_6%5()UXMf+tn#LkRO7-g)Qn*VrC_-V)T`bZzQIx324%UfWYyMl=WQ^n^Iz|`c@gMyq01t@(4dG zo#XIma>ZZAJ;5yx&@d5wG>OQ4)6isKu^xpr4lOg2Gn~FZET1H=9)NY0{?tn(!D);^ z4FK*a4|pV2D2x%Z!+b8L^wX41jof@WaXlG?J~;7>B1`h&m3(=j3F=}1T&KGptQeIO zCU}$=KvxKXUX-c>OKCcJo=Rp33V>El%rhIr#zJ5qq5F>Ho(fPHS>n#(e*4&ET=K%% z3$8LVFU!CW+eoRcA>{JM7Up?k6Gwp(9_|IfhaEj>yyyN?6jtn%AEUBWkIYwG?}L-} z#U=_`*r)J+rWIA}C&>pX9vlJPj0Wu&%3SZly&vxgNtkQOz#&Tg|SXOHXWS z3EajkiKKobQ#XGlWS+cT6(UF>HMbSAl`Ig#It@%dOymf8o-H%RjBle)f}@|?bH#?O zKKARD*{#G|_DsoaiM>|hDitb4c)qb}B1XFnq3a~>b9e@9s4F}ovWydmkoaYJ2PZLs z=nJl30w>7?K1UC<;zgl74{O4-jYVzW=@=E1&lvn3u7CSdp>^ys`0nv-BCFoU^ znMW{){wscHsNwEnxF@5Oox%Eof=N)23Y(7hn<&s{!P&-skvFA=o5dd|KOylr1Qzn2 zz=O2^$3Rl8B6mb_hEVYMCjJi>_2>YSnM|||5)BCZFY*Sr^pq6xxye(OZOa)Xp(_xE zb9x~cNM-n7aDA~OCnO|CCw}o}@e}~KvkUnKMVwEKFp!c{9?H}M1kfvtU2r*(GE{h$G`|;!brXg7X^MB01vbqW zyQ)o*E2D0juGYogsvgQPSblq6UI^nh zuK%$DXkET-L4(bbf+bU8eMd++u_}JEa&XDu>J_od5ruf|=1h*^{9zs$-##-dPw4p{ z0Sbe4bJKO1FmdG{X@9@uf3TSiknlj)`(xb06g$_~@Ij6Pj?x`U-%YK<^8^CyumVqunImZ{Jf1dCV$;Sa;g>NC?eLD7n^)64IYK`L;bXdb8}{U= zx)jsujrGMKQaK>c(>|TuN4Y(9QLZl?gB>_X)d?TG0rPcbZzHUqKJ`(%IrJ@0Y#D<2 zF;Db;*J^RDd;ve9EThtrTY)(T@)U0s2iNC>s<=3#(1HJy!NLn@1QGD|qKfeC=oYHW z*mNId0oDr|Kb zXvaHD1;XdyM3rh3)7KH}2mMeSeo6P(fJ)fcOFZi*mXydl`*In2h>@PAiDj-p><)Ik zWx5^h_h`3M=(I!JBB{2$342ZZCZqPC0#IU&RMvh~A=6|fULgmqBD@w&&HnNup<-D7F`4>h*zibsJ(_y%kosjkhh(?`Q}nd^e8?s;4RuS{*uEZ? zob}hRH0ttsw85w?d{A_6rZB-aC-4!Viwk^(%^$S_1zt-$=0wl47NB;A*zZ&XIE0yMF8nT}-)5*K|#! zbeJfNZb)pKTo8SsiA?IKqYirMFg03-tA0%_78ztT`{P7qM zzf@`N>OA~)6R6=v+(bs%zp@4$_aV?{lYQ?Em*y_;EN@ehCVImw;o9J7C&H@^)`_p< z!O&?M&f-{tjfjS{UmE~cOWpQzQ}yG2=(*CPB{=p{(O5gsP2_(+IbAL}a zZqV+Hvo;?8IDLOumA^gJ-k)?&auRa3lP;;_SXKE)tIX|*xjG4_{XGSh`R{nl4-*mt zlwO4vQFWK9+WIAvJ(0FuHC)x#w!h{wx>(PL$#jcDTQuH9TGXA`MJIOQUcS3PP6kxv za~h0}Zcbg=&3Qlg^Ilx6Di_ii^-H_55#@%JV_@B8uTgb?f8vv6)P5#?js@`!IZ+rq zO>kLGYb%c-4m^fWW#-JoNo-f5-?#eqg82M|BD~l%ffE!CO*n{#U1-7y`IY}t`VFBE z-TpoL;4ObER7~{rOEc^Hdiqe@w2(Ls6ZC%HbH8-;hMeWxqaH91weON6A?BAHOS9#8 zWsfkApoCD^D#zJv%RER+PG9TCIL!H4KcO^GLV&zsXzUu6_sbo}=WBm0)CV=77U+d^ zevCYvoW~y>(mXViuiz{#*%EVjyx(m19@=TI;g0pOqAyh|I-^p(r1vJX{pJbOBo)TP zqJEP_meFnEKh6fN2Jz3wKY5n*rv1r%L;W#qpIk24zFSh$|G^K=mOOm#%p$`b!>$O6 zTqqh^_AEk`Z?q=cyyR>pprLOaRg_b2iSAkcQ}6D2%h6Y>_riKB*Z!{kL2dtE+ctzB zO~7o1+XyK!Venp}2dmJxqfhbd<@qLvHffAuqm~0gr z#KFgo5U}NOsI&6sfNW~}S{jCR+!J$8-b(bt`o1yaM-zH^J4w|kaHi;e88s>a`V~Jg ziqIE1-M4?N{8^aLBw6R;Cu zNN96~ixs3oXC0h~rT{IXm?7cX#^`(-iIyl>~TlW9_*YaO>t~Bf+ z&BQ0=B!BITUqMVp#4&Y1)_gg6idZ;!E68s!UxS}!K}<70lxgL}`H0<$I82KewG|L# zAraRMt1Ox`mNW1YLy%rT<{tWXw zDkWI+AR+)Eim0*uEfFq9QW3W(M?!DGiQHH;x^nc5MPrO;9l1Pg3Syof?TH-Y@FZS2 z;tPVRF`40iDnlM)th%>obVXU4F>yV$Sk%|U^E_rGII;=*I?lJR{CMbmW>M<(l^-)| z8_7nkV@p(*aG?gpwkLif?%U$;>v^7Lvz8x^NVXN5NcKF>WRcR|jgK&< zr2C@(%u3)shi}XKazl}8AN8_5;{XU#tMsE|`AVXV)WRQhKxW|&n5zCvm4tfm2K!?r zIdAQ<>4D-syBs{5FrVP-SjdMv#;b z)qZopS~bi5{N+hLC#?TepVcB&zD)$nAh1n+;!(WK(o0u82|cuZ)Ks_{v3@FV3>rM3 zuEu2fsC9daTDK}Dyj)2c!($TK4k80!>!x>gEbvJ9rl%vx^E=>A5onXr&=dk=Lf}%l zr~Pec+8-lFBcbhr0K+Oq-^(qY3-#m<0|`KyW#pFGmENcVq1O{3d!?K&=V*tOZ8avY z18eq2j`mn9IAcsWn!#WC%HIv09iJfhLWqx@Atbh$gY4Q+RDdk+B*c2+j8>d6qdM|E zqZA1+p1U|ZWqChrO_?U3PeD=Z`?`30jCaReVRmiVZfC$wjW0w}fd_+PGJd5W9T%Z{ zs7HC#WIbV$U^Wn}kMw~JiLQ|i^=OfbiY_mRkjqhyR*zG<(PBJAA{%x|2D3pj@4h^; zA;Rl9c78`WdPzf~cVxqUCu2c6W5;sm+T~K(Q935>>$ok4IjAU{Muuii51IXB`A5wH z=3=c#fmQq5xbwo;-J{GlrBpf7Y>PJMi3I-{8Z7R}UN5essOKi;_2xI)oMTQLC5QK( z;th`|p(s9cgH4ZpxVaFFz!Q1TK;r7|dG0DcR~qBDS7mLfS~(luwOPW8Mh_bZ{)<|l zjqur9+~8e)csWnO(Xv+H%~&u@+%srHJkQEP@z+E4_$SB4_V$+IKYi4D zXp7(Vx_<~h_eaBLO^)5$JMSbP@_pEErMV`#rM@wAh9Z~g^+*4Dhk6oaB~acHh7H5N zkF7^eIJYKq)e}5BjFQ7e+WcbxZ{YZNEYrKNOt(4M&uJfD=I_mZyFL7|f=UwQ)^-+voa7PI zcPF3M8&;@Mp@`sVxpZD=1)m*sz=zbnU zKCVN}vZDmmS*q?$^e?vm`wsk}VD zS>Z0-kmQa9j;OUi4L|A4t5~_%y>fOh+bup%$=!3;J)NC=&)#4CaUV2fH=Y?AeZ>-q zX;A^b6@g+o7nBzqB&vQl=lpVl!$l$7tQ^2`ba)dpKN`?pm1aGxr>~qtTtcnDtwfAT zz@?W;k4=r|Q{{@ zHJ|n~*<%>bw-`@@ z&$U5ZYRWf&X-)TGu_e4v&xA+uMa__b=D^UE88f%~$+Gws`SE^$&rJZu1#`-N0Lk7%t@Q z2~lZc+*5>Ygu=xwzU6K8q&_Eqe8%{#=FaFoPV>C$UH$=*Y*y$uxV3QbqYIACxurnv zUC#4}`6(`E*ZRw!xfrRM3Yl}z@zY)WCi%6hjo_Qz`16MR+0wPzNWR0vW_b`q#j3EQ zm3b5M!FDkpY_DeCcKTh1@om}_{$*mANKzb}s`kbDel860A&HpWjjnX{<~MRu(*Dmo zq!G(c$P(;ZwKXlT+4MqQ^>~pB_(ZbnxqKG0{2so-`3~hhlNsDQ4gJ2Tm z?PGtrvM3TT{T8wAUM-*lr$(?#@QXlx;*uLYcTO!~869J5PS|K8(flrg7vRZ`4Wi zX+KN3wR4hlp1XSeqya8h)1-mi5k+hI0EHYQ@F-djJEVJ_Jlp2qro;{h2Bl;ojqE09{WkOj&|C(3B!*K5ll%q*(^c$6%{YDj04jWjv z0kb9fqGEtj^v)-iFD27bx!-I~{>mdlJ}`q?eysZk*;H^$o>l!2{pn7ByyixK@rQhv z8XuHT+(Tda=SK8D+12=7tokHZ;y8Ueb5V2nT=-cCdBA)nU{r1m7*)-}{4G?wiR+Q-FaJ)Lp~EaDIw@PKgg6=xu+QFfYF1R^g4!E$~l1GZ`q~ZPeb+ zNT$Sd`gqIt2bcQM;;~ZUhKeCT_|5`3VdnjM1-tgcnUax+g0huxXB*wm>FO!VIi=>O za`*yn55bpJS6NT@Tm0sme%CuhkW9uh_#vmeoS=7lp`7%T(ap0q1=<}i=*P{;ksbNl zc)|I?`QtoT{5BMsR($4%e)F|J`93`!Up(i0H6AZYd3!wDobe>6)gGs7zuz8@=yf>O zogU93H6E<$N6BlCXDbuob0vJ}{yL1u?(&XwFZ6iI!K+D|edS*m56FCJu%f8&qdhA$ zYJU#oE6w*flkAHg%Q2#&4Mn0b4#SY`^`J^yyg{dzxiz}5t9m`7DGt}l=Djbro?Bts=~HQbTGUi zJ&b^JN%rAkoIG^r!OsKwR9dqRUvA42^=!j3+VlASs(RjS6;#?EpCbX`ToqogKT6@- zC&>4dIzsF@ZXDuMKJaYO4rx}IlxM8jjDAAAI*i&M3ogXELm3c8cCxP!+@+c7lYInq zu&W4)$dyJ^{LW$2#}amMx~rnLeaQ#B4H_IhniCokJ(?Z5A_`lsoa2dI-HRd|<~w1m z8XVbEkBUcM&PJ78l7E^UA7p=j*I0ErdY=8E%a*q*5n)2)=!46yOo%+$G1v0;U8IE; zE^k)?!s5u$$Bgg&fTVy7yLc%a*`^o^6_ zaETqd7QTy5hz#mec85or$zScqQOv6a-w-0d1Np`LP4-w)3x8 zGl=#@30oMM3YifKM4G`R8ozmi+|Ac+>GOobK!E7nl4-~2^UJ^AFMKr_FD0bE$B9NF#s z;v*41TKK zZJH#_R^QNUR`|`$)|s3pC*)aq3v2}Y-}jW!Q2N{=1?@hYsI}yoKHGhZsA_ZFcHeZr z(|r>;Hr?mk<@jd%p=&-41wB?FDJ<&{8lje8J`#wl zerXQ&{cOZ8L6!Zg51Rh;-ud<-O9Sd^0@J zU6)toZ}mvr)REXLU8zvHyTm3`ncv`q$~9_lV3SJr!C0h1<0kVPBo=NAQhW*`C+jB?@e3fjE_<*2n;SfztS9Qz6IczkqYq@?^!~m z1D0Msu-50)FIV6r>D~8bHR9#B**dC75@{P%TB~)dN^m#;F>6N;7Y1`^folq*hwlsK z(n#4ljc&nlpvy>(S_{F_XL?5p8D=sI#o-at@UNv_&b#yDSv?ehSU0m}DYpYvNtY~D z$;CEB)s-|lmAoVnjQ2ZA6I9}dw0Tw!mrBk~Rf3MD0a3l4NjQ;Puw5qO)7-x5_s*V! z)NggOF|D<s`x_ z?D~C|ETgukop56LkuwRyYt$a2>E#VsT#K~)@O~E&xgLh(0TO|koHwaZ?j{_McAO;` zz=nkMyeBL*MNY01l8HC3-oGP@VxfOn;gV#q_@%jis9AB!C zU}%8;E509pgy}hn@5jR`8R$B`A5`GXwfrV}z$<4Y%(_Yz&Oj&~u48h-e}J6u9}Jld z^+ire_G|JGowJVm&^)@rU3qmSm+;&xI6~xFP`5AV;dLQbk-~Wz;&+p|sw8wa;F}hw3{u|>D1s~x^d;$J{?TzLM6oJ7v zX__^_c|5Z@!~Ot+Becg@m7lf|d7dpH3A0f3Lmu-LPh^kbssAuXu0DBD%tM^{KTw(V zu4m-}+dLFGY!Hfk(UxZ;e9f>9ov*Oou@3!|<>pw2TCooO7cq(DfT=XEbpG?nutut| z?oZLNS^vxaQSjgG-(i+QX8&BB`&Ul}-M8P zG`4O8u4>F^mF9+pXQM@Gts*{z7~jP5_MCz@_P3hXwFNG@Ucu6zwzLh?CpTpgK#T&N z`g-MN4NK{Zm{0npx;iG+RfV+;TlZU5}~{&)J9->HASI`^*yra<@a;Hb|1 z;~YU}0HWq09`HATpEjqqF53Kc3q}L*X4=n0$OSE(05~$$!7H5(I`I3Z{W~fAzG45G z-|pDI7Ou|gu%I6#g9hL~2nD9ZW~YC#@uMDhho?SXXw>~g*3T-o=C&J*`|}{ZT)k2m z&oRfx3mRA`4TKUX@Z8pX<4{i8*Ta>5i(2tw^;EMKu6(wL(wJ)!fa2?jSSCN=;PyA7 zXUVBwLl)EgN$2`(cz!ebxU>U(T=G^2a3-fcdoE+*_L;nbl9j}k;Lv5f=PWX%2Y(J3 z*fI)W&Nvo&9&bL0YbUIRO(^`EW#@$4B6?UOxx=u-1bye zbEL1nm3b2R7qn8%VE=d1oUvjhiJs?F%d4kceSg_oFMkJTgPwn-VrAbD{`1f-wDUb~ zX_OM?rsAesPTbQsE34ttKDVvEvAD^2hU;S{9OLGJu}iAQoA(YH#p9^Ecnl4?1a%ut zweR{emq9H0Z%lSKEG#vi*+}4xTQ;a#61^&KYq+tp7}jw!gzpj>rhMON)#l8cOMuG> zRIwDpx8+kt6=^J4ITMfG_U6PF0y|m7nrx>%BRc3CwSR=(108xuES(P9pW_{|B{}u$ zDopXSo$C{P`P%wAlZTG@;(Nov7w%5^Z&&gPJ<=PD2X?@KCAz_ufiUNg%Xp?>dbR1d z;Sn!D`fDgt&PEd235gbT(In@L7GZpCbjf;Eql=(}w#vV_#le^NM^Y{L0y{U`Uc3u0 z`5zYU&nWHS?ks2FCi6R@d8tD4J3C~}K=aa*qxns*XP~(kW>ENN@rc&`74!W!94BqlKL1#qeMNcbq9s!MOgvNEL zx}{#K;jvfMZCgRp#J`oDltj9Q@9|HzZA|6yNQ|E&OPvkfe@@JD7W zd&N%NoOB~6)B0$Dm1hp_~|6A3?Y8GW<+JSwO2pj6299y1b3q{~W?iLYSjBCzh!HLU!dDcl>=I2tCb~98yzv0Z@ zECfEOZ&;8BLTB84A#n<;T%ex*Pkqn##!^|58#-k1%P}zRW0}~suDxC1yMjOV z<+zR-!$|d^2c+{GL@-&M4~R42uE32ZWECv8;!Mano}Ave9EV%oL*|fs;t28eBys4- zI8Htai6UbW&m!wr=z7U$-A^tx58}>TmU+mdiIGOqN+4qE%6Vva)hl2K%GiAyiznVR`iM5cC*%Elki*k+7a)D9R?S)SuRG*`sX!i5fg+ zGv~s3tR6zEFkTGec@Z{n3E}T^lA1gP5wTL(tabk4=7pDgTe*R(IW~4h!@eG+2Z^Uw zVLZ}=p#2$lnYcpR(3EaM@bbV5Q8?Ta^)sePN-k19P!P;2xnV9q2tb8?cLWHQMw38dV* zMioU#p3AmfI}YF#6f_Z>Il#jZ0+q&8NpmMjuLXmFt?FS2j%jVHc@xGjV3!*>%LCMg zDcqm!xqZf$PLP-|8BOE~+49^szmmX(J3fJzBU%*Ij*qiJe$p(vfVl?gKog$>drk81 zfPQ){=7s_E80frX$i8Ugi?Rh8S&ld6OPJ^n)50rCJJx<+_JX$`R;WFoVgws{+j)Thu{J|C&Vu9grH_Xi$ z0Z(WJM1XTU+;a9oD5nzLoj{k>aDmABkgr%G7jSS4Fqz16pb#V>URdh`)t9L*fevfX!xK9n@)Q;X zpi_uRRtBG}a$unp=L zIf)pR<17X0$Zn>wZ?OeAb&tP|L2*8W41x$e;8-9QKgS(73_B`#IM+cIyKzt+IL_i6 zGoXo}l7Pnqc-Sxw2xp9V6 zbgX~2oj>nFe~kA4Kg=get2?4Hb2999g!hV^<8+wNnsbZp$X1#x0lDZj<5rwZsC7mk zX~-$Bm^1{7B%1h;FKft=4bOt2f)F3tNDa4dXc1?i7Lg50BX~YF@GymHqjR4sV3XXj}(&6%mBh$1`9+(y(rbCSD=hzMO}|dToFk9vpk}84`lW z0~-*Zg~04q4C5kh+nB?D6x^I6kf9vw8_2*};|%Hsr8!2pV}fBTM-y%bU##V7!IhP6 z84Hh+*!NgrV2TM#Ig+?$8rj_}b+E3*NN_FY$C3bd5Ec>6qXTgm0vwIs2`rM9*@95y z{F=Z(%jGu!f}Dtga|Vzmetx*}U<)QtMFVX~oFFJPte(Ms2ldrXi(%Z`od3Juw=q^C zEm%}<$v1e@6RsU+Vuqf2rT8`!JI32zy7f1u3LXO6FQ~Zpz0Q3;k z9rHwB@>p8ke#T9v9NR&}aYj8u2K$j)F`&>IGzNPNJ77)&&!@~}by5n-F(Jrj z0ie8Cw#zl*`MvfY=PM{{*a1~g7`9FwPg_GVh=p`v1&Z^eTTTTZ(%O5>acD%BQ+w_E z7*xJfK)4D1QGT>cOI~1xKFmGVcuoXZ#~|#sd<$~-WenuD8+f3&XyUeTG74HQfy@TC z8?^r`d><*+eeMFtKWdV&c1O;G#(s%f9U7azItny9Yf##wy=^)a%Zx@Ala@)BfTqGp zVvMp%2icmP1loOljB*ZK>^ho0y4Taj?(>}FaJMUR+sVOWLuj{Gnjzd9+6~bR>uEKh z1^htLBybr1j0#i+@CLszQUR)mD~9ahS3ypw%zllAurV(NB!~1=ldP~U3nAIskZju6 zPA zM|KN_32=mVATN)D0?-E@mb>Vy-mrCyq5^u**x4;uTxjQ_+-wvLQUvp~uHK4b&8&mh zOm+^^b3JIweFFMn0nl-FrNEm8s5^R%j8Ph3nh83@Xc8Xeq26~M>>*zSIRZ2ODAM)7 zfcn-}W0ZWjg_o)bn7CjbjgNBy+EKJNxE(SJW&lv0`88f0FvXi!)aD`qhlpgG*Wk5R zkflotrp=`BwGj1{`m?@LGHbFxEwOl!%$i}iA&GC|RyJ%+4cG#_1duI!0jb106}?WW zG&XEDGms`pFebHEM9Q(&(ot8F|?QEamZ?0rr3Z{%b^ zQ$fp>qp|%3IVAQ_!50_7+$M$tkglG!Loo6*C7Eice6 z5>OlcaeKn`%2OVXKTG=K*&&p%fAj1B!lFT2fNT<~AyZur36e0ZGi((vwPn}a8Ft&U zJFGK?qM7ta>x_31(R6!Tb{l)hu+lVoz=#B4 zj7Ws#L(3H18v)JB#4&{*!F;XkTXxt(=0?21RVy z-AECx8sfE2Cd3KZ3D?8340xoO|64dN-8NTr1a8G^`=!M*5!?bio`T0&X!c0C$`A1{ z#keHkP>PEK@h~%9-$$hhx1&KYumoFms#>E(Bg>1;e*(B+T~#yxF1SHeHAiEYVES5D2x(RbC7P6|@Fe z5VjQvyx{$z-7@D7hY&DV>^pCu4kV6EzN3k*&DgaDyB@`^JF#m4cFn-9aoClPU1O%9 zrvkBS8|I^p-K%0(N$lE<`JczG7qM$ScAbxfUdHb6cw4c1T+TJ@J`B4qz^+mlKd$Fp z%;z3<#pO?i`=8yTt3Ufkf39c7nSKeMOa{R}AH~O45HeuZZpayI-#hr~{O!Cge$=mo z4-7bOtH#p<`|;~{(9Cb3O}_I)zC$2?BD z4PeFa@7&#MtN{IP3o{1TcIA$F$#Ut*0VJlB`006pd9-%@SLq`Y;=KnBp?t>x1h9#d zF;F|p1CSn^xW_`+{v1CJm!NCHzI*{2?-5$XgS z+#^UV2OYQw!Q2D@lGYU|Mt4H=h>fRXzUx=-i=)EirL zO%M+-NQl&Dze==zC+-aq=a@hoMg0VbhJO^Ak$2*fbFtIoFgOQ+ z^hGP8A*%YUZsy&=hkwbCDY@Uq1_8?C1tvHT!x?Ibq4c9t=S)Cd8^{@a-QmGst(&`F zDYjR#*{{|F8<-S=gdavFMi>>87Q=4P7fGg~g8l||4wWwz3fd6eO#C+t2o!Fp+h292V@Rr$eKq$ z^?ys5A8|2@eprP$R99pb))@T|PC zK6>E}Ao+2^n5oo2>9Qul(ixN)kUjj5r~D-|unk#=^h4A?)AfjJ^&Zf&!sfJ*2#t#$ zO-Quka8MX($DwEB!Er>*`f2{R{yd}_C|**nAY3>ZLtt~zn^lJ6c!mH+O%>OGv$Ztf zY%NI|oTiID%v}8%YY;Ei;&bXCmx%+GewqJ3?K>zzh2|X;acbv8fLt_xK!s0&tAC?k zvt2usB_zhF3tKp3#{u0ue%I~Un?H5qp8NF=x~b#372@xk-}Jc$vVQ0T^NE1JvO`dQ zIFy3~#sG(VBh!NA3^17tr)WB|y2C#j{}Mk`!tUXE=mf-)aoCo7lzb9yp8qu<_yFLd3I5AOI5qD>&_WZUO2N z)`7#2>s>A$(weO}LzUHv4z@-oHNmzH%PdC;;wYeGjOAz0v}q;GAZz`AFj`IU#M0d8M?9&3xmJgjE$;bqETKD^+=%c=q& zKGq3Xk5~8093p%X=YYyfY_Ln%|OMVN%^?Ow7|2C>+ zKcd2_%rE^nJYCR#vxolZxCwxwhVx(BVSe^!e-y2^8ioP)S>i=#9(Fd32Zn}P|2PO1 zz8Nu{|Dof#HW!Y_`j;Kg%C-O0i*pc0wT@fgf6@Pcz5m&s^Y3W>CHJ2+N5kJgHOEu% zi~bw2eEXaJ^UwUJ)i`WWw}(GiB#M6zI4)~8<9-LghF4;=Wp%KS2#uHg8{Yt9YyO=C zY5rq^E>8GMf}o{Y1Qux*kJ|vQ2G+dg@yCV{hQU4d2L>#)5F^%&d4~z(zMo)1zZpM2 z7TRwZ#i^%FcZQ7$>f9cP$Fgk^feoT^J80IP=3;7`e|#};>v@G_J$M|k0L7ow{lpk|H; zz$t5}7sB~y@*NHi03qlt@XL0SXsmG&3?+W|Mgw=ld@KZ(UIaaM)I8+zA3)xy`Vvb! z(9jZ$FG0%z-(?UUpN{7Uv<9NJzzZ`}E5HkFhi3+e(l=lcsHH~058?;$!6v%=dB4U- zL!)^!h^RoUEe@9g1yC#y6|@Wd!oNi2f=6XWM5PB&Wf4))eny4G$mS1P%tL~~cah19 zfQ5#pWizX(aElEiqVz))SMVbAmqNo}D0%?h>kZMyMExKpwx}u+0h7C!2z#~&Y{8O? zL^Ne+AVH8q983){{&7Agj6#5Ul&Pm9+H8joZh!@SaB6L?U0sd`z$u`*@Hpnt$=EI} zunD7Mo^}#y4fBjk$)F4v5tzxeK{EG!lAfXqlk8}#CRl1WWG`MJCY}|Db)XR^^939` z%)^9@JI46Lv$DY-Hlyj~L;X(afhc&Wkn0xDCPOHj-xd=1TkeRTPPYPOVI+~MkGiVm z7@P9%Y)UZA&Bi7(UBoBzY2KjcAfBSw;Vwm2r~)?XN!(-8w?4CFmP z2q0yU9Gf~YI>zR2{ga~!%X!Ge6Mu&M%)}3%G@C#FFATqC zVl|$LV=Q&ZMBz=SrD$gJFaFCjxfmlPdAxW&8a!w7oBV}m3@aQs^OH0*>Y~BahE5FB z4&|Mm&@e#X#280W;G1(<3VuBpah63Z1q(hFbKn2VewS`e@ z!0C;#98fd+f|RbQh~q}08FC5 zJPc=$2cd5=E}@nH?RxOzd{cB1I<#xuDM)v$LnW%pLT#sLO9&!%EwvKx3}@+h^pXP3 zieETCGBM6wzj0at=K#uSXpJLL=Lybn2U5EPiFpE6iNuJy;UPzVgtS7);DTH`cvZlE zuH7Ms%cBc5KIj-?egzo0h1(WLFy7B^w&Q?6hy*y{_;c{@#WE$2qKjDboLV@~xshFl zPC=~|a67WIOMq}9AH%8HjiH-0P`ZgB6^V|8haD=*d|OMTF-=yKmFWg0l^J4 zi1S}LH}ueP^S{;C|B0UlJC|P7{pG~cA7%5iKmI>HkIL5v-mK^yhrLvP3gEWa|I_nq z{-%Y0-$-!i)BaBCzeqouKmMQOQT|pQysv)gzpaAu`P=c_2^R%X5E{>g4bMNLy**~5 zmkkW7!;V(mz8Yo&s9*56Nq+zPVO*ljV22AuiU^@($Xv0k#K63!p z$r1aD1`r=~j`&&oaCua?ze&i}Kzcyu0`vg9l@)Z~P)|&F`Y0q1(-mF*=6gDie<~&o zwJZEtm@ueixo{?Tu19Z^-4Lo`?VQGGNX{SM#~f`?_ZR8#J;puX1JmP|{D8Ds;c4Tq z-b-W#(XVwyn!@I=4ICBJV*XSX^!<0_h5uC^2?nL&QiP!K4{|CPvbyp*7Mz!vc({#JtFs03rNFo=2)N|7V9`@g0L(gV$h=rxd5 z3*$8;j^c0Xq3_vYB%7V3t^wKQNUS@@R7KyxkWJ84Mhk3daFh-OPO3#XpKLT>0Alxo zSXjxPC%OaE7Rn!gxquWskcJy7Aa&pXHtYfP8X(el>n@)3MX1cM3<-c#`woPr_vJv*56N<+!Lrs8&qxCJ45$YNGur5FZE>^(JK9i^+o9q1^(ywQ~x=B z#s4n;9bbOWfd4uEQCKqe59xn`RS($U0BhB;OoqncU$z%Yf5wl#m(lkke;<(`4I~iN zW++Sks9nfrpfG+85rDC9I!Cyvz}g%5#DrQ1^@5{)9tBw81Fq~B82b7q2Cc&}+i1)c zLa`9T)(kU#=opI^)wAotA7cFf|IgqXs)|2Xdgk}5maIr=bJ`QTY@ek zXe2??3A%xxWduD((AxxkO;EuRT&@B^wFo+spl$>WAm~zprW15CK`RM*ouKy#`jVi- z1Qqy#$CpE-%Y<;xC8#Gsml8CQpg9CBBIprFqx$dpIaChMt4rWw7Fy!MbMj5V~PtAl<+$lx{*d3NbbaGBndSHVrWi3Z?6X7zPE?>7fP& z#=emeL5x5~k}t#%6YLwu2=)z*fyjbUL~*`BOa`6q8xlSLN~+`-e~L!@H|yis8Qob;!E3E}_ONFc*>BI(f@nkb5p zI417+^LZuceWDiOPyZcIJ!SsJ{{i9u*ZBS}QCJQT3B^}q=;1V-aFa-S zHt=tUOXpsZANuLpm9z|IzrXr84R;T5=@{<*aZM-ge$c>3uwNEHA|mk+*sBLihaADk zO^2R0?k}+jr&L0}K&ov-Tx?`u5*1|=JqjvKAXXh1bS8@t4OKWWno4IdVi;6bG(9mE zsu?{bGU>l9mY;Ptj>(9K4&xRJX?EA|8Ks>&&flMZy5se}{ zM8xAl3BQLZ6Dp} zajZz@pY3BbHNcL+AlgSvZi(mL%j?~b`~RuGDbz=Vy++MrRA2;_b|i>%57!SSL$M#y z3w?k4>gf2!(SxDX<8+qB#YF$fhxn(%|DXP-?f`_B#7)n?(cT01U*(`S4CQMaGmrrm zMvaRIiw64;+Iku7H#>hDJ2!WKXKN=rHNx#^Z|CgpZ*TjXbD^D$o1HuE zHQ&zL9}akPbocjgv&X&M?VPQDeaOYh)!Nw`6KkE!V$c_Y3hps6kw_KoW$`TdkAQzB z{Kvt6ur`yS9j_gNzc;AN7%DxH9?W9Wsj-ZhV0s+>-uW}XVEGRTrgMMT8%h)U1;?Q3 z_iM^=|H5uO{bbxpf|fgs8BP_dCj8ML0s37e+*~^(@{dZzLP?}vA{^y2`u)j2e)jCy zcnE$SN>5M!)%_oouZ@MT2Q*4?zQN&vjL0Nko!~%5Sd1@&9u@(WF$r&$qeJM4I>C%U zCOu9kB1YRJRNpkjz#u3nP~TWjPd^lFkr6`oN0z9qucN1U~Pua13X`X z2_+A}`$8A){{ub$+ot7b8}`?JM|5C(L>MIMN4v)N5ZBY6(9;{<%X)DCr++i}O@;q| zxBV_TgV+22TiWk2BAwj#D!2XqSM4MNsth9z^}iw`q9T}3hoGAmLJ#@*vZ2zWL#Q#K z)Npztl^z!y7)xg|psNOr0~HxqAiR(mU{_qPn5d}0Na$QrBf(SiWKx&Wlc-V9{iFubsi6_k5x}Jp7Q>`E2Rc*Xl{Z~iJ0dz%Ga?!~su3Z0chv%P z#9xEh(@^i>*+6PED=LW2KyfT*#eh}+DmjpfzwLr!pi3GP`BQJIhA&GGe%grW&()-c z#;_o@3E|KcrN#zA#y|qNPjj_kMMnff50Z*qVq+qrnMB+%EGEh*MqqRpoy&{|ab0-+ z{m?%^E#SvJ))oKZiU@&@zz|8IuU%V^=>|EylMR`o{-v!`#@;4#T z)R>^9(9!stAh41+CcGMB7#dn|A5FKQYC%RsvZA6bsG3lJ&h_H;O#trEuYquL-@jJ~ zH)?~??>6D)wwt)`zq$?)ZKb*u&gqR)s{)+nG~#sWFhC{7OGr2*9p{U%Ex6QHl*}k)1*dg8&XMEwwF=7 z4XMRBEUNyf4astSz|%#KZLHQ+B`Tkw*t)*y>wKy(-*&?tCxIJ7>9(I79yjx9SJ_tX zyq9E?_`-HQuZGq%Hr39U&*035WA1jmS))&v-^;bjAgk*3Ppz|?c=!32Ui}YtFV>Zq zd(YCGt6nac^Cr)Ku52`aRaN!IxjS0tsy#W-GM8^<*Nfuz(YdRfni+v}4Cg(eCfyhz zhtE@t@Up3v-8HXbkIb}N*E{AZJM8$dX4QDwe&5Eon!%Q|et8AcFMbSKU`g+##E%DP zNiA}pI!`{JIi}q3Zh9kWzsuKV=*+UY_DzQFFZTN<-YT85=CS&G>u>T) z2jmyeKWypRr|()gU&`s};#nb==6eO~eCw1lGC!(%T=bp?x{kK*8=gKL2zI2DzgJ%J zbgQG{j@bPyQ4P6cp_=@2k1k+3%%J^2seXHP7F5 z+P&3cF0)M3Ib`?Kqb=+?&X&y&J8N|koJGtxt&8|l=6ulR;pYscKIipCw^^loWn8Li z?4{U_jxLhYVlO*SWVpy|lRS7;@wAK2*q!!^rGqZpE@tyP%F zYh4gozo<=EhUC`#R_8*#qLG{V@!BYcT7+A(x8?-#WxL&!yK3kIrMKMFoi#4*WeYAm z7WnS?y5qAJillhGlGTn|=;C{f<2QV8VeqN0Al9dc3sqv9{U+3s-6uPmSFywAx$Ep+ zQ+j+(ihD|9(d1+HC*6HNj6};lcf0il6hSqgy)$%+cC7XEStm53#zuRc&z9$x7CP*x_pzj&=J@h`@^L!!M9nB` zy04!7^-U!Pfxaudtp_u&n1{zyGTa(sPrxOA7JqJs0Y|`9z3`h)M6~^G`x-3T(Pq$K>eJaqiByx}51R zn?Fco&C8^7M)WCk`D%J#V(Q`xs;}vm!Ue;fx70#KuAe-8HODKoAjALZ*wVbvk@B;z zdx9E5&2}z*vE}Qh(ABp5&r)i&!frcEI+6b&Ff3R3<>HgeH-`qqAOa0gT~>a7T-;;(3geNY)6B3sqP71eCPbv?65oG6%NOe!|H`1PB@p9^;TO& zEDpMRSFWEK@z&y+Xb<&BM5k>@INQB9Ld3IW&hZH8r3K59Z^>ubFO3uMrcs}zEfw5n zs%`Y<)Ka0mY%`ug&Qiyr1FP#Nt1i>?)cCM9Vd1i~%MA3>JaU#D5lH*~Xz7Jz(?VjF zwDG=QW^5^JlG->ma+OGaqhF<8j&0%?T zTE^Ec{X6zY_XK`PnK-UHS}Wz;>!Lo1nD`ybrdcT3#S~=3H(=hsZ`NFrmiy5QZjN6}V_Kd$6 z#K`?nl-nA;g>h8>%is!!YYbukm2r8_ym8m!ecJWdLzt~Zu#_ZIm?)xSn3>V{JL2si&Pf6 z$Ll(`ynYsz8-F%1d1+7m#du1}y3*HxLtntc@M4nH+ zSLY~>Pg-TjOq1%HnWSHGNY_!6k!0DjVaD#l14&NF2|~?A50YZb)`os7kxX9arJX)w z!rbJTV`c$s*(;Lik&{-Mm{ugG&C^mGm;EexiTCG;cFz@7bZ@aR9=zeYqQf$m_c>qo zin)2yGka`nS2&t|tq@)|w8CE?dDr!9^_8F2$jzN|(0k<<_Z!P{1q)Z2O>1mADs*XO z^M|-B#(tQK@}CRt_#lN>lGM+LfNT-%Twn8240hnrK?>y;ac*Eas$X7EZeI ztR+6pkXbfUbwybkcO31XzN6}F@bQ;_3fCKthjaOQU*P@8l3M(GtDK-E3i!DA4}W5u z@W1`2{AIi{DhB_=g{~lpv}h2I-yU<3NLtXboe1|oM;#Iv=&L0mJO(})f>@!UbOvID z4QQ-*fGQye{Loks`oYJBzMg@ep`MYRv7U*Zsh*jhxxSvhzP^FJp}vv6vA&7EslJ)M zxq+U6zJY;(p@ETsv4M$!seze+xuKq+zM+Akp`nqXv7w2fsiB#nxsjfczL9~Ep^=f1 zv5|?9sgaqHxv`$HzOjL^p|O#%v9XDKs+WS zEFvl<{?9W0Rro(Y`F|vYJI=uU&g0TQ$K!j6ag+bs#)+oC!Rsq`oTwD+Kpp=7^q1wu z$GQGrsmCyS0VDH)k@y?~jIAIyjQ_HtVWf*LjxWEn}dol*7#$*u6zhDhajRJ zj>0?u8hib%y;1XJ`Z9c@eM5bNe0_b@^z;o3jf_o9&CCOXfuGa&3w|B2wQ1O6=H7X*Vlp$x9;Cnb^82+99B@%_&q`9J=||10+W$Gd~N zecNw8dCKv5kCUZ;ULL6nWNflwNA`a`{INMiHt3E^syiOKu5Y?KE3OcajVM6XsH z8VSrA3V)JQH7u=WvdGN-eRHKr-m9vT&rK3bC*{?NxgA*JMLThB`@6deIWBiY_gh!* z?lE7d*O#9}8GnGRx`0Rf`N^WrDI8%P$$b+Rv}J@J?>tj`{_ee=m5MJc4wf3ddi%(K zQ%KU|wC|L&E!mt;LsQe_C0}S~Y}+C^EZS*xp;Cn2kP&Ym-Y{8d!D9_dQC|FQj@ijgb5&cF45+gYi$_OC5z?VN;HjQ z%GHfl?`{|zolleQmVaIN&Re-~S6X;3z0+L6U$eYYx$K4L_?o9e5f3nuwuflk< zWtop^ZNk7MX^o)ADN~mm-QsEQ_;tgYof4uu!&|#rkG>lcOCCP6f0M#2*;C|o&lJfFRG&Q3l_y9paA4t#!a(&1_1k)2=76vyqct{>cx@-aG7 z+oM9anZj2Y7M9BjxwL49SHjdOk&+!R_jh&YL`8jQn*2`KvRAQt(%@W~@fX%MnyF~) z{q87Zf7+u%GIBI}N5K4rF8X&R#n!$#?IN|MA|T8zTW%FwY5$&!!wm7VsR}hqO^@+( z%BVPR3us_?);tdI&{Dr{OWq{YaE(vJ>!b1YvrHPV0t%PoMzni~NBIfH`S%H?G z<)k}@R(^~TzrX0)RH;sp&;i4<2fv(kJgJ!%6=J-yjCuIsMOCH>Rxc_FI*U9oARhPB2`SZ(ZsSB*Pm*v+f%HP{_>&_kT zsJ8pp9((RLl#yPM@gPBRh1bl!yZuLBG)PKJyAj~MYRS7MlPL$vj*L4ke|CTRyl}aX z%Pub%^z_)dUV3vDN#Iq|v`IG)s`WffVM=(8H`@ES;Ni^-k(>IPzb#a-i~PhgJ(g8fv6j3hx%-&LYNg$@aeVJXf{PV}yX7t{Tvq-}V5f0` z@&HAqlrpbPJoo*JWe)2ZPpL;GP0uY)bnLFSoqI$vD~iWX$v?Qhsgu&o$M0d!cVYWZ z8To;0%j_PRnV2Swj~G2JORl$;nOhoM@409ZLu^aMJEiMkM{i~*@$@7~eOyk?*O1-+ z(!=_?j8R(PgTi{TuGQq|d7j28>Qp*!bAR~Lb^DYjnxt(&sL(<;jtLeT=!G{Ic)J2??zUkHQbUT50e8B0Z)^?WYT?y{=eDcx=BI zPxYl_#w*(dB+UqlJ92z%NxF>WuJbK7LqAU6SuIgv&}QhRm=+Rc?RM#0N`UBx{8HZ@ z%GJ|r!@48BUwLlX*yWs(CfTz#fpJ+}_vl?+{`{vpV~Xi_Hu#K-dzVwTZs{!Li*%V# z+d1~_8Xs?YT6%1C7<(bPw}fwwlXXsw*QT@YB@B)#4Ls)!zkAI*Fe%|%gO$%48Fx2c zYSQw+e(jOg@M{!r@@m(e+w!Zz_pkJcXHqGHQi9r-b!|8i})OJ{kX7X^deW6N^zALGhbhJ?PAY7_%Yg)j@l(U0!!flYyUv8Rs5~jIy*mBI!iiHh#inYxmB_8K-xQn6IIK|p za0-2hc}i+0D@Q>*i}iV(?kvInHQB1NOG;KSOxF7gP1!2&a<{2`&r|u$KEqb>ce3X4 z52a~IJHD8A^h6Wsv4koA&2`%*Nz8jV+s<)c*!6z(JC*YaI^+c^uI}s{aO+Y%^RRI@ z&wF8BsbiN$Vcj zj2&Dsvi|+a#E<7MNai2=-Z45`sX^)GnZ;_sAxd3qL*^J5mh;FC`BSQ@PDAC)EY5H6 z<|*@j{;=@Ubn;$4bAQ=!pRSiR?ER*2o2;CxO?7f-DPh@x|o-h`Io7UGUD%ESf^GWJ9pYm*>UHb+cYkd$2y(E z@|K+yl`0uYNo3Ag(59Z+wSw%wQpG87bVRdNbix_^W8bXPg5`uV+KMLLzFTs6s`?e9 ztE;3Et|z+RsJR#xBNAmZ@tCRV$a3w6`-`rsddIH4;p8W7+qk!kqeyg@!u*;hf~>eT8bUyt&%MY5y= zo~~SRe8R$wa;@jWN{9R;wv`lJE}t`~@_|`2duhL}!sF-h%$QJ z^qtw)OU{(PF4rhYYmn&b=?RQ+;PI|>aAq1_ZC5zv_`HAeool_CrLzhPI^!sBI~S~8 zkg(k8b!FQ+`X(IE03i}m73VI(4h94_rqL~rTacp(&zNc*=V!` zA9sk3eLb*2GIVLzR5MXg0a-~01z8&vrNN2EUTW>LTt;R_uORP8mGN};IzOZ|n$zvO z=$rMEQOQXTlY=UYHe34#<^`DWwGo$G38dDP~eU--_Gn?l+M16a(SfFYBoT+jO)A z<=$&^1|;1k9FV=)l6^>ZU!l@0-ih7J@zp(67P}V8yNWur@l;Yi^9RU>eSJDd`k;{D zgksG{!=|T_-M(cSOWb`Za%lY=y?pQLX=gT?zmb=kFGLmN&71XjCu2GX>LU z6M46x)Jo z!PVFf$%U<_p3L`>x4rj0+WA<2rqW@HPpc**&EtE#W%B;DFK@`ye!UcaJ0S8#dQ#Sl z=%LxWQu_tbQj_Z05%c*eUh`d8^Dwl9D{klNt$|T20O~?u%6ycamI7z12l7ys1)6l%U8{?6%*_kXDWzefRm~$UO<^grzH_ zi*01JtCEt5>vy#8Rf8kZ;%_cA?$WM=0j}p5<56)=6J~GOI0a zgeJIdOXbu%im?*qyF(IR`iR{xo9r&)G2*CDm*yHUbYj+u^JflsN(2f~3`4Eb-(PIo zv_l zNt*tfvS&)N%GauXP}udo%)Q?y0q^6T@$-U_4r6Qm~e zJ3Siy_rItLsWhWezvdi0NNxctJlf8X+%DH#ZPui#4Z(}uZ zGRUjf?Q41=ySwtP=G@$!2X`nhi*@CH(<3)+?(1=TWLKBV=DxqTbMmQP_hsyzPD#7o zlbLRxf?@`*tx2@gU8%9fO~vofl2sSggl{!1z1X^%JV)+n&HV7IiZjJ`=Zsl&h=of< zX(m}EYX!({y}xyR=2H<>^@&A>EuN?5O7%&JnJC|tJMCnnS&~>__Mq~?zV!}0Qfp5v zI}|!KZE?WFz&)#uw5gU}d{Z-+Z9s9VbgC>q8zb+$ZCzmQ&HN*lh5J7B1$j%0JnmH3 zbFl06m3ybByR4cgVOOlaq?j=^Rr1r?o(et@g>m-Ea`qpyM@5Hc$ooWeO1GCdNZt0^ z)wXX$S9;}|qY_R$l5PuIgL^D|pVy2Cmnkd{yU!Hgqa?3euJZLuj3=eujW+FGdik-* zb@O#~-%CmwEf77DZ`4njaE*L2bTcAE#uP zKbIWGQ5sVJ=2=+yNKM$dV6Rg9%O~rU^?L3dn7^vjZ}x!9{YjaY72au&2TQLzR~WdH zea+2us~XzElWwLwbOKq20EOs%J|-VIrg?x`d(p&|3q(&lzYu6eNR&icKS6Cu|e&kOL|uigFR&BKE( zk`)$x$t^;Hhit~op6ebssrW&M^VPi6d||}cMwRzj8Zv(GUh00WY-X()6F>QpuU1m$ z#k}Y1C*D(=J(hM_?Ut|7J9mL>>x|?o`q;q{7T#Hd>-SNFmD%#2rWV&M`Pv(Cj_E2nQ?@gC$?Co@sk;4Zg8i(Ro5`N*zjwBO z-tuhuJ+q)|tIsPRy?-T9bYoIheX=&kvg3-ZCnZLE`JBM^?Ja9p>mL%7Qd5&V;k-25 zY5n~pmM&II6;5T+yIDC4_uW696Ed6RC%48gP-86e!NBoFQLb0FrAY1D6fR0X9&q?+ z9!(+HS64OD_Lb$C3#V!`mzNw5EPp3wvU9Dzmcb_-lltcu`n^9&4Fx8wl2ShZG`INf zmf4?Pt1fodGCrJgC3DY-o*si?wmfCO=V$8Zo*n(~PC7P>#7G}eCXbxbS9GY+D2OdC z@|JkG>2&?eswFlbMW3Z#ex;${@MsB-*OF((m-Z=#jbp!(zEdH`QQiO7 z>ZGKlGnuKp`~0q6fjxCwy&4XF-zQcm`~1p$r;c>eyrklnS6uhsBbVAH(Uh-~y7Dg{ zv&|6HR9V%o9VOdkC^h@0*Us&?sB+g2sH-Q<{d9O zXP-)l>!#yDUn9M2!b_E=c+HYLv0E2Aju%PvbeDzf z^_oMnm#rRCPFm9GhIZ@lG}vy?R>#^aVIt!d4#5)ugM36fmia85v?U_a|= zPC{oS{ifnn<15P!>_78);MRttL(0}Ns+abhQ&DO1e=RQVnOAX5l75RfFeG^In9Qk) zT$;;Dr3DX)om`a$40<&3ZwuUOl@Uv^Umo{_T5yuu70)j{gS=8ld{s7oaq5d}-fw3t zoUVN3!hW7zrYG87-<|hC_koA(o~>C%^G6mjWV}QY*`~-0DM>q~3{K=04 z34i2oIu0m=4Pfve6$ch7aNR|P7{Krce~l3aG~||tRX+~~IOLW`jvfv?pSAM(k!rG*l#|tq)rqsodS7y<#wj8|w0Rv{r zy*aPZ+{#H=Ac+GsRjT5Xlu|2RcR1icO>)rfEqfpO9a*D{12$z>w5Eu7d@LFW!GW8~ zuXbLa>LLGKa(6HW;3S9JH7q~kzp``nObo~=+t6tswkbhz-63HN(5YnJ)T42J+Ila0 z9N0;2IU^ev$zmN-BmkbZ`yUoGcXVtG!hxPjMQdKvoNLV7?S}(CC6hGioTHT?m8h3LX6+}CvDFj@ic$;$Pe9F>?VJc(>ddhPI{83T|?4_!OjX`6od;nO4xNGg9iV7kEcpEOjVv^FE-s`7W2#wWgMWoq5Ec4i_?NKveqSltapx@>L1$jH0OIi z256PMvN_vw!+GVwZ+kFct4zwb=T|>zJ)67|2e>L;_mi+vn0aDL-Yg90DmjNG-A)xQ z{;r1uUMU+k$d4Pi#$$P25(B;}7Jn@$t)NbvD}w`IC0Bhh6n+$b_-^-i3I{!9F6X3S09k3r_hllPjtvj`dN81@ytv%U z{+lr)t*_V^U{*p(r9ZH#En()sYYaFmz4ckZmopbOvG*>;0JQR>DkH;mofXlJIFMG= z|5WkWv2P-mU2s6HlxfMTBeQ3^o}PpQYvpWdlQy}`f4aBK2m{!vOcymdFL@&R`CuIe zw3T8NW@>dV7V4dX18(IuGWVTfzZKaUivw>}9<(&MeU=gQ55)nvWT_R2Q>&D&d`csL zxOcaCF7MmB@`FDP$W@*~?OYx8{MvA_J_gJs>m6cq1Os?J^Wp$q*_j)Ts|i=vS7z?S zfVxU_#bX}@q()pBIAE7NJ4o(SiDYZ8k z2l7h3z42_cMi>UXaX_!kYn$Dvhs3TQXFFoRUPad0NiLeLR!(`#~!OivEv4d?Ga9Dn<&&D+DY4o=BsThD* zwI^!rsygRqV+sV2*lU9J-q_Md7auRi0L600<`1`t%d&eh!hpuI{YiRh4t8fY486nw$9j&b1|h+QER*oaxclw=k*IIN7;srp=qQh7!i}?+ zQg8sX))~)lw0nyUCzb2KuUVb9xT>=J-mS2;+ zmA2HmSon(vOr^r8NzS2iB;SUxC)0jE`3 zC2lO)vG&fCI2=GN_4W3uc$-&ihYI>JAhn#u+DYz3hmO6B!vWPQAtswEeRE&Nab{w` zYV!BSvyV?5?Jrcr0oJnLE2rHr**wvBIu5i}R;gH=qdscHvjPWPlj(lTj~ugHRe#SE z176EqtQ4ilU+dFv&&B}QN}mfgj_KBEtCrrvfY_48RgA4O^hOS>&A|ZKGOL0LQXN*F zaXt0|17<6&-zi^k{20TnjEn)aB|nYpHBj&t5A(u-+7v^9trr7yZ&_*MfNjNIzKaPv zzGuQ|Iv8+Uvg^|EO?=%(?1Ha{+r&a3Y_g=kmkAVTeRb#j7JzONxJF#Uv1_YN9tzRh}Bfe-_?F0-E zF6a8T_@0B*>q-p*7~T=j(;{|Ndige83?MGG`ZiB8dCdD-8V(efJ7m8~?rv&%oj(p3 zSD6sKAZD&hbk_!k&BOk3*fjE#{nU!7Dvb4tM?MfU_ zPVRW#mwfr)N$m%hF<`mu>XPDnrx&Q2FT?@n%I>y2H1ft%d_`&)(3~8xiRXT2LdiID z9B?kv_$8z8>ZTUE@i_2Ysdnaq`@8*ivMh>xN-deSWg8|=FTicb($j=%p+;ITB)HmD7US5xk9v$|;fbeoN zHow+-MQQMm#sTpv&y*=ME1kAgz3jt)@ls3Z3iBuK8S6XPjRE9kPmlKQjL5y%z1|H2 z$}8*dF5~U1^3p86g#qTtqfK6!i}xOTpOJ$B=Vi}VYpd&vY>O>Df&u82<2UX&z3ZU= z>it3(ke=*bZ4!Ho}>b;WQ%zNF_v)i^%JnX@-%;K2N{+x;$C&ikh|31I+zg~6vo z732j6@1G6Dfcg?sRHBx6O<7ox4Um&1d;;B)i#PF&K#}^8a|3CKL1U{>s~(W|B-6V8R~O0a3y}ECPnbVFwK` zO~Rr^Gm~UOMv}~Ql0a~&144^ija#L4X~YeeYHF=gMUB=4_tavg)>or-p_XE-OKFSp z|9;PsOm1dSyS)GR*G~`Je9!aTbI$XeeYxkHSy~nS;AVWOnlBFw3^+Y)<=go?cieQ< zW^r&}$d2+~WkrHV7asA50|dPveI&*8!rYTr&yoiT`cIsY*7t&*FOR!8UmPeHGUvRl zRlP!iGkz162MhAAyLCz7FHidO^OuMN2K|TIF3-uGw)fDZHR7Pb;KIOPd;QQoXVnaO z;2?X~FaA>aSmmW-w|z$(Jm}YZ*JrsOZJAVmf;xbZdC?Cyz53HR>HA+72N7H={&@7Y zQ-)oZ`Tbvs0}1^`zJK(x{|QFE|M4PmFk#TEA3fG^=gFymec)7aK*9CgA3y4U&C5$3 zyyYx$P@(T5@84B?&M$M`TP_bQDh@8V7UWm#c+h?1^(uLQp>NS! z7kuZv+=sKbKP?V2aa7e`Zpk@K9&{Mi=cC@&-aII+`N4a|frmc(?|kjN{I{Lg-+G-m_%Pu6 z*Yvpl$2pny%WdKS#L!LWZ-3n0{(j(xZ;OKvyGF< zc-IB;V8qbvryRYr?7P=JyHXyI=skAmW7iy6XWR4pTyapMf8DziAO5>(ziWs*FfruW z6<-w1dHd}TKmM_}fF%3eowM(}^t2xZ4?Xix#X66-|Dfle-}li+#?e1)3VAorZXMiy z*3oxAyT*U=l!Np3wjN)aefRW}&#HZR=F4-}75r`Cy$|(U<9PW*--oFe_B213+5e0& zgC8ipX+*T(-RwL3jlciX{=d4)A5Oos=ejdj|GJ^Bc+AR~{pO6lwCI(VPscg0z2aw| zlzw+m#gAUAyYO(s;NX{ezWrZZZ=_wc!6elT@IW?HqQ zYV!17otpFc>pwfUrSPSt+f$x-%BIy;WB;oy*4l7oDdf$t^D7DA56g4_uyFF>w9n#@tJ@BbUb*6LveMmt}o?7gv4o^S9UlI2|2GmZb~{X`xWo?9uT z!}BzE)kiPz>-XO4q&`|-&DYrayJOc!pL+j~Ci<~1bBVu1u63l$2fvEn|Eu@MRURkf zafXVAzCX^&Z^Ahv-WBw9&*$LePIUy`N{4%1@dp37qolk!N}g5DK%B4PN1X2UD*pDn zxwx)O8moW)x;6Do;6LF#cUJ%Uo;xdF-*ac>|FiepS;N!!+;!JKTvc8Yq~fdVF@pUJh!;U z4U>=bTNy22uH@yB$i+)sq&QdJ8ac-(zy`F3|h5I59y9C==vE8B~Fl@4QY@f`Et z%HNBDH_u0QFK43N2-TKwU{O-a`;>55Xs%49nlb;pzVg~4ePHmg(pTSm#cN@yFYYK> zxgMCTUyHnP?0(Io-do3AGY~$;qPImV{Zm#pe@>CrkFWA|9;PmhzLaLf26)P)yng>ZA$ zIr2(LTp?A4Te)iLBN(TxlQ%H=RCrS<6eeLf<W_js)A3zg*?d8gJ>gSh(e}{DI?S z{N2hu^=AC%mGR0yaWhqtAY>VDIVkg8%hThWmUkq-^IU&zB(PEIil4Aia`gt0d(iLE zUSAtz${?Ha@}#bLdALz6igUEM;Wbq2uEA|)k#KEoh$m?S6_}5SWRz}4*Sc|sE(%dO zijo*Dmj=<CmWefA%rJ*{cRvGF*LuCNB zxk2$=Dx4WIm~QFkRrNGsJX8URin}>G${24hW=RyPIwwdyr>XEq7OW~PDw#iT!Kp?*}CV=UouFlYXeQjA31$shxa08YYcnjQm-cE-i4~ONbo) z^zYVrtxxsery{hK=sm<_2=z&i2hjWoqp?-F*Yjw-@TmI-eJ_nWH(V?0p1AI?TfN^s zS++|UHVN}fMQi=74HMc0W+2)I*$y05?sY%&K0*=e9x9)a9ntVcTmh{vVb|jWgad0R zEJMMrwkc8%y@Bw2^c!4jvGP9zpPT%w{HM?^l3y065v5UduPBs7q8oSTi(acxRY7sZ zq`SPHH%hav$Zk&bV)dfNShbZ6e6i^Jq{fGozIsFG=a9|KjH+FZAZXNR3?stsJU95c zQ)T=ZCz@G`Ms$R+#^>*d56ACFB(x3qi>B1771FR{AZ*Qt=izrc9xK00@wY1ZdPC){ z$Z*b?t^5UgepbFAP*cVjEejWNsTQ}GZVKb>QFNuaI+d3U!#B({8PDS+)oomeHl}zZ z%6NEVZELHrb+7bjY?JPduW%o`Nb2o*Q@Zym_tvr}hSjVJ)205p{rL>~bIr87 z`?^Xx_bB%|{g$BIjf4A%xKEr>x4z$x3c|3h{G;Hrj9K|6>J8f>E59fB+?;FW4@$ys z0)J!z_g8{{LIVDelJK{J?@r);Taxe}NWyOh%@16y9KbNL8aJ>vB#d1&DBj8T{!JAR-QHh;u-VUHNCp9=_`?;TV4j|r z3_MAuhyFfhd?xkP^;@TNvx-N{UYXA5yl_WxVHgwi@*oC+RTyYRF=fMD*BJbc=k(OQ zF@zi4{aq&zb1HDbnIFRv^k!~Mr%J<^=yj+yF{4uHvlcqjl$7vSR7y&5$$CvmZ6yXx zB^|ESJKUpfeKWhhW_=9?XmgEHRgY19g|W^jSebqEik5ayS**0+&h2nbvAXtNrti!= znO?`M@U8_i?X3LElkl%ne32^4m#ru%EW+IC7}8~zUV>E-F$Q@+$>$t~hVw1Xv#fl! zReTc81G_IS#Y@2&Qw=T}&mF@u;+iGnI|p`}V`#b&->_sN!JS|EW7|a23+*8FDXu^F ze9}$oJ(>k!ZdSC;C#(Mv@XvUD^w=Z9z4iSac+d7%PT4Sg=NL##DzJ*6KB>tukMM37 zvt_*WdQU$^v+t#`##01{*ezA=bU(5R3UmC^MFbPh5`KfCSr=&%=1T!@Y!^LNZO85H z_~i;LDr~G#6?T^jN3>bT3`dPHkqTJ$MSa81@8B0tF#Qw1TvV&VYgggr39Y)vTWEu+ z1AozEez;+F`KB88yqZmOQNzTvbguHJ+dm9ngwgrf)+FzfY&=)C8|@Jben--ttrFX| zD_VVb)9I|+Ay-(wk7=}o*Qn{u(w$d@=ba<-TetgvftI82$b#=4J-Tx_1lQ+}9zEWT zmoT2W(w~+;Q_*@Hv_#Rm99!2LWjmR)HJt3n&2Sq+STz!B1sejNV-y^N#M2~uJsBxrQ$=B%;J1En;`A-sc zd9a4#JtW^ZD%9>&a2?-!-AbOypE4|eVfg{=(gZ97bIkxFd^xt0Q)!k^7U|ZLWqwUi z0V@Bp7$XGr69n>?Op*lxzb>x~N7u8Aju7M|OptkbfvSyxO|>OrHlI6Yd{$v8*6Hd|?{z*IdOY%+%m-^bhv6;$ zcXYAxr-n9Fmxi(0jh`Ru_@3dJC(}o-6K+6-XZy~tNp81c#MFB|-qY=@H9f5JOZNnL zhOxS9QQ_%&#<4q1s_GBf2Ga=f`VVTdF<X*ow= z-8zOu307XZt}<8^VP_anawbaki~fQ5d0Ad_$Pxu9{g3E%Z&@56vkcrv54g3 z)0kR!Srxy|xsofKE9>i4RxB4Qo2xp0`D#(PVi|9!lxvss)Y@e}*1n3u;e0GyE|WhM zvKR|^Z1=%kj;|2;T(w-lRm))QLa}TKkPDTI#E%BCF{2-x&Dd0+mMLi`k0Eo7l6JYI z_bvRwNMMm#pBa65miMS}m7GgD0S(kA!vXD!VE96=o z1uPZokDa3Ov8-4CRaatBv6H({EJb1k5yBVoyZ^G5(|a% z#X_ME>x4@7LUi5puuO;m=jjzf(#vXA)ds;_pw|YK1&es|#zG?>|0XKzKIV!~&9M4~zx!1$KK*d>d{UCo6vgcg`xz`2j#QG&hQTQ4l7D_9k z;cEBFLb04_98mgjtVd%F?_%&c=C}5P@p*us*%NC*^gnZ{jGr!Fr-R2dwDSGnu>@H8 zmEh4Ycio<>_TCa#87qthKpBTx^!I2}%egFznlsP0%&mv>_^BmUmKCe=YY~jmqV!=O zL8I$Oaq+}rey%81ljHz~PMfMxFiXgtTvDPsBkCmK9BAr?J~2=a~A*QJzq-UHM~MK*N0F+!^;D zi>aIXg({>hru!T4Gg0d6q~{cwK6*Vxr!QQs!`Ck46V^Dm9TQ*9D$vik*|s6vO68Ah zd^Fl0+eGb`ji2~FgZH;6_Z{mn!WZ_3HUyE?#i}*Mt?*SGo4E^CEOE<^QYu~ERQ~li z>saZ6^`wrQ_?@SAEzhiroIf1Pzy2W7IegH+5{9|9+`Y>6oe;LK${+u8v*DSE<*o9d z_+2lQy(%SFkH?lOTG!LFp##f>?l*)?u886DS1o@M07FqMJ%!PaFd5aiSU0~{vJi2i zAcayNY+}Wibu0qb8m&r>-cPL4E7|?}|66=S^`A7hV;Z}~IB4P|TGOA4G%O2N{$}u4 zMy>n{lkjf^pKXHGJ^8co#FZi0tssk+dNs0 zzANe$h^U{+m@i_);jJSPET7L2Ce7_i59&^HtaK~-Qk|2Uks(b!u=-Yo`Y#LI2cN9Gda8vVPO6q?BLOfcD|@VJ6~3VZ8$;9HL>_nXZ2@!2|car8aIN6Bc+&A0cs@IX@bLT^&og)) z#&ZXroA6wP=X-b>@C5Okj_2^7jvieOoR4P?9uJ;xaAr_f6S2HmBA0gMnqyE-x$a#h z>zy8de+z|)rH*ZZyEu>LZSzUrKw=Qa8LqU}|Mzmcfd zS9LyXY=1?*|3~*@cbqc}M{0{JuuGBOu+YSBUoF$Y$H>9lhKFV2pO%9OXZ-KTw<|d- zDFjBJpR@Ay`ME^=5%Bj<>lJ@k4B>5GBjbMxm4Ye7!#+mm19>!TYiK%tuU>tpm)yAb zv*r0LT~@J#_O*VmUdz*RG{!FJdfv+_uj$vS+*s0g1_t45ORVX*8v(Pg?D%~k?)Szv z)AH(2%|G_bglj7bp{>Sd1Un%5<()5tt5Sn`-5A z-j;|zCkej-e2yio;Y7gW-YzRY3f|HL{95ohZ_iT`N2|Z@;9a8dwt%0DM=g7FllMKm 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 Date: Wed, 19 Jul 2023 15:26:32 +0530 Subject: [PATCH 030/864] build: phoenix build scripts and readme --- .gitignore | 4 ++++ README.md | 16 ++++++++++++---- package.json | 7 ++++++- src-tauri/tauri.conf.json | 6 +++--- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index c3a7567d..899b398e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,10 @@ yarn-error.log* pnpm-debug.log* lerna-debug.log* +node-bins +src-build/node-* +src-tauri/node-* + node_modules dist dist-ssr diff --git a/README.md b/README.md index 694a18c6..925f7674 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,19 @@ # Phoenix Desktop This repo deals with Windows, Mac and Linux Desktop builds of [Phoenix IDE](https://github.com/phcode-dev/phoenix). -Please see https://github.com/phcode-dev/phoenix on how to Contribute or get in touch with the community. +Please see https://github.com/phcode-dev/phoenix on how to Contribute or get in touch with the community. ## Status Experimental development- Work in progress, Track status here: https://github.com/orgs/phcode-dev/projects/1/views/1 # Development Setup - We use [Tauri](https://tauri.app/) as our app shell. Follow the below - instructions to set up development environment. +We use [Tauri](https://tauri.app/) as our app shell. We maintain the [phcode-tauri-shell](https://github.com/phcode-dev/phoenix-desktop) and +[phcode static website](https://github.com/phcode-dev/phoenix) code in two separate repositories. This +separation is intended to simplify development by distinctly isolating the shell and phcode. For instance, +if you are solely developing the shell internals, you can always construct an empty tauri app without having to build phoenix. + +Follow the below +instructions to set up development environment. ## Prerequisites @@ -24,6 +29,9 @@ git clone https://github.com/phcode-dev/phoenix.git ``` ## Running Phoenix Desktop Development Builds +For development, tauri will directly load the phcode static +server url "localhost:8000/src" from the phoenix repo. So you +can quickly iterate changes without rebuilding tauri src for each change. Just a simple reload will suffice. 1. Setup and run `phoenix` by following the steps. ```bash @@ -42,7 +50,7 @@ git clone https://github.com/phcode-dev/phoenix.git Phoenix Desktop will start compiling and the editor window should appear after the build is done. 3. Now you can make changes to [phoenix](https://github.com/phcode-dev/phoenix) and [phoenix-desktop](https://github.com/phcode-dev/phoenix-desktop) independently and see changes live. * Changes in `phoenix-desktop` folder built with Tauri will be auto compiled and live patched on save. - * To load changes in `phoenix` folder, just reload Phoenix by pressing `f5` in the Phoenix window just like you would do on the browser versions of Phoenix. + * To load changes in `phoenix` folder, just reload Phoenix by pressing `f5` in the Phoenix window just like you would do on the browser versions of Phoenix. ## Building release binaries wip: hyperlink to the wiki for release generation diff --git a/package.json b/package.json index 3275bd62..a46b8710 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "tauri": "tauri", "build": "", "servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", - "serve": "tauri dev", + "serve": "npm run servePhoenix && tauri dev", "postinstall": "node ./src-build/downloadNode.js", "cleanNode": "node src-build/cleanNode.js", "preinstallNodeArmDarwin": "npm run cleanNode", @@ -20,6 +20,11 @@ "adm-zip": "0.5.10", "fs-extra": "11.1.1" }, + "phoenixRepo" : { + "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", + "branch": "tauri", + "commit": "2e5dceb684970780204485f3209b1707b19b634a" + }, "dependencies": { } } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1a513a71..fd1f4818 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,9 +1,9 @@ { "$schema": "../node_modules/@tauri-apps/cli/schema.json", "build": { - "beforeBuildCommand": "npm run build", - "beforeDevCommand": "npm run servePhoenix", - "devPath": "../src/", + "beforeBuildCommand": "", + "beforeDevCommand": "", + "devPath": "http://localhost:8000/src/", "distDir": "../src/", "withGlobalTauri": true }, From 64fafb098579a79eb1f99542276ff974e93e34c0 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 20 Jul 2023 15:17:23 +0530 Subject: [PATCH 031/864] feat: add local release build generation scripts --- .gitignore | 1 + README.md | 38 +++++++++++++++++++++-- package.json | 6 ++++ src-build/createLocalReleaseConfig.js | 24 ++++++++++++++ src-build/createLocalReleaseConfigDist.js | 24 ++++++++++++++ 5 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 src-build/createLocalReleaseConfig.js create mode 100644 src-build/createLocalReleaseConfigDist.js diff --git a/.gitignore b/.gitignore index 899b398e..f123398a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ lerna-debug.log* node-bins src-build/node-* src-tauri/node-* +src-tauri/tauri-local.conf.json node_modules dist diff --git a/README.md b/README.md index 925f7674..df452da1 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ Get [phoenix](https://github.com/phcode-dev/phoenix) and [phoenix-desktop](https git clone https://github.com/phcode-dev/phoenix-desktop.git git clone https://github.com/phcode-dev/phoenix.git ``` +> **_IMPORTANT:_** `phoenix` and `phoenix-desktop` should be within the same parent directory!!! ## Running Phoenix Desktop Development Builds For development, tauri will directly load the phcode static @@ -52,8 +53,41 @@ can quickly iterate changes without rebuilding tauri src for each change. Just a * Changes in `phoenix-desktop` folder built with Tauri will be auto compiled and live patched on save. * To load changes in `phoenix` folder, just reload Phoenix by pressing `f5` in the Phoenix window just like you would do on the browser versions of Phoenix. -## Building release binaries -wip: hyperlink to the wiki for release generation +## Building release binaries locally for development/testing +Tauri development builds load phcode from `https://` url. But the release build uses packaged assets with custom tauri url +`tauri://`. So there may be some cases where the behavior is different between the release builds and development builds. + +> **_IMPORTANT:_** `phoenix` and `phoenix-desktop` projects should be within the same parent directory for the below commands to work!!! + +### generate release builds from the `phoenix/src` folder +If you want to generate the release builds locally directly while you are editing the `phoenix/src` folder, run the following command. +```bash +cd phoenix-desktop +# To generate debug builds: +npm run releaseLocalDebug +# OR to generate release builds, just run `npm run releaseLocal` +``` +This is the easiest way to quickly debug issues directly from the phoenix source folder. + +### generate dev, staging and prod release builds from `phoenix/dist` folder +These builds are faithful to the actual binaries that are generated from the github CI pipelines shipped to users. +If you want to generate the dev, staging and prod builds locally of phcode, run the following command: +```bash +# You should first build the appropriate release build in `phoenix`. +cd phoenix +npm install +npm run build +npm run release:prod +# Other release options are `npm run release:dev` and `npm run release:staging` + +# Now generate the tauri debug builds: +cd ../phoenix-desktop +npm run releaseLocalDistDebug +# OR to generate release builds, just run `npm run releaseLocalDist` +``` + +## Building release binaries in github actions +WIP: TBD ## Creating Installers wip: hyperlink to the wiki for installer generation diff --git a/package.json b/package.json index a46b8710..a6f56cff 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,12 @@ "scripts": { "tauri": "tauri", "build": "", + "createLocalReleaseConfig": "node ./src-build/createLocalReleaseConfig.js", + "createLocalReleaseConfigDist": "node ./src-build/createLocalReleaseConfigDist.js", + "releaseLocal": "npm run createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseLocalDist": "npm run createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseLocalDebug": "npm run createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseLocalDistDebug": "npm run createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", "serve": "npm run servePhoenix && tauri dev", "postinstall": "node ./src-build/downloadNode.js", diff --git a/src-build/createLocalReleaseConfig.js b/src-build/createLocalReleaseConfig.js new file mode 100644 index 00000000..5257e80f --- /dev/null +++ b/src-build/createLocalReleaseConfig.js @@ -0,0 +1,24 @@ +import {fileURLToPath} from "url"; +import {dirname} from "path"; +import fs from 'fs'; + +import {getPlatformDetails} from "./utils.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +async function createLocalReleaseConfig() { + const platform = getPlatformDetails().platform; + const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` + : `${__dirname}/../src-tauri/tauri.conf.json`; + const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` + : `${__dirname}/../src-tauri/tauri-local.conf.json`; + console.log("Reading config file: ", tauriConfigPath); + let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + delete configJson.tauri.updater; + configJson.build.distDir = '../../phoenix/src/' + console.log("Writing new local config json ", tauriLocalConfigPath); + fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); +} + +await createLocalReleaseConfig(); diff --git a/src-build/createLocalReleaseConfigDist.js b/src-build/createLocalReleaseConfigDist.js new file mode 100644 index 00000000..4af61e3e --- /dev/null +++ b/src-build/createLocalReleaseConfigDist.js @@ -0,0 +1,24 @@ +import {fileURLToPath} from "url"; +import {dirname} from "path"; +import fs from 'fs'; + +import {getPlatformDetails} from "./utils.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +async function createLocalReleaseConfig() { + const platform = getPlatformDetails().platform; + const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` + : `${__dirname}/../src-tauri/tauri.conf.json`; + const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` + : `${__dirname}/../src-tauri/tauri-local.conf.json`; + console.log("Reading config file: ", tauriConfigPath); + let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + delete configJson.tauri.updater; + configJson.build.distDir = '../../phoenix/dist/' + console.log("Writing new local config json ", tauriLocalConfigPath); + fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); +} + +await createLocalReleaseConfig(); From 6269e754835f54817efbab4c479caa30afc5d222 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 20 Jul 2023 23:07:24 +0530 Subject: [PATCH 032/864] feat: release build generation scripts --- .gitignore | 2 + package-lock.json | 1452 ++++++++++++++++---------- package.json | 74 +- src-build/clonePhoenix.js | 29 + src-build/createDistReleaseConfig.js | 49 + src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 7 files changed, 1013 insertions(+), 597 deletions(-) create mode 100644 src-build/clonePhoenix.js create mode 100644 src-build/createDistReleaseConfig.js diff --git a/.gitignore b/.gitignore index f123398a..95e305e1 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ node-bins src-build/node-* src-tauri/node-* src-tauri/tauri-local.conf.json +src-tauri/tauri-dist.conf.json +phoenix node_modules dist diff --git a/package-lock.json b/package-lock.json index 8d968f8f..cdface35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,567 +1,899 @@ { - "name": "phoenix-code-ide", - "version": "5.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "phoenix-code-ide", - "version": "5.0.0", - "hasInstallScript": true, - "devDependencies": { - "@tauri-apps/cli": "1.4.0", - "adm-zip": "0.5.10", - "fs-extra": "11.1.1", - "tar": "6.1.15" - } - }, - "node_modules/@tauri-apps/cli": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.4.0.tgz", - "integrity": "sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==", - "dev": true, - "bin": { - "tauri": "tauri.js" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/tauri" - }, - "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.4.0", - "@tauri-apps/cli-darwin-x64": "1.4.0", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.4.0", - "@tauri-apps/cli-linux-arm64-gnu": "1.4.0", - "@tauri-apps/cli-linux-arm64-musl": "1.4.0", - "@tauri-apps/cli-linux-x64-gnu": "1.4.0", - "@tauri-apps/cli-linux-x64-musl": "1.4.0", - "@tauri-apps/cli-win32-arm64-msvc": "1.4.0", - "@tauri-apps/cli-win32-ia32-msvc": "1.4.0", - "@tauri-apps/cli-win32-x64-msvc": "1.4.0" - } - }, - "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.4.0.tgz", - "integrity": "sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.4.0.tgz", - "integrity": "sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.4.0.tgz", - "integrity": "sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.4.0.tgz", - "integrity": "sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.4.0.tgz", - "integrity": "sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.4.0.tgz", - "integrity": "sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.4.0.tgz", - "integrity": "sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.4.0.tgz", - "integrity": "sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.4.0.tgz", - "integrity": "sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.4.0.tgz", - "integrity": "sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/adm-zip": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", - "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", - "dev": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - }, - "dependencies": { - "@tauri-apps/cli": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.4.0.tgz", - "integrity": "sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==", - "dev": true, - "requires": { - "@tauri-apps/cli-darwin-arm64": "1.4.0", - "@tauri-apps/cli-darwin-x64": "1.4.0", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.4.0", - "@tauri-apps/cli-linux-arm64-gnu": "1.4.0", - "@tauri-apps/cli-linux-arm64-musl": "1.4.0", - "@tauri-apps/cli-linux-x64-gnu": "1.4.0", - "@tauri-apps/cli-linux-x64-musl": "1.4.0", - "@tauri-apps/cli-win32-arm64-msvc": "1.4.0", - "@tauri-apps/cli-win32-ia32-msvc": "1.4.0", - "@tauri-apps/cli-win32-x64-msvc": "1.4.0" - } - }, - "@tauri-apps/cli-darwin-arm64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.4.0.tgz", - "integrity": "sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-darwin-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.4.0.tgz", - "integrity": "sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.4.0.tgz", - "integrity": "sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.4.0.tgz", - "integrity": "sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-arm64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.4.0.tgz", - "integrity": "sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-x64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.4.0.tgz", - "integrity": "sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-x64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.4.0.tgz", - "integrity": "sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.4.0.tgz", - "integrity": "sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.4.0.tgz", - "integrity": "sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-win32-x64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.4.0.tgz", - "integrity": "sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==", - "dev": true, - "optional": true - }, - "adm-zip": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", - "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", - "dev": true - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } + "name": "phoenix-code-ide", + "version": "3.2.2", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "phoenix-code-ide", + "version": "3.2.2", + "hasInstallScript": true, + "devDependencies": { + "@tauri-apps/cli": "1.4.0", + "adm-zip": "0.5.10", + "execa": "^7.1.1", + "fs-extra": "11.1.1", + "tar": "6.1.15" + } + }, + "node_modules/@tauri-apps/cli": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.4.0.tgz", + "integrity": "sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==", + "dev": true, + "bin": { + "tauri": "tauri.js" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/tauri" + }, + "optionalDependencies": { + "@tauri-apps/cli-darwin-arm64": "1.4.0", + "@tauri-apps/cli-darwin-x64": "1.4.0", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.4.0", + "@tauri-apps/cli-linux-arm64-gnu": "1.4.0", + "@tauri-apps/cli-linux-arm64-musl": "1.4.0", + "@tauri-apps/cli-linux-x64-gnu": "1.4.0", + "@tauri-apps/cli-linux-x64-musl": "1.4.0", + "@tauri-apps/cli-win32-arm64-msvc": "1.4.0", + "@tauri-apps/cli-win32-ia32-msvc": "1.4.0", + "@tauri-apps/cli-win32-x64-msvc": "1.4.0" + } + }, + "node_modules/@tauri-apps/cli-darwin-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.4.0.tgz", + "integrity": "sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-darwin-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.4.0.tgz", + "integrity": "sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.4.0.tgz", + "integrity": "sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm64-gnu": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.4.0.tgz", + "integrity": "sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-arm64-musl": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.4.0.tgz", + "integrity": "sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-x64-gnu": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.4.0.tgz", + "integrity": "sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-linux-x64-musl": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.4.0.tgz", + "integrity": "sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-arm64-msvc": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.4.0.tgz", + "integrity": "sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-ia32-msvc": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.4.0.tgz", + "integrity": "sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tauri-apps/cli-win32-x64-msvc": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.4.0.tgz", + "integrity": "sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/execa": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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 + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { + "dependencies": { + "@tauri-apps/cli": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.4.0.tgz", + "integrity": "sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==", + "dev": true, + "requires": { + "@tauri-apps/cli-darwin-arm64": "1.4.0", + "@tauri-apps/cli-darwin-x64": "1.4.0", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.4.0", + "@tauri-apps/cli-linux-arm64-gnu": "1.4.0", + "@tauri-apps/cli-linux-arm64-musl": "1.4.0", + "@tauri-apps/cli-linux-x64-gnu": "1.4.0", + "@tauri-apps/cli-linux-x64-musl": "1.4.0", + "@tauri-apps/cli-win32-arm64-msvc": "1.4.0", + "@tauri-apps/cli-win32-ia32-msvc": "1.4.0", + "@tauri-apps/cli-win32-x64-msvc": "1.4.0" + } + }, + "@tauri-apps/cli-darwin-arm64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.4.0.tgz", + "integrity": "sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==", + "dev": true, + "optional": true + }, + "@tauri-apps/cli-darwin-x64": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.4.0.tgz", + "integrity": "sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==", + "dev": true, + "optional": true + }, + "@tauri-apps/cli-linux-arm-gnueabihf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.4.0.tgz", + "integrity": "sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==", + "dev": true, + "optional": true + }, + "@tauri-apps/cli-linux-arm64-gnu": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.4.0.tgz", + "integrity": "sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==", + "dev": true, + "optional": true + }, + "@tauri-apps/cli-linux-arm64-musl": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.4.0.tgz", + "integrity": "sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==", + "dev": true, + "optional": true + }, + "@tauri-apps/cli-linux-x64-gnu": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.4.0.tgz", + "integrity": "sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==", + "dev": true, + "optional": true + }, + "@tauri-apps/cli-linux-x64-musl": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.4.0.tgz", + "integrity": "sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==", + "dev": true, + "optional": true + }, + "@tauri-apps/cli-win32-arm64-msvc": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.4.0.tgz", + "integrity": "sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==", + "dev": true, + "optional": true + }, + "@tauri-apps/cli-win32-ia32-msvc": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.4.0.tgz", + "integrity": "sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==", + "dev": true, + "optional": true + }, + "@tauri-apps/cli-win32-x64-msvc": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.4.0.tgz", + "integrity": "sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==", + "dev": true, + "optional": true + }, + "adm-zip": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", + "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "dev": true + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "execa": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + }, + "dependencies": { + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + } + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "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 + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + }, + "tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true } - } } diff --git a/package.json b/package.json index a6f56cff..d5a1a54f 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,40 @@ { - "name": "phoenix-code-ide", - "private": true, - "version": "5.0.0", - "type": "module", - "scripts": { - "tauri": "tauri", - "build": "", - "createLocalReleaseConfig": "node ./src-build/createLocalReleaseConfig.js", - "createLocalReleaseConfigDist": "node ./src-build/createLocalReleaseConfigDist.js", - "releaseLocal": "npm run createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseLocalDist": "npm run createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseLocalDebug": "npm run createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", - "releaseLocalDistDebug": "npm run createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json --debug", - "servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", - "serve": "npm run servePhoenix && tauri dev", - "postinstall": "node ./src-build/downloadNode.js", - "cleanNode": "node src-build/cleanNode.js", - "preinstallNodeArmDarwin": "npm run cleanNode", - "installNodeArmDarwin": "node ./src-build/downloadNode.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", - "getPackageVersion" : "node ./src-build/getVersion.js" - }, - "devDependencies": { - "@tauri-apps/cli": "1.4.0", - "tar": "6.1.15", - "adm-zip": "0.5.10", - "fs-extra": "11.1.1" - }, - "phoenixRepo" : { - "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", - "branch": "tauri", - "commit": "2e5dceb684970780204485f3209b1707b19b634a" - }, - "dependencies": { - } -} + "name": "phoenix-code-ide", + "private": true, + "version": "3.2.2", + "type": "module", + "scripts": { + "tauri": "tauri", + "build": "", + "createLocalReleaseConfig": "node ./src-build/createLocalReleaseConfig.js", + "createLocalReleaseConfigDist": "node ./src-build/createLocalReleaseConfigDist.js", + "ci-createDistReleaseConfig": "node ./src-build/createDistReleaseConfig.js", + "releaseLocal": "npm run createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseLocalDist": "npm run createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseLocalDebug": "npm run createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseLocalDistDebug": "npm run createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", + "ci-cloneAndBuildPhoenix": "node ./src-build/clonePhoenix.js && cd phoenix && npm install && npm run build && cd ..", + "ci-release:dev": "npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", + "ci-release:staging": "npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", + "ci-release:prod": "npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", + "serve": "npm run servePhoenix && tauri dev", + "postinstall": "node ./src-build/downloadNode.js", + "cleanNode": "node src-build/cleanNode.js", + "preinstallNodeArmDarwin": "npm run cleanNode", + "installNodeArmDarwin": "node ./src-build/downloadNode.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", + "getPackageVersion": "node ./src-build/getVersion.js" + }, + "devDependencies": { + "@tauri-apps/cli": "1.4.0", + "adm-zip": "0.5.10", + "execa": "^7.1.1", + "fs-extra": "11.1.1", + "tar": "6.1.15" + }, + "phoenixRepo": { + "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", + "branch": "tauri", + "commit": "2e5dceb684970780204485f3209b1707b19b634a" + } +} \ No newline at end of file diff --git a/src-build/clonePhoenix.js b/src-build/clonePhoenix.js new file mode 100644 index 00000000..6d40ea0e --- /dev/null +++ b/src-build/clonePhoenix.js @@ -0,0 +1,29 @@ +import {$} from 'execa'; // https://www.npmjs.com/package/execa +import fs from 'fs'; +import path from 'path' + +console.log("Cloning phoenix..."); +async function pwd() { + let output = await $`pwd`; + const pwd = output.stdout.toString(); + console.log("pwd ", pwd); + return pwd; +} + +const projectDir = await pwd(); +const phoenixProjectPath = path.join(projectDir, "phoenix"); +console.log("current dir: ", projectDir); + +let packageJSONPath = path.join(projectDir, 'package.json'); +console.log('loading package.json: ', packageJSONPath); + +let packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf-8')); +const phoenixRepo = packageJSON.phoenixRepo; +console.log(`Cloning`, phoenixRepo); +if(!fs.existsSync(phoenixProjectPath)){ + await $`git clone ${phoenixRepo.gitClonrUrl} --branch ${phoenixRepo.branch}`; +} +process.chdir('phoenix'); +await pwd(); +console.log('checking out commit: ', phoenixRepo.commit); +await $`git checkout ${phoenixRepo.commit}`; \ No newline at end of file diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js new file mode 100644 index 00000000..3d88c7c4 --- /dev/null +++ b/src-build/createDistReleaseConfig.js @@ -0,0 +1,49 @@ +import {fileURLToPath} from "url"; +import {dirname, join} from "path"; +import { EOL } from "os"; +import fs from 'fs'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +async function patchVersionNumbers() { + const phoenixConfigPath = join(__dirname, '..', 'phoenix', 'dist', 'config.json'); + const packageJSONPath = join(__dirname, '..', 'package.json'); + const tauriTOMLPath = join(__dirname, '..', 'src-tauri', 'Cargo.toml'); + console.log("loading phoenix config: ", phoenixConfigPath); + + let configJson = JSON.parse(fs.readFileSync(phoenixConfigPath)); + const phoenixVersion = configJson.version.split("-")[0]; + const phoenixStage = configJson.config.environment; + console.log("phoenix version detected is: ", phoenixVersion); // "version": "3.2.2-19332" + console.log("phoenix stage is: ", phoenixStage); + console.log("write version in package.json", packageJSONPath); + let packageJson = JSON.parse(fs.readFileSync(packageJSONPath)); + packageJson.version = phoenixVersion; + fs.writeFileSync(packageJSONPath, JSON.stringify(packageJson, null, 4)); + + console.log("write version in cargo.toml", tauriTOMLPath); + const toml = fs.readFileSync(tauriTOMLPath).toString(); + const lines = toml.split(/\r?\n/); + for(let i=0;i Date: Thu, 20 Jul 2023 23:12:08 +0530 Subject: [PATCH 033/864] fix: update version in tauri.conf.json as well --- src-build/createDistReleaseConfig.js | 6 + src-tauri/tauri.conf.json | 192 +++++++++++++-------------- 2 files changed, 102 insertions(+), 96 deletions(-) diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index 3d88c7c4..7e31cb73 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -10,6 +10,7 @@ async function patchVersionNumbers() { const phoenixConfigPath = join(__dirname, '..', 'phoenix', 'dist', 'config.json'); const packageJSONPath = join(__dirname, '..', 'package.json'); const tauriTOMLPath = join(__dirname, '..', 'src-tauri', 'Cargo.toml'); + const tauriConfigPath = join(__dirname, '..', 'src-tauri', 'tauri.conf.json'); console.log("loading phoenix config: ", phoenixConfigPath); let configJson = JSON.parse(fs.readFileSync(phoenixConfigPath)); @@ -32,6 +33,11 @@ async function patchVersionNumbers() { } const patchedTOML = lines.join(EOL); fs.writeFileSync(tauriTOMLPath, patchedTOML); + + console.log("write version in tauri.conf.json", tauriConfigPath); + configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + configJson.package.version = phoenixVersion; + fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); return phoenixVersion; } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a568b910..8a3a3394 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,99 +1,99 @@ { - "$schema": "../node_modules/@tauri-apps/cli/schema.json", - "build": { - "beforeBuildCommand": "", - "beforeDevCommand": "", - "devPath": "http://localhost:8000/src/", - "distDir": "../src/", - "withGlobalTauri": true - }, - "package": { - "productName": "PhCode", - "version": "3.0.0" - }, - "tauri": { - "allowlist": { - "all": false, - "window": { - "all": true - }, - "fs": { - "all": true, - "scope": [ - "$RESOURCE/*" - ] - }, - "shell": { - "sidecar": true, - "scope": [ - { - "name": "node", - "sidecar": true - } - ] - } - }, - "bundle": { - "active": true, - "category": "DeveloperTool", - "copyright": "Copyright (c) 2022 - present Core.ai", - "deb": { - "depends": [] - }, - "externalBin": [ - "./node" - ], - "icon": [ - "icons/32x32.png", - "icons/128x128.png", - "icons/128x128@2x.png", - "icons/icon.icns", - "icons/icon.ico" - ], - "identifier": "dev.phcode", - "longDescription": "", - "macOS": { - "entitlements": null, - "exceptionDomain": "", - "frameworks": [], - "providerShortName": null, - "signingIdentity": null - }, - "resources": [ - "app/*" - ], - "shortDescription": "", - "targets": "all", - "windows": { - "certificateThumbprint": "AB7D19C00251C1E412594A28DC79D201AAEF50D0", - "digestAlgorithm": "sha256", - "timestampUrl": "http://timestamp.comodoca.com" - } + "$schema": "../node_modules/@tauri-apps/cli/schema.json", + "build": { + "beforeBuildCommand": "", + "beforeDevCommand": "", + "devPath": "http://localhost:8000/src/", + "distDir": "../src/", + "withGlobalTauri": true }, - "security": { - "csp": null + "package": { + "productName": "PhCode", + "version": "3.2.2" }, - "updater": { - "active": true, - "windows": { - "installMode": "passive" - }, - "endpoints": [ - "https://releases.phcode.dev/{{target}}/{{arch}}/{{current_version}}" - ], - "dialog": true, - "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDY2QTY2RjMxQUIzQkU0RDQKUldUVTVEdXJNVyttWmc2ODNSODlVcmZhS0dFRW1mYnBkaytvTDcrSDJXSlhYOHVrUWRyaXhHRjcK" - }, - "windows": [ - { - "fullscreen": false, - "height": 768, - "minHeight": 600, - "resizable": true, - "title": "Phoenix Code", - "width": 1024, - "minWidth": 800 - } - ] - } -} + "tauri": { + "allowlist": { + "all": false, + "window": { + "all": true + }, + "fs": { + "all": true, + "scope": [ + "$RESOURCE/*" + ] + }, + "shell": { + "sidecar": true, + "scope": [ + { + "name": "node", + "sidecar": true + } + ] + } + }, + "bundle": { + "active": true, + "category": "DeveloperTool", + "copyright": "Copyright (c) 2022 - present Core.ai", + "deb": { + "depends": [] + }, + "externalBin": [ + "./node" + ], + "icon": [ + "icons/32x32.png", + "icons/128x128.png", + "icons/128x128@2x.png", + "icons/icon.icns", + "icons/icon.ico" + ], + "identifier": "dev.phcode", + "longDescription": "", + "macOS": { + "entitlements": null, + "exceptionDomain": "", + "frameworks": [], + "providerShortName": null, + "signingIdentity": null + }, + "resources": [ + "app/*" + ], + "shortDescription": "", + "targets": "all", + "windows": { + "certificateThumbprint": "AB7D19C00251C1E412594A28DC79D201AAEF50D0", + "digestAlgorithm": "sha256", + "timestampUrl": "http://timestamp.comodoca.com" + } + }, + "security": { + "csp": null + }, + "updater": { + "active": true, + "windows": { + "installMode": "passive" + }, + "endpoints": [ + "https://releases.phcode.dev/{{target}}/{{arch}}/{{current_version}}" + ], + "dialog": true, + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDY2QTY2RjMxQUIzQkU0RDQKUldUVTVEdXJNVyttWmc2ODNSODlVcmZhS0dFRW1mYnBkaytvTDcrSDJXSlhYOHVrUWRyaXhHRjcK" + }, + "windows": [ + { + "fullscreen": false, + "height": 768, + "minHeight": 600, + "resizable": true, + "title": "Phoenix Code", + "width": 1024, + "minWidth": 800 + } + ] + } +} \ No newline at end of file From fee3ab42cb56b4f12f101cb369cb240a73c0abe3 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 20 Jul 2023 23:19:52 +0530 Subject: [PATCH 034/864] docs: update readme with release build commands and docs --- README.md | 14 ++++++++------ src-tauri/Cargo.lock | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index df452da1..9faaa541 100644 --- a/README.md +++ b/README.md @@ -86,14 +86,16 @@ npm run releaseLocalDistDebug # OR to generate release builds, just run `npm run releaseLocalDist` ``` -## Building release binaries in github actions -WIP: TBD - -## Creating Installers -wip: hyperlink to the wiki for installer generation +## Building release binaries and installers in github actions +In GitHub actions or ci, run the following commands to build phcode release binaries +```bash +cd phoenix-desktop +npm install +npm run ci-release:prod +# Other release options are `ci-release:dev` and `ci-release:staging` +``` # License -Discussion: #184 GNU AGPL-3.0 License diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index dad7e570..2c3c3bf9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2027,7 +2027,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "5.0.0" +version = "3.2.2" dependencies = [ "serde", "serde_json", From e3fe428fdd626fd453952abfdf1bfb0d9b848c83 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 21 Jul 2023 12:56:29 +0530 Subject: [PATCH 035/864] build: refactor ci scripts --- README.md | 35 +++++++++++++++++-- package.json | 27 +++++++------- ...onfig.js => ci-createDistReleaseConfig.js} | 5 +-- 3 files changed, 49 insertions(+), 18 deletions(-) rename src-build/{createDistReleaseConfig.js => ci-createDistReleaseConfig.js} (94%) diff --git a/README.md b/README.md index 9faaa541..2277446c 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,12 @@ can quickly iterate changes without rebuilding tauri src for each change. Just a * To load changes in `phoenix` folder, just reload Phoenix by pressing `f5` in the Phoenix window just like you would do on the browser versions of Phoenix. ## Building release binaries locally for development/testing + +> Note: For the majority of development tasks, it's not necessary to build the release artifacts locally, +> as outlined in this section. Most development requirements can be met by simply following the instructions +> provided in the [Running Phoenix Desktop Development Builds](#running-phoenix-desktop-development-builds) section. +> This process is mainly required when you want to test something specific that might behave differently under the `tauri://` protocol. + Tauri development builds load phcode from `https://` url. But the release build uses packaged assets with custom tauri url `tauri://`. So there may be some cases where the behavior is different between the release builds and development builds. @@ -86,15 +92,38 @@ npm run releaseLocalDistDebug # OR to generate release builds, just run `npm run releaseLocalDist` ``` -## Building release binaries and installers in github actions -In GitHub actions or ci, run the following commands to build phcode release binaries +## Building release binaries and installers in GitHub actions +The npm commands that begin with `ci-*` are exclusively designed to execute in a GitHub Actions environment. +These commands are not typically executed on your local machine unless you're actively working on the GitHub +Actions workflows. However, if you need to run these locally for testing, look for `#uncomment_line_for_local_build_1` +in the codebase and uncomment the corresponding line. + +### Primary GitHub Actions Targets +There are three primary targets for our GitHub actions: +1. `npm run ci-release:prod` +2. `npm run ci-release:dev` +3. `npm run ci-release:staging` + +To run the ci-release script, you can use the following steps: ```bash +# Example on how to run the ci-release script. cd phoenix-desktop npm install npm run ci-release:prod -# Other release options are `ci-release:dev` and `ci-release:staging` ``` +### Execution Workflow +The script will begin by cloning the repository identified in the `phoenixRepo` section of the `package.json` file. +Next, it will build the corresponding stage as specified in the `npm run ci-release:` command and will +generate the necessary distribution folders in `phoenix/dist`. Following this, it will patch the Tauri configuration files +to use the generated distribution folder for creating the release builds. + +The actual release artifacts will then be built by the tauri action `tauri-apps/tauri-action@v0` specified in the +`tauri-build.yml` file. Finally, it will generate a draft release. + +Remember, the `npm run ci-*` commands are designed to execute in the GitHub Actions environment. +They're not typically used for local machine executions unless you're working on or testing the GitHub Actions workflows themselves. + # License GNU AGPL-3.0 License diff --git a/package.json b/package.json index d5a1a54f..2a539c26 100644 --- a/package.json +++ b/package.json @@ -6,19 +6,20 @@ "scripts": { "tauri": "tauri", "build": "", - "createLocalReleaseConfig": "node ./src-build/createLocalReleaseConfig.js", - "createLocalReleaseConfigDist": "node ./src-build/createLocalReleaseConfigDist.js", - "ci-createDistReleaseConfig": "node ./src-build/createDistReleaseConfig.js", - "releaseLocal": "npm run createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseLocalDist": "npm run createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseLocalDebug": "npm run createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", - "releaseLocalDistDebug": "npm run createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json --debug", - "servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", - "ci-cloneAndBuildPhoenix": "node ./src-build/clonePhoenix.js && cd phoenix && npm install && npm run build && cd ..", - "ci-release:dev": "npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", - "ci-release:staging": "npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", - "ci-release:prod": "npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", - "serve": "npm run servePhoenix && tauri dev", + "_createLocalReleaseConfig": "node ./src-build/createLocalReleaseConfig.js", + "_createLocalReleaseConfigDist": "node ./src-build/createLocalReleaseConfigDist.js", + "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", + "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", + "releaseLocal": "npm run _createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseLocalDist": "npm run _createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseLocalDebug": "npm run _createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseLocalDistDebug": "npm run _createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "_servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", + "ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm install && npm run build && cd ..", + "ci-release:dev": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", + "ci-release:staging": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", + "ci-release:prod": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", + "serve": "npm run _servePhoenix && tauri dev", "postinstall": "node ./src-build/downloadNode.js", "cleanNode": "node src-build/cleanNode.js", "preinstallNodeArmDarwin": "npm run cleanNode", diff --git a/src-build/createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js similarity index 94% rename from src-build/createDistReleaseConfig.js rename to src-build/ci-createDistReleaseConfig.js index 7e31cb73..0cd12c70 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -41,15 +41,16 @@ async function patchVersionNumbers() { return phoenixVersion; } -async function createDistReleaseConfig() { +async function ciCreateDistReleaseConfig() { const tauriConfigPath = join(__dirname, '..', 'src-tauri', 'tauri.conf.json'); const tauriDistConfigPath = join(__dirname, '..', 'src-tauri', 'tauri-dist.conf.json'); console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); configJson.package.version = await patchVersionNumbers() || "3.0.0"; + // delete configJson.tauri.updater; // #uncomment_line_for_local_build_1 configJson.build.distDir = '../phoenix/dist/' console.log("Writing new dist config json ", tauriDistConfigPath); fs.writeFileSync(tauriDistConfigPath, JSON.stringify(configJson, null, 4)); } -await createDistReleaseConfig(); +await ciCreateDistReleaseConfig(); From 76ea0080a3cbdaa3cc94919f731ff4fccb021310 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 21 Jul 2023 13:10:37 +0530 Subject: [PATCH 036/864] build: refactor ci scripts for more clarity --- README.md | 4 +++- package.json | 6 +++--- src-build/ci-createDistReleaseConfig.js | 5 ++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 2277446c..de4f0eab 100644 --- a/README.md +++ b/README.md @@ -106,10 +106,12 @@ There are three primary targets for our GitHub actions: To run the ci-release script, you can use the following steps: ```bash -# Example on how to run the ci-release script. +# Example on how to run the ci-release script locally. cd phoenix-desktop npm install npm run ci-release:prod +npm run tauri build --debug +# or if you want the release builds, use `npm run tauri build` ``` ### Execution Workflow diff --git a/package.json b/package.json index 2a539c26..746f60f5 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,9 @@ "releaseLocalDistDebug": "npm run _createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "_servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", "ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm install && npm run build && cd ..", - "ci-release:dev": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", - "ci-release:staging": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", - "ci-release:prod": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig && tauri build --config ./src-tauri/tauri-dist.conf.json", + "ci-release:dev": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig", + "ci-release:staging": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig", + "ci-release:prod": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig", "serve": "npm run _servePhoenix && tauri dev", "postinstall": "node ./src-build/downloadNode.js", "cleanNode": "node src-build/cleanNode.js", diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index 0cd12c70..ecae211b 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -43,14 +43,13 @@ async function patchVersionNumbers() { async function ciCreateDistReleaseConfig() { const tauriConfigPath = join(__dirname, '..', 'src-tauri', 'tauri.conf.json'); - const tauriDistConfigPath = join(__dirname, '..', 'src-tauri', 'tauri-dist.conf.json'); console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); configJson.package.version = await patchVersionNumbers() || "3.0.0"; // delete configJson.tauri.updater; // #uncomment_line_for_local_build_1 configJson.build.distDir = '../phoenix/dist/' - console.log("Writing new dist config json ", tauriDistConfigPath); - fs.writeFileSync(tauriDistConfigPath, JSON.stringify(configJson, null, 4)); + console.log("Writing new dist config json ", tauriConfigPath); + fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); } await ciCreateDistReleaseConfig(); From c61f75df16b7fc05cccabd1efeec254cb01617b8 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 21 Jul 2023 14:38:50 +0530 Subject: [PATCH 037/864] build: refactor ci scripts rename as private _ci for more clarity --- README.md | 16 ++++++++------- package.json | 20 +++++++++---------- ...nfigDist.js => createDistReleaseConfig.js} | 4 ++-- ...aseConfig.js => createSrcReleaseConfig.js} | 4 ++-- 4 files changed, 23 insertions(+), 21 deletions(-) rename src-build/{createLocalReleaseConfigDist.js => createDistReleaseConfig.js} (92%) rename src-build/{createLocalReleaseConfig.js => createSrcReleaseConfig.js} (92%) diff --git a/README.md b/README.md index de4f0eab..96792e43 100644 --- a/README.md +++ b/README.md @@ -93,37 +93,39 @@ npm run releaseLocalDistDebug ``` ## Building release binaries and installers in GitHub actions -The npm commands that begin with `ci-*` are exclusively designed to execute in a GitHub Actions environment. +The npm commands that begin with `_ci-*` are exclusively designed to execute in a GitHub Actions environment. These commands are not typically executed on your local machine unless you're actively working on the GitHub Actions workflows. However, if you need to run these locally for testing, look for `#uncomment_line_for_local_build_1` in the codebase and uncomment the corresponding line. +> NB: Make sure not to check in any artists created by the build process!!! + ### Primary GitHub Actions Targets There are three primary targets for our GitHub actions: -1. `npm run ci-release:prod` -2. `npm run ci-release:dev` -3. `npm run ci-release:staging` +1. `npm run _ci-release:prod` +2. `npm run _ci-release:dev` +3. `npm run _ci-release:staging` To run the ci-release script, you can use the following steps: ```bash # Example on how to run the ci-release script locally. cd phoenix-desktop npm install -npm run ci-release:prod +npm run _ci-release:prod npm run tauri build --debug # or if you want the release builds, use `npm run tauri build` ``` ### Execution Workflow The script will begin by cloning the repository identified in the `phoenixRepo` section of the `package.json` file. -Next, it will build the corresponding stage as specified in the `npm run ci-release:` command and will +Next, it will build the corresponding stage as specified in the `npm run _ci-release:` command and will generate the necessary distribution folders in `phoenix/dist`. Following this, it will patch the Tauri configuration files to use the generated distribution folder for creating the release builds. The actual release artifacts will then be built by the tauri action `tauri-apps/tauri-action@v0` specified in the `tauri-build.yml` file. Finally, it will generate a draft release. -Remember, the `npm run ci-*` commands are designed to execute in the GitHub Actions environment. +Remember, the `npm run _ci-*` commands are designed to execute in the GitHub Actions environment. They're not typically used for local machine executions unless you're working on or testing the GitHub Actions workflows themselves. # License diff --git a/package.json b/package.json index 746f60f5..c6742e62 100644 --- a/package.json +++ b/package.json @@ -6,19 +6,19 @@ "scripts": { "tauri": "tauri", "build": "", - "_createLocalReleaseConfig": "node ./src-build/createLocalReleaseConfig.js", - "_createLocalReleaseConfigDist": "node ./src-build/createLocalReleaseConfigDist.js", + "_createSrcReleaseConfig": "node src-build/createSrcReleaseConfig.js", + "_createDistReleaseConfig": "node src-build/createDistReleaseConfig.js", "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", - "releaseLocal": "npm run _createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseLocalDist": "npm run _createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseLocalDebug": "npm run _createLocalReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", - "releaseLocalDistDebug": "npm run _createLocalReleaseConfigDist && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseSrc": "npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseSrcDebug": "npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseDist": "npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseDistDebug": "npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "_servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", - "ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm install && npm run build && cd ..", - "ci-release:dev": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig", - "ci-release:staging": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig", - "ci-release:prod": "npm run _ci-env-warn && npm run ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig", + "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm install && npm run build && cd ..", + "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig", + "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig", + "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig", "serve": "npm run _servePhoenix && tauri dev", "postinstall": "node ./src-build/downloadNode.js", "cleanNode": "node src-build/cleanNode.js", diff --git a/src-build/createLocalReleaseConfigDist.js b/src-build/createDistReleaseConfig.js similarity index 92% rename from src-build/createLocalReleaseConfigDist.js rename to src-build/createDistReleaseConfig.js index 4af61e3e..123e491c 100644 --- a/src-build/createLocalReleaseConfigDist.js +++ b/src-build/createDistReleaseConfig.js @@ -7,7 +7,7 @@ import {getPlatformDetails} from "./utils.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -async function createLocalReleaseConfig() { +async function createDistReleaseConfig() { const platform = getPlatformDetails().platform; const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` : `${__dirname}/../src-tauri/tauri.conf.json`; @@ -21,4 +21,4 @@ async function createLocalReleaseConfig() { fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); } -await createLocalReleaseConfig(); +await createDistReleaseConfig(); diff --git a/src-build/createLocalReleaseConfig.js b/src-build/createSrcReleaseConfig.js similarity index 92% rename from src-build/createLocalReleaseConfig.js rename to src-build/createSrcReleaseConfig.js index 5257e80f..9f7b35d4 100644 --- a/src-build/createLocalReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -7,7 +7,7 @@ import {getPlatformDetails} from "./utils.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -async function createLocalReleaseConfig() { +async function createSrcReleaseConfig() { const platform = getPlatformDetails().platform; const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` : `${__dirname}/../src-tauri/tauri.conf.json`; @@ -21,4 +21,4 @@ async function createLocalReleaseConfig() { fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); } -await createLocalReleaseConfig(); +await createSrcReleaseConfig(); From 603245132750cd9c355c21d9f0d771e7e3810158 Mon Sep 17 00:00:00 2001 From: "charly@core.ai" Date: Fri, 21 Jul 2023 14:28:01 +0530 Subject: [PATCH 038/864] feat: support for mac signing from github workflow --- .github/workflows/tauri-build.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index ba21bc04..a4d6bdea 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -108,6 +108,12 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} with: releaseId: ${{ needs.create-release.outputs.release_id }} @@ -123,6 +129,12 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin From b9b323e46726044a856aa6332255e3cc2f02d0fe Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 21 Jul 2023 15:17:05 +0530 Subject: [PATCH 039/864] build: adding phcode release build generation step to GitHubaction --- .github/workflows/tauri-build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index a4d6bdea..5909dff1 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -58,7 +58,9 @@ jobs: sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf - name: install frontend dependencies - run: npm install # change this to npm or pnpm depending on which one you use + run: | + npm install + npm run _ci-release:dev - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' run: | From d446709d15a9435aa31806ee999420d976b749af Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 22 Jul 2023 13:25:50 +0530 Subject: [PATCH 040/864] fix: release build failure for windows --- src-build/clonePhoenix.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src-build/clonePhoenix.js b/src-build/clonePhoenix.js index 6d40ea0e..6f3abf5f 100644 --- a/src-build/clonePhoenix.js +++ b/src-build/clonePhoenix.js @@ -4,15 +4,13 @@ import path from 'path' console.log("Cloning phoenix..."); async function pwd() { - let output = await $`pwd`; - const pwd = output.stdout.toString(); - console.log("pwd ", pwd); + const pwd = process.cwd(); + console.log("current dir: ", pwd); return pwd; } const projectDir = await pwd(); const phoenixProjectPath = path.join(projectDir, "phoenix"); -console.log("current dir: ", projectDir); let packageJSONPath = path.join(projectDir, 'package.json'); console.log('loading package.json: ', packageJSONPath); From 6d73d2f4af8309bc9b286729fad846cef86b1d74 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 22 Jul 2023 22:07:19 +0530 Subject: [PATCH 041/864] build: auto merge pohoenix chnages on push to tauri branch in phoenix repo --- .github/workflows/update-phcode-build.yml | 56 +++++++++++++++++ package.json | 1 + src-build/update-phcode-build.js | 74 +++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 .github/workflows/update-phcode-build.yml create mode 100644 src-build/update-phcode-build.js diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml new file mode 100644 index 00000000..55742794 --- /dev/null +++ b/.github/workflows/update-phcode-build.yml @@ -0,0 +1,56 @@ +name: Update phcode to latest from tauri branch in phcode repo +# Aim: Update 'tauri' branch from phcode repo +# Process: +# 1. The 'tauri' repository, branch, and commit information are stored in the 'package.json' file in this repository. +# 2. This action creates a pull request to update its commit ID and versions of phcode to ensure build consistency. + +on: + repository_dispatch: + types: [update-phcode-build] + +jobs: + build-tasks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Event triggered by + run: | + echo source: ${{github.event.client_payload.source}}, workflow: ${{github.event.client_payload.workflow}}, action_run_id: ${{github.event.client_payload.run_id}}, action_run_number: ${{github.event.client_payload.run_number}}, sha: ${{ github.event.client_payload.sha }}, github_ref: ${{ github.event.client_payload.ref }} + + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: lts/* + + - name: Update phcode and version + run: | + npm install + npm run update-phcode-build + git status + phoenix_version=`node -p "require('./package.json').version"` + echo "PHOENIX_VERSION=${phoenix_version}" >> $GITHUB_ENV + shell: bash + + - name: Create phcode patch update Pull Request + id: cpr + uses: peter-evans/create-pull-request@v4 + with: + commit-message: 'ci: update phcode version to ${{ env.PHOENIX_VERSION }}' + committer: GitHub + author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com> + title: '[Release BOT] update phcode version to ${{ env.PHOENIX_VERSION }}' + add-paths: | + package.json + src-tauri/cargo.toml + src-tauri/tauri.conf.json + body: | + A new version of phcode has been pushed to `${{github.event.client_payload.source}}` repo's `tauri` branch. + This pull request updates the dependency to bring in the latest changes to phcode. + - version being mereged is ${{ env.PHOENIX_VERSION }} + - Auto-generated by `update-phcode-build.yml` action + - commit hash being merged in is [${{ github.event.client_payload.ref }}](https://github.com/phcode-dev/phoenix/tree/${{ github.event.client_payload.ref }}) + - name: Check outputs + if: ${{ steps.cpr.outputs.pull-request-number }} + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" \ No newline at end of file diff --git a/package.json b/package.json index c6742e62..05fbcf8e 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig", "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig", "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig", + "_ci_update-phcode-build": "node src-build/update-phcode-build.js", "serve": "npm run _servePhoenix && tauri dev", "postinstall": "node ./src-build/downloadNode.js", "cleanNode": "node src-build/cleanNode.js", diff --git a/src-build/update-phcode-build.js b/src-build/update-phcode-build.js new file mode 100644 index 00000000..0ccd23d2 --- /dev/null +++ b/src-build/update-phcode-build.js @@ -0,0 +1,74 @@ +import {$} from 'execa'; // https://www.npmjs.com/package/execa +import fs from 'fs'; +import path, {join, dirname} from 'path' +import {fileURLToPath} from "url"; +import {EOL} from "os"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// print process.argv +console.log("Updating phoenix to latest, Received the following arguments: ") +process.argv.forEach(function (val, index, array) { + console.log(index + ': ' + val); +}); + +const commitHash = process.argv[2]; +console.log("Commit hash to update to is: ", commitHash); + +async function pwd() { + const pwd = process.cwd(); + console.log("current dir: ", pwd); + return pwd; +} + +const projectDir = join(__dirname, '..'); +const phoenixProjectPath = path.join(projectDir, "phoenix"); + +let packageJSONPath = path.join(projectDir, 'package.json'); +console.log('loading package.json: ', packageJSONPath); +let packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf-8')); + + +const phoenixRepo = packageJSON.phoenixRepo; +console.log(`Cloning`, phoenixRepo); +if(!fs.existsSync(phoenixProjectPath)){ + await $`git clone ${phoenixRepo.gitClonrUrl} --branch ${phoenixRepo.branch}`; +} +process.chdir('phoenix'); +await pwd(); +console.log('checking out commit: ', commitHash); +await $`git checkout ${commitHash}`; +process.chdir('..'); +await pwd(); + +// update file package.json +const phoenixVersion = JSON.parse(fs.readFileSync("phoenix/package.json")).apiVersion.trim(); +console.log("phoenix version and commit detected to update is: ", phoenixVersion, commitHash); +packageJSON.version = phoenixVersion; +packageJSON.phoenixRepo.commit = commitHash; +console.log("Writing updated phoenix-desktop package.json", packageJSONPath); +fs.writeFileSync(packageJSONPath, JSON.stringify(packageJSON, null, 4)); + + +// update file src-tauri/tauri.conf.json +const tauriConfigPath = join(__dirname, '..', 'src-tauri', 'tauri.conf.json'); +console.log("Reading tauri config file: ", tauriConfigPath); +let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); +configJson.package.version = phoenixVersion || configJson.package.version; +console.log("Writing updated tauri config file tauri.conf.json", tauriConfigPath); +fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); + + +// update file src-tauri/cargo.toml +const tauriTOMLPath = join(__dirname, '..', 'src-tauri', 'Cargo.toml'); +console.log("write version in cargo.toml", tauriTOMLPath); +const toml = fs.readFileSync(tauriTOMLPath).toString(); +const lines = toml.split(/\r?\n/); +for(let i=0;i Date: Sat, 22 Jul 2023 22:10:23 +0530 Subject: [PATCH 042/864] fix: build script typo --- .github/workflows/update-phcode-build.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 55742794..3c931176 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -25,7 +25,7 @@ jobs: - name: Update phcode and version run: | npm install - npm run update-phcode-build + npm run _ci-update-phcode-build git status phoenix_version=`node -p "require('./package.json').version"` echo "PHOENIX_VERSION=${phoenix_version}" >> $GITHUB_ENV diff --git a/package.json b/package.json index 05fbcf8e..b791c8fe 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig", "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig", "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig", - "_ci_update-phcode-build": "node src-build/update-phcode-build.js", + "_ci-update-phcode-build": "node src-build/update-phcode-build.js", "serve": "npm run _servePhoenix && tauri dev", "postinstall": "node ./src-build/downloadNode.js", "cleanNode": "node src-build/cleanNode.js", From f0768374ff0692f55950a14ad3d35f0000f03f67 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 22 Jul 2023 22:11:34 +0530 Subject: [PATCH 043/864] fix: build script missing commit id pass --- .github/workflows/update-phcode-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 3c931176..b464b265 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -25,7 +25,7 @@ jobs: - name: Update phcode and version run: | npm install - npm run _ci-update-phcode-build + npm run _ci-update-phcode-build ${{ github.event.client_payload.ref }} git status phoenix_version=`node -p "require('./package.json').version"` echo "PHOENIX_VERSION=${phoenix_version}" >> $GITHUB_ENV From 9b929b7a7f00d4adebf856159ee162ecdf5f15c8 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 22 Jul 2023 22:48:41 +0530 Subject: [PATCH 044/864] fix: typo Cargo.toml --- .github/workflows/update-phcode-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index b464b265..43ea595a 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -41,7 +41,7 @@ jobs: title: '[Release BOT] update phcode version to ${{ env.PHOENIX_VERSION }}' add-paths: | package.json - src-tauri/cargo.toml + src-tauri/Cargo.toml src-tauri/tauri.conf.json body: | A new version of phcode has been pushed to `${{github.event.client_payload.source}}` repo's `tauri` branch. From ed2fe4ed4a8a6ec27d3c76cbca9ccb64e62428ae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 22 Jul 2023 16:42:39 +0000 Subject: [PATCH 045/864] chore(deps): update peter-evans/create-pull-request action to v5 --- .github/workflows/update-phcode-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 43ea595a..de3aa3ec 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -33,7 +33,7 @@ jobs: - name: Create phcode patch update Pull Request id: cpr - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v5 with: commit-message: 'ci: update phcode version to ${{ env.PHOENIX_VERSION }}' committer: GitHub From a455abb8366c4a2fb62640665745ac7f35fae3c0 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 22 Jul 2023 23:01:39 +0530 Subject: [PATCH 046/864] fix: wrong github commit hash variable in update phcode action --- .github/workflows/update-phcode-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index de3aa3ec..a21e39e9 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -25,7 +25,7 @@ jobs: - name: Update phcode and version run: | npm install - npm run _ci-update-phcode-build ${{ github.event.client_payload.ref }} + npm run _ci-update-phcode-build ${{ github.event.client_payload.sha }} git status phoenix_version=`node -p "require('./package.json').version"` echo "PHOENIX_VERSION=${phoenix_version}" >> $GITHUB_ENV @@ -48,7 +48,7 @@ jobs: This pull request updates the dependency to bring in the latest changes to phcode. - version being mereged is ${{ env.PHOENIX_VERSION }} - Auto-generated by `update-phcode-build.yml` action - - commit hash being merged in is [${{ github.event.client_payload.ref }}](https://github.com/phcode-dev/phoenix/tree/${{ github.event.client_payload.ref }}) + - commit hash being merged in is [${{ github.event.client_payload.sha }}](https://github.com/phcode-dev/phoenix/tree/${{ github.event.client_payload.sha }}) - name: Check outputs if: ${{ steps.cpr.outputs.pull-request-number }} run: | From 0c3a9fa499a028d025b0b60c1ec3ea86368f0522 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 22 Jul 2023 17:34:45 +0000 Subject: [PATCH 047/864] ci: update phcode version to 3.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b791c8fe..ed2be746 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "2e5dceb684970780204485f3209b1707b19b634a" + "commit": "3ce6abe6b11f24d5a364ee9a5dd6b5fd04b73b9a" } } \ No newline at end of file From 466c655009ce9174a8017b3593376030b554327b Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 22 Jul 2023 23:13:47 +0530 Subject: [PATCH 048/864] docs: update release commands --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 96792e43..92dc3490 100644 --- a/README.md +++ b/README.md @@ -70,8 +70,8 @@ If you want to generate the release builds locally directly while you are editin ```bash cd phoenix-desktop # To generate debug builds: -npm run releaseLocalDebug -# OR to generate release builds, just run `npm run releaseLocal` +npm run releaseSrcDebug +# OR to generate release builds, just run `npm run releaseSrc` ``` This is the easiest way to quickly debug issues directly from the phoenix source folder. @@ -88,8 +88,8 @@ npm run release:prod # Now generate the tauri debug builds: cd ../phoenix-desktop -npm run releaseLocalDistDebug -# OR to generate release builds, just run `npm run releaseLocalDist` +npm run releaseDistDebug +# OR to generate release builds, just run `npm run releaseDist` ``` ## Building release binaries and installers in GitHub actions From 3956fb8acc0546115e5b80addcd406c694571ce4 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 25 Jul 2023 15:21:11 +0530 Subject: [PATCH 049/864] feat: enable nsis for windows --- .github/workflows/tauri-build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build.yml index 5909dff1..0ffab302 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build.yml @@ -118,6 +118,7 @@ jobs: APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} with: releaseId: ${{ needs.create-release.outputs.release_id }} + updaterJsonPreferNsis: true - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' From da4d63f850d350685a583cd78fb03d32e0f892be Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 26 Jul 2023 14:56:28 +0530 Subject: [PATCH 050/864] feat: product name is Phoenix Code --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8a3a3394..cbfc79b4 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ "withGlobalTauri": true }, "package": { - "productName": "PhCode", + "productName": "Phoenix Code", "version": "3.2.2" }, "tauri": { From 73e011481070de833d389d6f7c6e675bd2ed083c Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 26 Jul 2023 22:15:52 +0530 Subject: [PATCH 051/864] build: change name as per stage, phoenix code experimental build, pre-release etc. --- .gitignore | 1 - src-build/ci-createDistReleaseConfig.js | 51 +++++++++++++++++++------ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index 95e305e1..1def9783 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ node-bins src-build/node-* src-tauri/node-* src-tauri/tauri-local.conf.json -src-tauri/tauri-dist.conf.json phoenix node_modules diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index ecae211b..96f3bfb9 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -6,7 +6,39 @@ import fs from 'fs'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -async function patchVersionNumbers() { +let productNameSuffixForStage = { + // the environment field in phoenix repo: config.json, brackets.config.dist.json and brackets.config.staging.json + // forms the keys and the product name suffix corresponding to each stage. + dev : "Experimental Build", + stage: "Pre-release" + //production: "" has no suffix +}; + +// if the name is already of the form `Phoenix code Pre-release`, just return `Phoenix Code` +function _removeSuffixesFromName(name) { + name = name.trim(); + const knownSuffixes = Object.values(productNameSuffixForStage) + for(let suffix of knownSuffixes){ + if(name.endsWith(suffix)){ + name = name.substring(0, name.length - suffix.length) + } + } + return name.trim(); +} + +function _getProductName(name, stage) { + name = _removeSuffixesFromName(name); + if(stage === 'production') { + return name; // Phoenix Code + } + if(!productNameSuffixForStage[stage]) { + throw new Error(`Cannot build Phoenix for unknown environment ${stage}`); + } + // return `Phoenix code Pre-release` or `Phoenix code Experimental Build` + return `${name} ${productNameSuffixForStage[stage]}`; +} + +async function ciCreateDistReleaseConfig() { const phoenixConfigPath = join(__dirname, '..', 'phoenix', 'dist', 'config.json'); const packageJSONPath = join(__dirname, '..', 'package.json'); const tauriTOMLPath = join(__dirname, '..', 'src-tauri', 'Cargo.toml'); @@ -36,20 +68,15 @@ async function patchVersionNumbers() { console.log("write version in tauri.conf.json", tauriConfigPath); configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - configJson.package.version = phoenixVersion; - fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); - return phoenixVersion; -} - -async function ciCreateDistReleaseConfig() { - const tauriConfigPath = join(__dirname, '..', 'src-tauri', 'tauri.conf.json'); - console.log("Reading config file: ", tauriConfigPath); - let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - configJson.package.version = await patchVersionNumbers() || "3.0.0"; - // delete configJson.tauri.updater; // #uncomment_line_for_local_build_1 configJson.build.distDir = '../phoenix/dist/' + // delete configJson.tauri.updater; // #uncomment_line_for_local_build_1 + configJson.package.version = phoenixVersion; + configJson.package.productName = _getProductName(configJson.package.productName, phoenixStage); + console.log("Product name is: ", configJson.package.productName); + configJson.tauri.windows[0].title = configJson.package.productName; console.log("Writing new dist config json ", tauriConfigPath); fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); + return phoenixVersion; } await ciCreateDistReleaseConfig(); From 26013322883ff4600257e78aa409d1b8e8045ca6 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 27 Jul 2023 18:50:29 +0530 Subject: [PATCH 052/864] build: generate appropriate releases on push to dev, staging and prod branch --- .github/workflows/tauri-build-dev.yml | 168 ++++++++++++++++++ .../{tauri-build.yml => tauri-build-prod.yml} | 8 +- .github/workflows/tauri-build-staging.yml | 168 ++++++++++++++++++ 3 files changed, 341 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/tauri-build-dev.yml rename .github/workflows/{tauri-build.yml => tauri-build-prod.yml} (98%) create mode 100644 .github/workflows/tauri-build-staging.yml diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml new file mode 100644 index 00000000..ca4368b8 --- /dev/null +++ b/.github/workflows/tauri-build-dev.yml @@ -0,0 +1,168 @@ +name: 'generate experimental/dev stage draft GitHub release' + +on: + push: + branches: [ dev ] + +jobs: + create-release: + permissions: + contents: write + runs-on: ubuntu-20.04 + outputs: + release_id: ${{ steps.create-release.outputs.result }} + + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: get version + run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + - name: create release + id: create-release + uses: actions/github-script@v6 + with: + script: | + const { data } = await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: `app-v${process.env.PACKAGE_VERSION}`, + name: `Desktop App v${process.env.PACKAGE_VERSION}`, + body: 'Take a look at the assets to download and install this app.', + draft: true, + prerelease: false + }) + return data.id + + build-tauri: + needs: create-release + permissions: + contents: write + strategy: + fail-fast: false + matrix: + platform: [ macos-latest, ubuntu-20.04, windows-latest ] + + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + - name: install dependencies (ubuntu only) + if: matrix.platform == 'ubuntu-20.04' + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + - name: install frontend dependencies + run: | + npm install + npm run _ci-release:dev + - name: install AzureSignTool (windows only) + if: matrix.platform == 'windows-latest' + run: | + dotnet tool install --global AzureSignTool + - name: import certificate for signing (windows only) + if: matrix.platform == 'windows-latest' + run: | + echo "${{ secrets.AZURE_EV_CERT }}" > secret.cer + Import-Certificate -FilePath .\secret.cer -CertStoreLocation Cert:\LocalMachine\My + shell: powershell + - name: patch signTool (windows only) + if: matrix.platform == 'windows-latest' + run: Start-Process -FilePath .\src-build\win\copy_sign_tool.exe -Verb RunAs + shell: powershell + - name: setup env for signing (windows only) + if: matrix.platform == 'windows-latest' + env: + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }} + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} + AZURE_CERT_NAME: ${{ secrets.AZURE_CERT_NAME }} + AZURE_COMPANY_NAME: ${{ secrets.AZURE_COMPANY_NAME }} + run: | + $jsonContent = @{ + "AZURE_KEY_VAULT_URI" = $env:AZURE_KEY_VAULT_URI + "AZURE_CLIENT_ID" = $env:AZURE_CLIENT_ID + "AZURE_TENANT_ID" = $env:AZURE_TENANT_ID + "AZURE_CLIENT_SECRET" = $env:AZURE_CLIENT_SECRET + "AZURE_CERT_NAME" = $env:AZURE_CERT_NAME + "AZURE_COMPANY_NAME" = $env:AZURE_COMPANY_NAME + } + $jsonContent | ConvertTo-Json | Out-File -FilePath ./secrets.json -Encoding utf8 + # Load content from the file + $content = Get-Content -Path "./secrets.json" -Raw + + # Replace \r\n with \n + $content = $content -replace "`r`n", "`n" + + # Write the content back to the file + Set-Content -Path "./secrets.json" -Value $content + shell: powershell + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + with: + releaseId: ${{ needs.create-release.outputs.release_id }} + updaterJsonPreferNsis: true + + - name: setup env for mac arm (Mac only) + if: matrix.platform == 'macos-latest' + run: | + rustup target add aarch64-apple-darwin + npm run installNodeArmDarwin + - name: build for mac arm (Mac only) + if: matrix.platform == 'macos-latest' + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + with: + releaseId: ${{ needs.create-release.outputs.release_id }} + args: --target aarch64-apple-darwin + + + publish-release: + permissions: + contents: write + runs-on: ubuntu-20.04 + needs: [ create-release, build-tauri ] + + steps: + - name: publish release + id: publish-release + uses: actions/github-script@v6 + env: + release_id: ${{ needs.create-release.outputs.release_id }} + with: + script: | + github.rest.repos.updateRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: process.env.release_id, + draft: true, + prerelease: true + }) diff --git a/.github/workflows/tauri-build.yml b/.github/workflows/tauri-build-prod.yml similarity index 98% rename from .github/workflows/tauri-build.yml rename to .github/workflows/tauri-build-prod.yml index 0ffab302..7abf7ca7 100644 --- a/.github/workflows/tauri-build.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -1,6 +1,8 @@ -name: 'publish' +name: 'generate production draft GitHub release' -on: pull_request +on: + push: + branches: [ prod ] jobs: create-release: @@ -60,7 +62,7 @@ jobs: - name: install frontend dependencies run: | npm install - npm run _ci-release:dev + npm run _ci-release:prod - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' run: | diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml new file mode 100644 index 00000000..8c085b8e --- /dev/null +++ b/.github/workflows/tauri-build-staging.yml @@ -0,0 +1,168 @@ +name: 'generate pre-release/staging draft GitHub release' + +on: + push: + branches: [ staging ] + +jobs: + create-release: + permissions: + contents: write + runs-on: ubuntu-20.04 + outputs: + release_id: ${{ steps.create-release.outputs.result }} + + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: get version + run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + - name: create release + id: create-release + uses: actions/github-script@v6 + with: + script: | + const { data } = await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + tag_name: `app-v${process.env.PACKAGE_VERSION}`, + name: `Desktop App v${process.env.PACKAGE_VERSION}`, + body: 'Take a look at the assets to download and install this app.', + draft: true, + prerelease: false + }) + return data.id + + build-tauri: + needs: create-release + permissions: + contents: write + strategy: + fail-fast: false + matrix: + platform: [ macos-latest, ubuntu-20.04, windows-latest ] + + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: lts/* + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + - name: install dependencies (ubuntu only) + if: matrix.platform == 'ubuntu-20.04' + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + - name: install frontend dependencies + run: | + npm install + npm run _ci-release:staging + - name: install AzureSignTool (windows only) + if: matrix.platform == 'windows-latest' + run: | + dotnet tool install --global AzureSignTool + - name: import certificate for signing (windows only) + if: matrix.platform == 'windows-latest' + run: | + echo "${{ secrets.AZURE_EV_CERT }}" > secret.cer + Import-Certificate -FilePath .\secret.cer -CertStoreLocation Cert:\LocalMachine\My + shell: powershell + - name: patch signTool (windows only) + if: matrix.platform == 'windows-latest' + run: Start-Process -FilePath .\src-build\win\copy_sign_tool.exe -Verb RunAs + shell: powershell + - name: setup env for signing (windows only) + if: matrix.platform == 'windows-latest' + env: + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }} + AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} + AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} + AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} + AZURE_CERT_NAME: ${{ secrets.AZURE_CERT_NAME }} + AZURE_COMPANY_NAME: ${{ secrets.AZURE_COMPANY_NAME }} + run: | + $jsonContent = @{ + "AZURE_KEY_VAULT_URI" = $env:AZURE_KEY_VAULT_URI + "AZURE_CLIENT_ID" = $env:AZURE_CLIENT_ID + "AZURE_TENANT_ID" = $env:AZURE_TENANT_ID + "AZURE_CLIENT_SECRET" = $env:AZURE_CLIENT_SECRET + "AZURE_CERT_NAME" = $env:AZURE_CERT_NAME + "AZURE_COMPANY_NAME" = $env:AZURE_COMPANY_NAME + } + $jsonContent | ConvertTo-Json | Out-File -FilePath ./secrets.json -Encoding utf8 + # Load content from the file + $content = Get-Content -Path "./secrets.json" -Raw + + # Replace \r\n with \n + $content = $content -replace "`r`n", "`n" + + # Write the content back to the file + Set-Content -Path "./secrets.json" -Value $content + shell: powershell + - uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + with: + releaseId: ${{ needs.create-release.outputs.release_id }} + updaterJsonPreferNsis: true + + - name: setup env for mac arm (Mac only) + if: matrix.platform == 'macos-latest' + run: | + rustup target add aarch64-apple-darwin + npm run installNodeArmDarwin + - name: build for mac arm (Mac only) + if: matrix.platform == 'macos-latest' + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + with: + releaseId: ${{ needs.create-release.outputs.release_id }} + args: --target aarch64-apple-darwin + + + publish-release: + permissions: + contents: write + runs-on: ubuntu-20.04 + needs: [ create-release, build-tauri ] + + steps: + - name: publish release + id: publish-release + uses: actions/github-script@v6 + env: + release_id: ${{ needs.create-release.outputs.release_id }} + with: + script: | + github.rest.repos.updateRelease({ + owner: context.repo.owner, + repo: context.repo.repo, + release_id: process.env.release_id, + draft: true, + prerelease: true + }) From a992c673869e286fe289b5ef280d6028756c56a9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 27 Jul 2023 03:17:42 +0000 Subject: [PATCH 053/864] chore(deps): update dependency execa to v7.2.0 --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index cdface35..13bcd787 100644 --- a/package-lock.json +++ b/package-lock.json @@ -237,9 +237,9 @@ } }, "node_modules/execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", @@ -669,9 +669,9 @@ } }, "execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", "dev": true, "requires": { "cross-spawn": "^7.0.3", From 86acd1f0a5116535351f2eadf4ba194a41803a66 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 10:52:17 +0530 Subject: [PATCH 054/864] build: update GitHub release text update --- .github/workflows/tauri-build-dev.yml | 4 ++-- .github/workflows/tauri-build-prod.yml | 4 ++-- .github/workflows/tauri-build-staging.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index ca4368b8..2eb03b1b 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -29,8 +29,8 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, tag_name: `app-v${process.env.PACKAGE_VERSION}`, - name: `Desktop App v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install this app.', + name: `Phoenix Code Experimental build v${process.env.PACKAGE_VERSION}`, + body: 'Take a look at the assets to download and install Phoenix Code For your platform.', draft: true, prerelease: false }) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 7abf7ca7..f437cc18 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -29,8 +29,8 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, tag_name: `app-v${process.env.PACKAGE_VERSION}`, - name: `Desktop App v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install this app.', + name: `Phoenix Code Stable Release v${process.env.PACKAGE_VERSION}`, + body: 'Take a look at the assets to download and install Phoenix Code For your platform.', draft: true, prerelease: false }) diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 8c085b8e..556cabad 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -29,8 +29,8 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, tag_name: `app-v${process.env.PACKAGE_VERSION}`, - name: `Desktop App v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install this app.', + name: `Phoenix Code Pre-release v${process.env.PACKAGE_VERSION}`, + body: 'Take a look at the assets to download and install Phoenix Code For your platform.', draft: true, prerelease: false }) From 35a6b6e0d07917e2c35eec33c0dcf9356cc89905 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 14:44:11 +0530 Subject: [PATCH 055/864] build: release update latest.json auto create --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- .github/workflows/updateNotification.js | 89 ++++++++++++++++++++++- src-build/ci-createDistReleaseConfig.js | 17 ++--- src-build/constants.js | 18 +++++ 6 files changed, 114 insertions(+), 16 deletions(-) create mode 100644 src-build/constants.js diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 2eb03b1b..d8d701f1 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -30,7 +30,7 @@ jobs: repo: context.repo.repo, tag_name: `app-v${process.env.PACKAGE_VERSION}`, name: `Phoenix Code Experimental build v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install Phoenix Code For your platform.', + body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', draft: true, prerelease: false }) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index f437cc18..2ff7ab7a 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -30,7 +30,7 @@ jobs: repo: context.repo.repo, tag_name: `app-v${process.env.PACKAGE_VERSION}`, name: `Phoenix Code Stable Release v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install Phoenix Code For your platform.', + body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', draft: true, prerelease: false }) diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 556cabad..15800f50 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -30,7 +30,7 @@ jobs: repo: context.repo.repo, tag_name: `app-v${process.env.PACKAGE_VERSION}`, name: `Phoenix Code Pre-release v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install Phoenix Code For your platform.', + body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', draft: true, prerelease: false }) diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js index 9a0858da..de073da0 100644 --- a/.github/workflows/updateNotification.js +++ b/.github/workflows/updateNotification.js @@ -1,4 +1,84 @@ import fs from 'fs'; +import { + LATEST_JSON_GITHUB_RELEASE, + PRODUCT_NAME_SUFFIX_FOR_STAGE, + UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH +} from "../../src-build/constants.js"; +import {get} from "https"; + +export function _getTextHTTPS(url) { + return new Promise((resolve, reject)=>{ + get(url, (resp) => { + let data = ''; + if(resp.statusCode === 302){ + // http redirect, follow links + _getTextHTTPS(resp.headers.location) + .then(resolve) + .catch(reject); + return; + } + // A chunk of data has been received. + resp.on('data', (chunk) => { + data += chunk; + }); + + // The whole response has been received. + resp.on('end', () => { + resolve(data); + }); + + }).on("error", (err) => { + reject(err); + }); + }); +} + +function _makePrefix(name) { + return name.trim().split(" ").join("."); +} + +// these are the prefix for names of assets in the release created by tauri GitHub action. +// Eg. Phoenix.Code.Experimental.Build_3.2.2_aarch64.dmg, Phoenix.Code.Pre-release_3.2.2_x64-setup.exe, etc.. +// note that not all platform bin names follow these convention, so we just check if any of the assets follow the pattern +const DEV_STAGE_PRODUCT_NAME_PREFIX = "Phoenix.Code." + _makePrefix(PRODUCT_NAME_SUFFIX_FOR_STAGE.dev); +const PRE_RELEASE_STAGE_PRODUCT_NAME_PREFIX = "Phoenix.Code." + _makePrefix(PRODUCT_NAME_SUFFIX_FOR_STAGE.stage); +//"": "production" has no suffix + +// identify if the release is staging/pre-release/prod, then based on that get the pathname of the update json file +function _identifyUpdateJSONPath(releaseAssets) { + for(let releaseAsset of releaseAssets) { + if(releaseAsset.name.startsWith(DEV_STAGE_PRODUCT_NAME_PREFIX)){ + return UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH.dev; + } + else if(releaseAsset.name.startsWith(PRE_RELEASE_STAGE_PRODUCT_NAME_PREFIX)){ + return UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH.stage; + } + } + return UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH.production; +} + +async function _getLatestJson(releaseAssets) { + for(let releaseAsset of releaseAssets) { + if(releaseAsset.name === LATEST_JSON_GITHUB_RELEASE){ + // "browser_download_url": "https://github.com/phoenix/phoenix-desktop/releases/download/34/latest.json" + const downloadURL = releaseAsset.browser_download_url; + console.log("Latest json download URL is: ", downloadURL); + const latestJSON = await _getTextHTTPS(downloadURL); + console.log("Latest json file contents: ", latestJSON); + return latestJSON; + } + } + throw new Error(`Could not locate ${LATEST_JSON_GITHUB_RELEASE} file in github releases.`); +} + +function _extractSmallReleaseNotes(releaseNotes, releaseTitle) { + for(let line of releaseNotes.split("\n")){ + if(line.startsWith(">UpdateNotification: ")){ + return line.replace(">UpdateNotification: ", ""); + } + } + return releaseTitle; +} export default async function printStuff({github, context, githubWorkspaceRoot}) { console.log(github, context, "yo"); @@ -12,6 +92,8 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) console.log("Release isPreRelease: ", isPreRelease); const releaseNotes = context.payload.release.body; console.log("Release Notes: ", releaseNotes); + const releaseTitle = context.payload.release.name; + console.log("Release Title: ", releaseTitle); const releaseID = context.payload.release.id; const releaseAssets = (await github.rest.repos.listReleaseAssets({ owner, @@ -24,5 +106,10 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) // See https://octokit.github.io/rest.js/v19#repos-get-release-by-tag for more availableapis // write to the docs folder here. all changes made here to the docs folder will be part of the pull request - fs.writeFileSync(`${githubWorkspaceRoot}/docs/tauri/release.json`, JSON.stringify(releaseAssets, null, 2)); + console.log("Updating tauri update JSON file: ", _identifyUpdateJSONPath(releaseAssets)); + const latestJSON = JSON.parse(await _getLatestJson(releaseAssets)); + latestJSON.notes = _extractSmallReleaseNotes(releaseNotes, releaseTitle); + const latestJsonPath = `${githubWorkspaceRoot}/${_identifyUpdateJSONPath(releaseAssets)}`; + console.log("writing latest json to path: ", latestJsonPath, " contents: ", latestJSON) + fs.writeFileSync(latestJsonPath, JSON.stringify(latestJSON, null, 4)); } \ No newline at end of file diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index 96f3bfb9..c7457d36 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -1,25 +1,18 @@ import {fileURLToPath} from "url"; import {dirname, join} from "path"; +import {PRODUCT_NAME_SUFFIX_FOR_STAGE} from "./constants.js"; import { EOL } from "os"; import fs from 'fs'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -let productNameSuffixForStage = { - // the environment field in phoenix repo: config.json, brackets.config.dist.json and brackets.config.staging.json - // forms the keys and the product name suffix corresponding to each stage. - dev : "Experimental Build", - stage: "Pre-release" - //production: "" has no suffix -}; - // if the name is already of the form `Phoenix code Pre-release`, just return `Phoenix Code` function _removeSuffixesFromName(name) { name = name.trim(); - const knownSuffixes = Object.values(productNameSuffixForStage) + const knownSuffixes = Object.values(PRODUCT_NAME_SUFFIX_FOR_STAGE) for(let suffix of knownSuffixes){ - if(name.endsWith(suffix)){ + if(suffix && name.endsWith(suffix)){ name = name.substring(0, name.length - suffix.length) } } @@ -31,11 +24,11 @@ function _getProductName(name, stage) { if(stage === 'production') { return name; // Phoenix Code } - if(!productNameSuffixForStage[stage]) { + if(!PRODUCT_NAME_SUFFIX_FOR_STAGE[stage]) { throw new Error(`Cannot build Phoenix for unknown environment ${stage}`); } // return `Phoenix code Pre-release` or `Phoenix code Experimental Build` - return `${name} ${productNameSuffixForStage[stage]}`; + return `${name} ${PRODUCT_NAME_SUFFIX_FOR_STAGE[stage]}`; } async function ciCreateDistReleaseConfig() { diff --git a/src-build/constants.js b/src-build/constants.js new file mode 100644 index 00000000..2f9f6515 --- /dev/null +++ b/src-build/constants.js @@ -0,0 +1,18 @@ +export const PRODUCT_NAME_SUFFIX_FOR_STAGE = { + // keys are the `environment` field of files in phoenix repo: config.json, brackets.config.dist.json + // and brackets.config.staging.json. The product name suffix corresponding to each stage are values. + dev : "Experimental Build", + stage: "Pre-release", + production: "" // has no suffix +}; + +export const UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH = { + // do not change any of these names unless you want to nuke the updater for all the whole installation base!! + // or you know what you are doing. + dev: "docs/tauri/update-latest-experimental-build.json", + stage: "docs/tauri/update-latest-pre-release.json", + production: "docs/tauri/update-latest-stable-prod.json" +}; + +// latest.json file that is generated as part of tauri build in every GitHub release. it is generated by tauri build action. +export const LATEST_JSON_GITHUB_RELEASE = "latest.json"; \ No newline at end of file From 09133fbd506888c1cf821400f26cf554adb9d912 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 15:20:09 +0530 Subject: [PATCH 056/864] build: release tags to lock update notifications --- .github/workflows/tauri-build-dev.yml | 3 ++- .github/workflows/tauri-build-prod.yml | 2 ++ .github/workflows/tauri-build-staging.yml | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index d8d701f1..8c632391 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -121,6 +121,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true + tagName: app-v__VERSION__ - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' @@ -143,7 +144,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin - + tagName: app-v__VERSION__ publish-release: permissions: diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 2ff7ab7a..dd8fec13 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -121,6 +121,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true + tagName: app-v__VERSION__ - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' @@ -143,6 +144,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin + tagName: app-v__VERSION__ publish-release: diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 15800f50..1873f78a 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -121,6 +121,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true + tagName: app-v__VERSION__ - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' @@ -143,6 +144,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin + tagName: app-v__VERSION__ publish-release: From 3029588e85e991496a2bb95ece7b5ce31d79c63f Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 15:54:57 +0530 Subject: [PATCH 057/864] ci: git tag proper settings --- .github/workflows/tauri-build-dev.yml | 13 +++++++++---- .github/workflows/tauri-build-prod.yml | 13 +++++++++---- .github/workflows/tauri-build-staging.yml | 13 +++++++++---- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 8c632391..1bc9635a 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -19,7 +19,9 @@ jobs: with: node-version: lts/* - name: get version - run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + run: | + echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: create release id: create-release uses: actions/github-script@v6 @@ -28,7 +30,8 @@ jobs: const { data } = await github.rest.repos.createRelease({ owner: context.repo.owner, repo: context.repo.repo, - tag_name: `app-v${process.env.PACKAGE_VERSION}`, + tag_name: `${process.env.GIT_TAG_NAME}`, + target_commitish: 'dev', name: `Phoenix Code Experimental build v${process.env.PACKAGE_VERSION}`, body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', draft: true, @@ -121,7 +124,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true - tagName: app-v__VERSION__ + tagName: ${{ env.GIT_TAG_NAME }} - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' @@ -144,7 +147,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin - tagName: app-v__VERSION__ + tagName: ${{ env.GIT_TAG_NAME }} publish-release: permissions: @@ -163,6 +166,8 @@ jobs: github.rest.repos.updateRelease({ owner: context.repo.owner, repo: context.repo.repo, + tag_name: `${process.env.GIT_TAG_NAME}`, + target_commitish: 'dev', release_id: process.env.release_id, draft: true, prerelease: true diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index dd8fec13..21989b63 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -19,7 +19,9 @@ jobs: with: node-version: lts/* - name: get version - run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + run: | + echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: create release id: create-release uses: actions/github-script@v6 @@ -28,7 +30,8 @@ jobs: const { data } = await github.rest.repos.createRelease({ owner: context.repo.owner, repo: context.repo.repo, - tag_name: `app-v${process.env.PACKAGE_VERSION}`, + tag_name: `${process.env.GIT_TAG_NAME}`, + target_commitish: 'prod', name: `Phoenix Code Stable Release v${process.env.PACKAGE_VERSION}`, body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', draft: true, @@ -121,7 +124,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true - tagName: app-v__VERSION__ + tagName: ${{ env.GIT_TAG_NAME }} - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' @@ -144,7 +147,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin - tagName: app-v__VERSION__ + tagName: ${{ env.GIT_TAG_NAME }} publish-release: @@ -164,6 +167,8 @@ jobs: github.rest.repos.updateRelease({ owner: context.repo.owner, repo: context.repo.repo, + tag_name: `${process.env.GIT_TAG_NAME}`, + target_commitish: 'dev', release_id: process.env.release_id, draft: true, prerelease: false diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 1873f78a..7742d7ca 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -19,7 +19,9 @@ jobs: with: node-version: lts/* - name: get version - run: echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + run: | + echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV + echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: create release id: create-release uses: actions/github-script@v6 @@ -28,7 +30,8 @@ jobs: const { data } = await github.rest.repos.createRelease({ owner: context.repo.owner, repo: context.repo.repo, - tag_name: `app-v${process.env.PACKAGE_VERSION}`, + tag_name: `${process.env.GIT_TAG_NAME}`, + target_commitish: 'staging', name: `Phoenix Code Pre-release v${process.env.PACKAGE_VERSION}`, body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', draft: true, @@ -121,7 +124,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true - tagName: app-v__VERSION__ + tagName: ${{ env.GIT_TAG_NAME }} - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' @@ -144,7 +147,7 @@ jobs: with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin - tagName: app-v__VERSION__ + tagName: ${{ env.GIT_TAG_NAME }} publish-release: @@ -164,6 +167,8 @@ jobs: github.rest.repos.updateRelease({ owner: context.repo.owner, repo: context.repo.repo, + tag_name: `${process.env.GIT_TAG_NAME}`, + target_commitish: 'dev', release_id: process.env.release_id, draft: true, prerelease: true From a392906ef053205719e7109f2fc7928837ffb059 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 16:20:59 +0530 Subject: [PATCH 058/864] fix: git tag not working --- .github/workflows/tauri-build-dev.yml | 5 +++++ .github/workflows/tauri-build-prod.yml | 5 +++++ .github/workflows/tauri-build-staging.yml | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 1bc9635a..fdbf5ab7 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -51,6 +51,8 @@ jobs: runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v3 + - name: get Git Tag + run: echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node uses: actions/setup-node@v3 with: @@ -156,6 +158,9 @@ jobs: needs: [ create-release, build-tauri ] steps: + - uses: actions/checkout@v3 + - name: get Git Tag + run: echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: publish release id: publish-release uses: actions/github-script@v6 diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 21989b63..225fb9e1 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -51,6 +51,8 @@ jobs: runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v3 + - name: get Git Tag + run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node uses: actions/setup-node@v3 with: @@ -157,6 +159,9 @@ jobs: needs: [ create-release, build-tauri ] steps: + - uses: actions/checkout@v3 + - name: get Git Tag + run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: publish release id: publish-release uses: actions/github-script@v6 diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 7742d7ca..3305a828 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -51,6 +51,8 @@ jobs: runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v3 + - name: get Git Tag + run: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node uses: actions/setup-node@v3 with: @@ -157,6 +159,9 @@ jobs: needs: [ create-release, build-tauri ] steps: + - uses: actions/checkout@v3 + - name: get Git Tag + run: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: publish release id: publish-release uses: actions/github-script@v6 From fbb885aead192bfeb8da7b112386657e06965f11 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 17:18:44 +0530 Subject: [PATCH 059/864] fix: draft release to to at issue creation --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index fdbf5ab7..c4c4a58a 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -35,7 +35,7 @@ jobs: name: `Phoenix Code Experimental build v${process.env.PACKAGE_VERSION}`, body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', draft: true, - prerelease: false + prerelease: true }) return data.id From 0891f25e95234b67a7a559bb7701b2ba4dff32ab Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 17:18:52 +0530 Subject: [PATCH 060/864] fix: draft release to to at issue creation --- .github/workflows/tauri-build-staging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 3305a828..0c168763 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -35,7 +35,7 @@ jobs: name: `Phoenix Code Pre-release v${process.env.PACKAGE_VERSION}`, body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', draft: true, - prerelease: false + prerelease: true }) return data.id From 7adb5c7ed161e79cb319d46915b8f7111e1e016b Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 17:29:59 +0530 Subject: [PATCH 061/864] fix: use bash to fix git tag env variable set --- .github/workflows/tauri-build-dev.yml | 1 + .github/workflows/tauri-build-prod.yml | 1 + .github/workflows/tauri-build-staging.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index c4c4a58a..6b7975c8 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -52,6 +52,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: get Git Tag + shell: bash run: echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node uses: actions/setup-node@v3 diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 225fb9e1..c9080150 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -52,6 +52,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: get Git Tag + shell: bash run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node uses: actions/setup-node@v3 diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 0c168763..1db8ff3b 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -52,6 +52,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: get Git Tag + shell: bash run: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node uses: actions/setup-node@v3 From 5e13611e1d147501eb225ae5cc9e3dfba1f6a7d0 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 11:37:14 +0000 Subject: [PATCH 062/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 docs/tauri/update-latest-experimental-build.json diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json new file mode 100644 index 00000000..87424579 --- /dev/null +++ b/docs/tauri/update-latest-experimental-build.json @@ -0,0 +1,23 @@ +{ + "version": "3.2.2", + "notes": "", + "pub_date": "2023-07-28T11:20:09.293Z", + "platforms": { + "linux-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxUdk9NbUVVKzlkMlN4UExPQ3pBU0h5YWh4cXJibXFybmw3Wnp2aHJZc3BLdnZCbTNpQTUrRkFYZWlHNzJ4eUxEbU4zVmdmUlhxMkdycTdrcHNJamdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQyMzUyCWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjIuMl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKTUJCM1BHa3JHZHd6Mi9aeFBpVGw2c21MRCtBUDg5ei83NkM2L0dEclhwTFlkbWoxSkl2dDhBVFNFZ1lRVWEvUXlPdGNTMzU5M1BZTytVYklWcEFvQ0E9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/phoenix-code-experimental-build_3.2.2_amd64.AppImage.tar.gz" + }, + "windows-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhXUnFuN21URFdiUWswV3JrS0hLMUFhL3R3NG5uZXdOU0dmWjQzeDdmN1N5ZWNCcjQvRnBSYU50dFdpa3FHNk1xNTk0RTZTQlM2ZloxcitucStoUkFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQyMzgxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjIuMl94NjQtc2V0dXAubnNpcy56aXAKRnJoQU9WVGpON1k3cDhSLzN1VTJTQ2poU1ZOOU1XVmllaWRKREVsSUhNUzZUNDFxdFh0c2FHNWQ5azJMdHhaY0lWdE5YeCsxbWdWdFJVc0NTSm5kQ0E9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/latest/download/Phoenix.Code.Experimental.Build_3.2.2_x64-setup.nsis.zip" + }, + "darwin-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRrQzZxV2lwUWpFNDV5SVlrTjUyVjM2UDYxcFczNTVXMkR1c1NwdWFObmtsTEtZNHJLYWRLcmR5aitxYk9xbTNCdnF3QVNZNS91QkF4YmUvTjlXeHdvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQyNDA2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjNPQ0pzbFdCdWtwZXZ5MWVReHQ4d1B5VzBKQ3pIU0ZPZnljMUxEQ1puWFY2VDduNmVhV2M3Mm84TmFpbHpTUGRWVW5QRCsyYkVuejdiRTB2dENhTERnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + }, + "darwin-aarch64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxpRUNFVXcvSHhLakFjMng2Wmo3WXQ3OVVpcWRybk1velRvSlU5bkIya0x1QmJGZVF2dUxPck8vaXI1K1lzTU1SNVNKOHVvVVFqTUozbG03empkRkFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQzMjA0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjJuU1o5Wkt4aDNscDhRM2g5UFRrTnNtMjZZSS9VNmtIdS9MbDE2SVpkV2FaTnErZTMvS1dQenFvZXhoeHBvVU05RFFza0c5QVdTUXNTSnFBWHZtS0N3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + } + } +} \ No newline at end of file From e9a98819e0cc9c898acb32487e979ee5ad2a8b60 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 18:15:42 +0530 Subject: [PATCH 063/864] build: setting update url for stage release --- .github/workflows/updateNotification.js | 2 +- src-build/ci-createDistReleaseConfig.js | 10 +++++++++- src-build/constants.js | 8 +++++--- src-tauri/tauri.conf.json | 2 +- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js index de073da0..a2dc0952 100644 --- a/.github/workflows/updateNotification.js +++ b/.github/workflows/updateNotification.js @@ -109,7 +109,7 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) console.log("Updating tauri update JSON file: ", _identifyUpdateJSONPath(releaseAssets)); const latestJSON = JSON.parse(await _getLatestJson(releaseAssets)); latestJSON.notes = _extractSmallReleaseNotes(releaseNotes, releaseTitle); - const latestJsonPath = `${githubWorkspaceRoot}/${_identifyUpdateJSONPath(releaseAssets)}`; + const latestJsonPath = `${githubWorkspaceRoot}/docs/${_identifyUpdateJSONPath(releaseAssets)}`; console.log("writing latest json to path: ", latestJsonPath, " contents: ", latestJSON) fs.writeFileSync(latestJsonPath, JSON.stringify(latestJSON, null, 4)); } \ No newline at end of file diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index c7457d36..bcb4c306 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -1,6 +1,10 @@ import {fileURLToPath} from "url"; import {dirname, join} from "path"; -import {PRODUCT_NAME_SUFFIX_FOR_STAGE} from "./constants.js"; +import { + PRODUCT_NAME_SUFFIX_FOR_STAGE, + UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH, + UPDATE_NOTIFICATIONS_BASE_URL +} from "./constants.js"; import { EOL } from "os"; import fs from 'fs'; @@ -67,6 +71,10 @@ async function ciCreateDistReleaseConfig() { configJson.package.productName = _getProductName(configJson.package.productName, phoenixStage); console.log("Product name is: ", configJson.package.productName); configJson.tauri.windows[0].title = configJson.package.productName; + configJson.tauri.updater.endpoints = [ + `${UPDATE_NOTIFICATIONS_BASE_URL}${UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH[phoenixStage]}` + ]; + console.log("Product update endpoints are: ", configJson.tauri.updater.endpoints); console.log("Writing new dist config json ", tauriConfigPath); fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); return phoenixVersion; diff --git a/src-build/constants.js b/src-build/constants.js index 2f9f6515..3d99ca53 100644 --- a/src-build/constants.js +++ b/src-build/constants.js @@ -9,10 +9,12 @@ export const PRODUCT_NAME_SUFFIX_FOR_STAGE = { export const UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH = { // do not change any of these names unless you want to nuke the updater for all the whole installation base!! // or you know what you are doing. - dev: "docs/tauri/update-latest-experimental-build.json", - stage: "docs/tauri/update-latest-pre-release.json", - production: "docs/tauri/update-latest-stable-prod.json" + dev: "tauri/update-latest-experimental-build.json", + stage: "tauri/update-latest-pre-release.json", + production: "tauri/update-latest-stable-prod.json" }; +export const UPDATE_NOTIFICATIONS_BASE_URL = "https://updates.phcode.io/"; + // latest.json file that is generated as part of tauri build in every GitHub release. it is generated by tauri build action. export const LATEST_JSON_GITHUB_RELEASE = "latest.json"; \ No newline at end of file diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index cbfc79b4..ccc7daee 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -79,7 +79,7 @@ "installMode": "passive" }, "endpoints": [ - "https://releases.phcode.dev/{{target}}/{{arch}}/{{current_version}}" + "https://updates.phcode.io/tauri/update-latest-experimental-build.json" ], "dialog": true, "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDY2QTY2RjMxQUIzQkU0RDQKUldUVTVEdXJNVyttWmc2ODNSODlVcmZhS0dFRW1mYnBkaytvTDcrSDJXSlhYOHVrUWRyaXhHRjcK" From b117c12e68b3010a5dada61e403f703633be7132 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 12:53:32 +0000 Subject: [PATCH 064/864] ci: tauri release update notification json --- docs/tauri/update-latest-experimental-build.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 87424579..a9c1140d 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,22 +1,22 @@ { "version": "3.2.2", "notes": "", - "pub_date": "2023-07-28T11:20:09.293Z", + "pub_date": "2023-07-28T12:34:35.164Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxUdk9NbUVVKzlkMlN4UExPQ3pBU0h5YWh4cXJibXFybmw3Wnp2aHJZc3BLdnZCbTNpQTUrRkFYZWlHNzJ4eUxEbU4zVmdmUlhxMkdycTdrcHNJamdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQyMzUyCWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjIuMl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKTUJCM1BHa3JHZHd6Mi9aeFBpVGw2c21MRCtBUDg5ei83NkM2L0dEclhwTFlkbWoxSkl2dDhBVFNFZ1lRVWEvUXlPdGNTMzU5M1BZTytVYklWcEFvQ0E9PQo=", + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1vNU1UMitOVnhJTlprY25lZjNhUWtDa29UN1N4VmE3bEhoaFJxZkdhYm1kdjljQlRleHFkb2ROWXRjR0tTMnRPOThxSHdGcXZyaEtEWTJ3VkRLOVFvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQ2NDE3CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjIuMl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKVVI2Y1JXaDA0RlNLRHl0d0JxUlJTUGJURDFuR1BYNVR1ai9VS0NmcG1SdXpiRXhBVDlVTloySndLUHRuTU1lYVpudkVod3RWanhxaGNVNldxRUdyQXc9PQo=", "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/phoenix-code-experimental-build_3.2.2_amd64.AppImage.tar.gz" }, - "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhXUnFuN21URFdiUWswV3JrS0hLMUFhL3R3NG5uZXdOU0dmWjQzeDdmN1N5ZWNCcjQvRnBSYU50dFdpa3FHNk1xNTk0RTZTQlM2ZloxcitucStoUkFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQyMzgxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjIuMl94NjQtc2V0dXAubnNpcy56aXAKRnJoQU9WVGpON1k3cDhSLzN1VTJTQ2poU1ZOOU1XVmllaWRKREVsSUhNUzZUNDFxdFh0c2FHNWQ5azJMdHhaY0lWdE5YeCsxbWdWdFJVc0NTSm5kQ0E9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/latest/download/Phoenix.Code.Experimental.Build_3.2.2_x64-setup.nsis.zip" - }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRrQzZxV2lwUWpFNDV5SVlrTjUyVjM2UDYxcFczNTVXMkR1c1NwdWFObmtsTEtZNHJLYWRLcmR5aitxYk9xbTNCdnF3QVNZNS91QkF4YmUvTjlXeHdvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQyNDA2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjNPQ0pzbFdCdWtwZXZ5MWVReHQ4d1B5VzBKQ3pIU0ZPZnljMUxEQ1puWFY2VDduNmVhV2M3Mm84TmFpbHpTUGRWVW5QRCsyYkVuejdiRTB2dENhTERnPT0K", + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm00RGdCRkpYbmMrQmtCYTBPUmF1QW1ZMTdzQ3pXNEJwVmhwRHNwQjR4enBXWVpwUC9FUVlrcHp2RmU4c0xqc3daelJMK2xQZ3ZzNk94T1ZQNnQ1UXd3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQ2NjExCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnFQV3Qzcm9GQnQ1UHZEWkdKZ2NhRjRyaU9sUUNCa0IvNGtFdU5aZXNXenRja3BMUndIbUhncit0eUdka3pEVG03aDVLRm8xakZyN1ZFd1AvK1FhN0FnPT0K", "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, + "windows-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5ZZlNFMUpFd0RvU0Q4U0ovKy83bXpvT1E0Y01CZXk0Z3NuVFIzZUNZZ0Q3Rks5ZEJsSG92bm1OR1JXVVRObHUvMWsxRnFKY3pYREVxaUN4Ly9kTWdJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQ2NzAzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjIuMl94NjQtc2V0dXAubnNpcy56aXAKS1RNZkwrOFRwcTFVNzMvRFRqTHJVdnlDLzRjdThwRXVjVVp1Y1JwZGc1czhtTzVnRU1WcHBiZU5EaTVxTDRMcWltekNpRkNscFkxVCt4bjkrRDRMQ0E9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_3.2.2_x64-setup.nsis.zip" + }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxpRUNFVXcvSHhLakFjMng2Wmo3WXQ3OVVpcWRybk1velRvSlU5bkIya0x1QmJGZVF2dUxPck8vaXI1K1lzTU1SNVNKOHVvVVFqTUozbG03empkRkFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQzMjA0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjJuU1o5Wkt4aDNscDhRM2g5UFRrTnNtMjZZSS9VNmtIdS9MbDE2SVpkV2FaTnErZTMvS1dQenFvZXhoeHBvVU05RFFza0c5QVdTUXNTSnFBWHZtS0N3PT0K", + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBZWWdhTDA0WWlnTEpiM29EaEkvTUZIV2V3YkltMG1XZk5sM1VWZG02V1A0Uy81T0dSMVdwNlRMdmkzMGtUdG1VTHhWMHU4WXdsVzVZaU1iMmt5WVFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQ3NjY4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClcwV3JtMlA2d2RveTRiMUluK21sc0xkeVUzUTh6VlJQZ0QxMmVQZGdCOElyTTJkbmFDYS9yRGY2STZBVGUyd29DdC9Oc3FFeVhkUko1SDI1YmkvOUF3PT0K", "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } From 9d8bb60696ca12e4fb5aaf00189031a6f5553e3a Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 28 Jul 2023 16:42:00 +0000 Subject: [PATCH 065/864] ci: update phcode version to 3.2.3 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index ed2be746..42d2a841 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.2", + "version": "3.2.3", "type": "module", "scripts": { "tauri": "tauri", @@ -37,6 +37,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "3ce6abe6b11f24d5a364ee9a5dd6b5fd04b73b9a" + "commit": "ba6dc018d22a705013a6af0c66346d5f9bf6b1cf" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 15983a7c..4ae097d9 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.2" +version = "3.2.3" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ccc7daee..e2dd87e5 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code", - "version": "3.2.2" + "version": "3.2.3" }, "tauri": { "allowlist": { From f550f58adc1fa2db9aa4080a42b23534f7943a47 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 17:00:32 +0000 Subject: [PATCH 066/864] ci: tauri release update notification json --- docs/tauri/update-latest-experimental-build.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index a9c1140d..817b28a5 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,22 +1,22 @@ { "version": "3.2.2", "notes": "", - "pub_date": "2023-07-28T12:34:35.164Z", + "pub_date": "2023-07-28T16:58:50.024Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1vNU1UMitOVnhJTlprY25lZjNhUWtDa29UN1N4VmE3bEhoaFJxZkdhYm1kdjljQlRleHFkb2ROWXRjR0tTMnRPOThxSHdGcXZyaEtEWTJ3VkRLOVFvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQ2NDE3CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjIuMl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKVVI2Y1JXaDA0RlNLRHl0d0JxUlJTUGJURDFuR1BYNVR1ai9VS0NmcG1SdXpiRXhBVDlVTloySndLUHRuTU1lYVpudkVod3RWanhxaGNVNldxRUdyQXc9PQo=", + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhWbmg3cHUwSEVWelVWRmVxcnhVOHpIQ09ybXFSaDhMWmdLSnE2bndPVjRmUktJcmdmdjgwcmVuWkdXRnZtT3dVVmo1LzhYVS9iekJhaDJGVFRkZEFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTYyNzU4CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjIuMl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKa08xQ3E2NnVwL1B0cFdnVGIvT052WFUrN1kyb1Vtenh4YkZUVG8zclU5ZFp0VjdzUUNTeDRzZDM2QzdDQjlSbkVBbTRXWTh4M1ppVTNDZnRtamltQ1E9PQo=", "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/phoenix-code-experimental-build_3.2.2_amd64.AppImage.tar.gz" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm00RGdCRkpYbmMrQmtCYTBPUmF1QW1ZMTdzQ3pXNEJwVmhwRHNwQjR4enBXWVpwUC9FUVlrcHp2RmU4c0xqc3daelJMK2xQZ3ZzNk94T1ZQNnQ1UXd3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQ2NjExCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnFQV3Qzcm9GQnQ1UHZEWkdKZ2NhRjRyaU9sUUNCa0IvNGtFdU5aZXNXenRja3BMUndIbUhncit0eUdka3pEVG03aDVLRm8xakZyN1ZFd1AvK1FhN0FnPT0K", + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNDSkNJN0xkRUFaREU3K293WWwwUlkzV2hiY1M4Wm84c2tQeG9SRFhZcHE1VVhxa1B4UGxUdmY3NkcydVh3WWFnaTZzVXRxTzA5U25JRjBwaWtlNlFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTYyNzg3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmcweWxhNExSQ3pNc2FYTzNNS0lrZU1iZHBFN2VXZ1I1dU93N3B4QVltbFk3ZEQzNUZZTWtWR09KTTAxTTBpbnI1M0ZJUmE3THI3Z2piYzVoQ1J3Q0N3PT0K", "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5ZZlNFMUpFd0RvU0Q4U0ovKy83bXpvT1E0Y01CZXk0Z3NuVFIzZUNZZ0Q3Rks5ZEJsSG92bm1OR1JXVVRObHUvMWsxRnFKY3pYREVxaUN4Ly9kTWdJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQ2NzAzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjIuMl94NjQtc2V0dXAubnNpcy56aXAKS1RNZkwrOFRwcTFVNzMvRFRqTHJVdnlDLzRjdThwRXVjVVp1Y1JwZGc1czhtTzVnRU1WcHBiZU5EaTVxTDRMcWltekNpRkNscFkxVCt4bjkrRDRMQ0E9PQo=", + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm4wYjVsMzVob1pEekdMQ2RlUGtKOGRlWmJHdGdFc0VYS21XV3JMQTkrSjBlVnQrTEIvSEErMUJCa1N2WWh5dmE5NW5YRy8wZFR2Qk5wODBrRUZCWWdNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTYzMTI0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjIuMl94NjQtc2V0dXAubnNpcy56aXAKMW96NWpYQ2x6VjRBeGZhVWxIQkJiTFZJQkNIUWU4bmh0WXR4RHRDSFFrYUtWczlJWTAvalg5bDFRcWFTTC9WU3hxM1liKzdvUnMwSTJwak0yYnNnQmc9PQo=", "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_3.2.2_x64-setup.nsis.zip" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBZWWdhTDA0WWlnTEpiM29EaEkvTUZIV2V3YkltMG1XZk5sM1VWZG02V1A0Uy81T0dSMVdwNlRMdmkzMGtUdG1VTHhWMHU4WXdsVzVZaU1iMmt5WVFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTQ3NjY4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClcwV3JtMlA2d2RveTRiMUluK21sc0xkeVUzUTh6VlJQZ0QxMmVQZGdCOElyTTJkbmFDYS9yRGY2STZBVGUyd29DdC9Oc3FFeVhkUko1SDI1YmkvOUF3PT0K", + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtYcFJsaFRxQVNTOXo4dFc0aEpPV29Tamkzc3FMZHRGekh5b2R2S3hZMWxZZkxXb3QvZEl5OC9SM01qSWp2YjBQVFNvQ0QrY2cxa1RzdGM4akVLdVFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTYzNTI1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClhwNks2OFZCbCtvTHNmcVhPcmQ5NXRERzVPcEVyeHFLcHMzV1lOVFNHWit5ZzQ2SFNFa0N3UlNzdzFFejM0Q2pTODlXdVJ5aUVoZ2FnR0x0MTR5VUNBPT0K", "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } From 2e117efb003523a2e3fdb5aa4fb683110831cf1c Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 28 Jul 2023 17:28:47 +0000 Subject: [PATCH 067/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 817b28a5..ad161096 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.2.2", + "version": "3.2.3", "notes": "", - "pub_date": "2023-07-28T16:58:50.024Z", + "pub_date": "2023-07-28T17:25:10.800Z", "platforms": { - "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhWbmg3cHUwSEVWelVWRmVxcnhVOHpIQ09ybXFSaDhMWmdLSnE2bndPVjRmUktJcmdmdjgwcmVuWkdXRnZtT3dVVmo1LzhYVS9iekJhaDJGVFRkZEFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTYyNzU4CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjIuMl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKa08xQ3E2NnVwL1B0cFdnVGIvT052WFUrN1kyb1Vtenh4YkZUVG8zclU5ZFp0VjdzUUNTeDRzZDM2QzdDQjlSbkVBbTRXWTh4M1ppVTNDZnRtamltQ1E9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/phoenix-code-experimental-build_3.2.2_amd64.AppImage.tar.gz" - }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNDSkNJN0xkRUFaREU3K293WWwwUlkzV2hiY1M4Wm84c2tQeG9SRFhZcHE1VVhxa1B4UGxUdmY3NkcydVh3WWFnaTZzVXRxTzA5U25JRjBwaWtlNlFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTYyNzg3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmcweWxhNExSQ3pNc2FYTzNNS0lrZU1iZHBFN2VXZ1I1dU93N3B4QVltbFk3ZEQzNUZZTWtWR09KTTAxTTBpbnI1M0ZJUmE3THI3Z2piYzVoQ1J3Q0N3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnI3Z1dYREV4Yi9NNGpRVGdKTVdERXpwSlJCaEtOYUY2NSszRCszQUFMemVVVlJUZlNDUVRRMndlUm9FWE1td2xsMHBuQ0pUODdPWGo0UHBLUVlVNWdJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTY0Njg1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cko1WU5NbXA2M0Y0cCtNZmpwT05ZQjFNNmJFUTB0eUpoeGdhekIvN05Tb29TTDRGZjBDNldOWkJaMVBhNFNOaDJBcHBBOFZtalpHV0JvZktOOUMyQUJnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.3/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + }, + "linux-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNjaTdSb1pOeXBNUnVEcFpydkJFRXJJbTVCQjlYYk1pUFd1dnl6N0d4cEdaaU1xT2tUencybytHa2hwTWlBdDJ0VC9TeFpIZFFIWWl6clFBSnRJRGc0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTY0NzA5CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjIuM19hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKblN1bHlSQkd1OHgwOHZEOStxOVVZMUQzU1ZXSVB4ZlJWaTZFbzVaR3k2c1Q1bDJwRnk1WC93cGw3ZFc3Tm00WUxsa3pUTG5LNldwYnVyaUVtdlkxRFE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.3/phoenix-code-experimental-build_3.2.3_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm4wYjVsMzVob1pEekdMQ2RlUGtKOGRlWmJHdGdFc0VYS21XV3JMQTkrSjBlVnQrTEIvSEErMUJCa1N2WWh5dmE5NW5YRy8wZFR2Qk5wODBrRUZCWWdNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTYzMTI0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjIuMl94NjQtc2V0dXAubnNpcy56aXAKMW96NWpYQ2x6VjRBeGZhVWxIQkJiTFZJQkNIUWU4bmh0WXR4RHRDSFFrYUtWczlJWTAvalg5bDFRcWFTTC9WU3hxM1liKzdvUnMwSTJwak0yYnNnQmc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_3.2.2_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmppRXlabWh5TkZVR29xa2p5c3hFYmxTclRmYXZGRFFicmdmaEprNE5Fem1pczgwVkx6aEVhL3dCWGQ1RTV1cDBtY0NFdlFWRStvZW5UOXJDVVhpYncwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTY0NzY0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjIuM194NjQtc2V0dXAubnNpcy56aXAKNGNjckI4TWtJM3NKV2YxMzdoaURwSzMrQ20xblVxZ2ZjMitCdzR2blJMREJ3ai94WkFaM3ZJNzNJcjVMM1dXWGV3VnViaEVWRForRGxYK3Mrb0Z3Q0E9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.3/Phoenix.Code.Experimental.Build_3.2.3_x64-setup.nsis.zip" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtYcFJsaFRxQVNTOXo4dFc0aEpPV29Tamkzc3FMZHRGekh5b2R2S3hZMWxZZkxXb3QvZEl5OC9SM01qSWp2YjBQVFNvQ0QrY2cxa1RzdGM4akVLdVFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTYzNTI1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClhwNks2OFZCbCtvTHNmcVhPcmQ5NXRERzVPcEVyeHFLcHMzV1lOVFNHWit5ZzQ2SFNFa0N3UlNzdzFFejM0Q2pTODlXdVJ5aUVoZ2FnR0x0MTR5VUNBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9uU3pxVEZsU3puWEJDMGphL1ZQQ3duVnEwdXFLcHZNVmE1YW5nVjlna1I5ays5M1VBdENIVWUreUZOdHFrRVBEclhYcXFzaS9YZXhBN0hsbGdKZkFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTY1MTA1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CndSMnhwY1pNc09NdzBnRkFhRlNBRFRRcmV2bHRNVFNCeGVjbWRvZGpSbG9qRGw1K2lVODZoRElpa2JNdmp4MUVFUTR0Q3psQkw4NXhzTEtBNjFCaUJBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.3/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 09cc06fa7dfd3202566621a20b76a85e0bc919d4 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 29 Jul 2023 08:36:51 +0530 Subject: [PATCH 068/864] feat: nsis windows installer only and add locale language support --- src-tauri/tauri.conf.json | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index e2dd87e5..ab7d926e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -51,7 +51,7 @@ "icons/icon.ico" ], "identifier": "dev.phcode", - "longDescription": "", + "longDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", "macOS": { "entitlements": null, "exceptionDomain": "", @@ -62,12 +62,26 @@ "resources": [ "app/*" ], - "shortDescription": "", - "targets": "all", + "shortDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", + "targets": ["deb", "appimage", "nsis", "app", "dmg", "updater"], "windows": { "certificateThumbprint": "AB7D19C00251C1E412594A28DC79D201AAEF50D0", "digestAlgorithm": "sha256", - "timestampUrl": "http://timestamp.comodoca.com" + "timestampUrl": "http://timestamp.comodoca.com", + "nsis": { + "displayLanguageSelector": true, + "languages": [ + "Afrikaans", "Albanian", "Arabic", "Armenian", "Asturian", "Basque", "Belarusian", "Bosnian", "Breton", + "Bulgarian", "Catalan", "Cibemba", "Corsican", "Croatian", "Czech", "Danish", "Dutch", "Efik", "English", + "Esperanto", "Estonian", "Farsi", "Finnish", "French", "Galician", "Georgian", "German", "Greek", "Hebrew", "Hindi", + "Hungarian", "Icelandic", "Igbo", "Indonesian", "Irish", "Italian", "Japanese", "Khmer", "Korean", "Kurdish", "Latvian", + "Lithuanian", "Luxembourgish", "Macedonian", "Malagasy", "Malay", "Mongolian", "Norwegian", "NorwegianNynorsk", "Pashto", + "Polish", "Portuguese", "PortugueseBR", "Romanian", "Russian", "ScotsGaelic", "Serbian", "SerbianLatin", "SimpChinese", + "Slovak", "Slovenian", "Spanish", "SpanishInternational", "Swahili", "Swedish", "Tatar", "Thai", "TradChinese", + "Turkish", "Ukrainian", "Uzbek", "Valencian", "Vietnamese", "Welsh", "Yoruba" + ] + + } } }, "security": { From 946831762559280749f4f88ded47f53fefda1626 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 29 Jul 2023 09:24:40 +0530 Subject: [PATCH 069/864] fix: windows build break due to unsupported installer languages --- src-tauri/tauri.conf.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ab7d926e..deef520a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -71,14 +71,14 @@ "nsis": { "displayLanguageSelector": true, "languages": [ - "Afrikaans", "Albanian", "Arabic", "Armenian", "Asturian", "Basque", "Belarusian", "Bosnian", "Breton", - "Bulgarian", "Catalan", "Cibemba", "Corsican", "Croatian", "Czech", "Danish", "Dutch", "Efik", "English", + "English", "Afrikaans", "Albanian", "Arabic", "Armenian", "Asturian", "Basque", "Belarusian", "Bosnian", "Breton", + "Bulgarian", "Catalan", "Corsican", "Croatian", "Czech", "Danish", "Dutch", "Esperanto", "Estonian", "Farsi", "Finnish", "French", "Galician", "Georgian", "German", "Greek", "Hebrew", "Hindi", - "Hungarian", "Icelandic", "Igbo", "Indonesian", "Irish", "Italian", "Japanese", "Khmer", "Korean", "Kurdish", "Latvian", - "Lithuanian", "Luxembourgish", "Macedonian", "Malagasy", "Malay", "Mongolian", "Norwegian", "NorwegianNynorsk", "Pashto", + "Hungarian", "Icelandic", "Indonesian", "Irish", "Italian", "Japanese", "Korean", "Kurdish", "Latvian", + "Lithuanian", "Luxembourgish", "Macedonian", "Malay", "Mongolian", "Norwegian", "NorwegianNynorsk", "Pashto", "Polish", "Portuguese", "PortugueseBR", "Romanian", "Russian", "ScotsGaelic", "Serbian", "SerbianLatin", "SimpChinese", - "Slovak", "Slovenian", "Spanish", "SpanishInternational", "Swahili", "Swedish", "Tatar", "Thai", "TradChinese", - "Turkish", "Ukrainian", "Uzbek", "Valencian", "Vietnamese", "Welsh", "Yoruba" + "Slovak", "Slovenian", "Spanish", "SpanishInternational", "Swedish", "Tatar", "Thai", "TradChinese", + "Turkish", "Ukrainian", "Uzbek", "Vietnamese", "Welsh" ] } From 154706b6328b8195cb585071173c9846ad2b5b96 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 29 Jul 2023 09:29:56 +0530 Subject: [PATCH 070/864] fix: npm run release* builds failing locally --- src-build/ci-createDistReleaseConfig.js | 1 + src-build/createDistReleaseConfig.js | 1 + src-build/createSrcReleaseConfig.js | 1 + 3 files changed, 3 insertions(+) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index bcb4c306..622a7f50 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -67,6 +67,7 @@ async function ciCreateDistReleaseConfig() { configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); configJson.build.distDir = '../phoenix/dist/' // delete configJson.tauri.updater; // #uncomment_line_for_local_build_1 + // delete configJson.tauri.bundle.windows.certificateThumbprint // #uncomment_line_for_local_build_1 configJson.package.version = phoenixVersion; configJson.package.productName = _getProductName(configJson.package.productName, phoenixStage); console.log("Product name is: ", configJson.package.productName); diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index 123e491c..7a32c088 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -16,6 +16,7 @@ async function createDistReleaseConfig() { console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); delete configJson.tauri.updater; + delete configJson.tauri.bundle.windows.certificateThumbprint; configJson.build.distDir = '../../phoenix/dist/' console.log("Writing new local config json ", tauriLocalConfigPath); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index 9f7b35d4..ff2ef1da 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -16,6 +16,7 @@ async function createSrcReleaseConfig() { console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); delete configJson.tauri.updater; + delete configJson.tauri.bundle.windows.certificateThumbprint; configJson.build.distDir = '../../phoenix/src/' console.log("Writing new local config json ", tauriLocalConfigPath); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); From 4c00a2cd7e83b59f1b31233001021067803c244b Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 31 Jul 2023 18:56:28 +0530 Subject: [PATCH 071/864] chore: change node name to phnode --- package-lock.json | 4 ++-- src-build/utils.js | 8 ++++---- src-tauri/Cargo.lock | 2 +- src-tauri/tauri.conf.json | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 13bcd787..40506a3d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.2.2", + "version": "3.2.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.2", + "version": "3.2.3", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.4.0", diff --git a/src-build/utils.js b/src-build/utils.js index b7381559..9a5a5f5b 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -77,16 +77,16 @@ export function getPlatformDetails() { export function getSideCarBinName(platform, arch) { if (platform === "linux" && arch === "x64") { - return "node-x86_64-unknown-linux-gnu"; + return "phnode-x86_64-unknown-linux-gnu"; } if (platform === "darwin" && arch === "x64") { - return "node-x86_64-apple-darwin"; + return "phnode-x86_64-apple-darwin"; } if (platform ==="darwin" && arch === "arm64"){ - return "node-aarch64-apple-darwin"; + return "phnode-aarch64-apple-darwin"; } if (platform === "win" && arch === "x64") { - return "node-x86_64-pc-windows-msvc.exe"; + return "phnode-x86_64-pc-windows-msvc.exe"; } throw new Error(`unsupported ${platform} ${arch}`); } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2c3c3bf9..01003460 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2027,7 +2027,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.2" +version = "3.2.3" dependencies = [ "serde", "serde_json", diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index deef520a..50d0598c 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -41,7 +41,7 @@ "depends": [] }, "externalBin": [ - "./node" + "./phnode" ], "icon": [ "icons/32x32.png", @@ -110,4 +110,4 @@ } ] } -} \ No newline at end of file +} From 586bebd1d9ca00ac6913d2adceac3ad54db09ec7 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 1 Aug 2023 13:04:24 +0530 Subject: [PATCH 072/864] build: remove dmg builds in ubuntu and add macos entitlements --- .gitignore | 2 ++ entitlements.plist | 6 ++++++ src-tauri/tauri.conf.json | 9 ++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 entitlements.plist diff --git a/.gitignore b/.gitignore index 1def9783..b0057347 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ lerna-debug.log* node-bins src-build/node-* src-tauri/node-* +src-build/phnode-* +src-tauri/phnode-* src-tauri/tauri-local.conf.json phoenix diff --git a/entitlements.plist b/entitlements.plist new file mode 100644 index 00000000..5516ebf3 --- /dev/null +++ b/entitlements.plist @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 50d0598c..c37433a4 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -40,6 +40,9 @@ "deb": { "depends": [] }, + "appimage": { + "bundleMediaFramework": true + }, "externalBin": [ "./phnode" ], @@ -53,8 +56,8 @@ "identifier": "dev.phcode", "longDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", "macOS": { - "entitlements": null, - "exceptionDomain": "", + "entitlements": "../entitlements.plist", + "exceptionDomain": "localhost", "frameworks": [], "providerShortName": null, "signingIdentity": null @@ -63,7 +66,7 @@ "app/*" ], "shortDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", - "targets": ["deb", "appimage", "nsis", "app", "dmg", "updater"], + "targets": ["appimage", "nsis", "app", "dmg", "updater"], "windows": { "certificateThumbprint": "AB7D19C00251C1E412594A28DC79D201AAEF50D0", "digestAlgorithm": "sha256", From 3e9186be3ce9ab50894e0f802f4fe3b14af57850 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 1 Aug 2023 14:51:51 +0530 Subject: [PATCH 073/864] feat: enable dev tools in release builds --- src-build/downloadNode.js | 3 +-- src-tauri/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index a48f0a05..be8c68c0 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -70,8 +70,7 @@ async function downloadNodeBinary(version, platform, arch) { res.pipe(file); res.on('end', () => resolve(fileName)); res.on('error', (err) => { - fs.unlink(fileName, () => { - }); // Remove the file on error + fs.unlinkSync(fileName); // Remove the file on error reject(err); }); }); diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4ae097d9..86b4869d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,7 +16,7 @@ tauri-build = { version = "1.4.0", features = [] } [dependencies] serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4.1", features = [ "updater", "shell-sidecar", "fs-all", "window-all"] } +tauri = { version = "1.4.1", features = [ "updater", "shell-sidecar", "fs-all", "window-all", "devtools"] } [features] # by default Tauri runs in production mode From dc9089218145d52ba323a9824ea6a0c755410e17 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 1 Aug 2023 18:16:07 +0530 Subject: [PATCH 074/864] feat: add toggle_devtools api in tauri --- src-tauri/src/main.rs | 19 ++++++++++++++++--- src-tauri/tauri.conf.json | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 2cb97bb9..0e1086cd 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -11,19 +11,32 @@ fn greet(handle: tauri::AppHandle, name: &str) -> String { let resource_path = handle.path_resolver() .resolve_resource("app/hello.js") .expect("failed to resolve resource"); - Command::new_sidecar("node") + Command::new_sidecar("phnode") .expect("failed to create `my-sidecar` binary command") .args(resource_path.as_path().to_str()) .spawn() .expect("Failed to spawn sidecar"); - // let name = "hello"; println!("hello"); format!("Hello, {}! You've been greeted from Rust!", name) } +#[tauri::command] +fn toggle_devtools(window: tauri::Window) { + static mut DEVTOOLS_LOADED:bool = false; + unsafe { + // though unsafe, this is fine as its just a view toggle and not mission critical. + if !DEVTOOLS_LOADED { + window.open_devtools(); + } else { + window.close_devtools(); + } + DEVTOOLS_LOADED = !DEVTOOLS_LOADED; + } +} + fn main() { tauri::Builder::default() - .invoke_handler(tauri::generate_handler![greet]) + .invoke_handler(tauri::generate_handler![greet, toggle_devtools]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c37433a4..84253a2a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -27,7 +27,7 @@ "sidecar": true, "scope": [ { - "name": "node", + "name": "phnode", "sidecar": true } ] From e375b28a1698eadd83a7a8794972643d32b96c24 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Tue, 1 Aug 2023 14:03:03 +0000 Subject: [PATCH 075/864] ci: update phcode version to 3.2.5 --- package.json | 4 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 88 +++++++++++++++++++++++++++++++++------ 3 files changed, 79 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 42d2a841..b61e8ba6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.3", + "version": "3.2.5", "type": "module", "scripts": { "tauri": "tauri", @@ -37,6 +37,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "ba6dc018d22a705013a6af0c66346d5f9bf6b1cf" + "commit": "33f9cc52669a82a66b106c5fa9f9cc89a65b0b06" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 86b4869d..1458ec06 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.3" +version = "3.2.5" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 84253a2a..424534e2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code", - "version": "3.2.3" + "version": "3.2.5" }, "tauri": { "allowlist": { @@ -66,7 +66,13 @@ "app/*" ], "shortDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", - "targets": ["appimage", "nsis", "app", "dmg", "updater"], + "targets": [ + "appimage", + "nsis", + "app", + "dmg", + "updater" + ], "windows": { "certificateThumbprint": "AB7D19C00251C1E412594A28DC79D201AAEF50D0", "digestAlgorithm": "sha256", @@ -74,16 +80,74 @@ "nsis": { "displayLanguageSelector": true, "languages": [ - "English", "Afrikaans", "Albanian", "Arabic", "Armenian", "Asturian", "Basque", "Belarusian", "Bosnian", "Breton", - "Bulgarian", "Catalan", "Corsican", "Croatian", "Czech", "Danish", "Dutch", - "Esperanto", "Estonian", "Farsi", "Finnish", "French", "Galician", "Georgian", "German", "Greek", "Hebrew", "Hindi", - "Hungarian", "Icelandic", "Indonesian", "Irish", "Italian", "Japanese", "Korean", "Kurdish", "Latvian", - "Lithuanian", "Luxembourgish", "Macedonian", "Malay", "Mongolian", "Norwegian", "NorwegianNynorsk", "Pashto", - "Polish", "Portuguese", "PortugueseBR", "Romanian", "Russian", "ScotsGaelic", "Serbian", "SerbianLatin", "SimpChinese", - "Slovak", "Slovenian", "Spanish", "SpanishInternational", "Swedish", "Tatar", "Thai", "TradChinese", - "Turkish", "Ukrainian", "Uzbek", "Vietnamese", "Welsh" + "English", + "Afrikaans", + "Albanian", + "Arabic", + "Armenian", + "Asturian", + "Basque", + "Belarusian", + "Bosnian", + "Breton", + "Bulgarian", + "Catalan", + "Corsican", + "Croatian", + "Czech", + "Danish", + "Dutch", + "Esperanto", + "Estonian", + "Farsi", + "Finnish", + "French", + "Galician", + "Georgian", + "German", + "Greek", + "Hebrew", + "Hindi", + "Hungarian", + "Icelandic", + "Indonesian", + "Irish", + "Italian", + "Japanese", + "Korean", + "Kurdish", + "Latvian", + "Lithuanian", + "Luxembourgish", + "Macedonian", + "Malay", + "Mongolian", + "Norwegian", + "NorwegianNynorsk", + "Pashto", + "Polish", + "Portuguese", + "PortugueseBR", + "Romanian", + "Russian", + "ScotsGaelic", + "Serbian", + "SerbianLatin", + "SimpChinese", + "Slovak", + "Slovenian", + "Spanish", + "SpanishInternational", + "Swedish", + "Tatar", + "Thai", + "TradChinese", + "Turkish", + "Ukrainian", + "Uzbek", + "Vietnamese", + "Welsh" ] - } } }, @@ -113,4 +177,4 @@ } ] } -} +} \ No newline at end of file From 98bd9d0e566365d07dea96303f2d69dbd9890b97 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 1 Aug 2023 22:16:02 +0530 Subject: [PATCH 076/864] fix: linux ubuntu releases cannot play youtube videos --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 6b7975c8..19cf5c42 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -64,7 +64,7 @@ jobs: if: matrix.platform == 'ubuntu-20.04' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf gstreamer1.0-libav - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index c9080150..7446cc41 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -64,7 +64,7 @@ jobs: if: matrix.platform == 'ubuntu-20.04' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf gstreamer1.0-libav - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 1db8ff3b..296d820b 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -64,7 +64,7 @@ jobs: if: matrix.platform == 'ubuntu-20.04' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf gstreamer1.0-libav - name: install frontend dependencies run: | npm install From df6a162cc0e4257948cd2c55489574632ccaaadc Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 2 Aug 2023 17:02:13 +0530 Subject: [PATCH 077/864] fix: youtube not playing in ubuntu appimafe --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 19cf5c42..a016c7f7 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -64,7 +64,7 @@ jobs: if: matrix.platform == 'ubuntu-20.04' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf gstreamer1.0-libav + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 7446cc41..e4e1c1a5 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -64,7 +64,7 @@ jobs: if: matrix.platform == 'ubuntu-20.04' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf gstreamer1.0-libav + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 296d820b..bfe72c1c 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -64,7 +64,7 @@ jobs: if: matrix.platform == 'ubuntu-20.04' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf gstreamer1.0-libav + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies run: | npm install From e1b1a8ef4a0fe94f06f42921b8a230e85b198f97 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 3 Aug 2023 00:14:30 +0530 Subject: [PATCH 078/864] fix: app image not rendering video in linux --- .github/workflows/tauri-build-dev.yml | 3 +++ .github/workflows/tauri-build-prod.yml | 2 ++ .github/workflows/tauri-build-staging.yml | 2 ++ src-tauri/Cargo.lock | 2 +- 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index a016c7f7..a80ea842 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -65,6 +65,9 @@ jobs: run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio + sudo apt-get install -y gvfs + sudo apt-get install -y libglib2.0-0 + - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index e4e1c1a5..4dcec675 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -65,6 +65,8 @@ jobs: run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio + sudo apt-get install -y gvfs + sudo apt-get install -y libglib2.0-0 - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index bfe72c1c..11938d6e 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -65,6 +65,8 @@ jobs: run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio + sudo apt-get install -y gvfs + sudo apt-get install -y libglib2.0-0 - name: install frontend dependencies run: | npm install diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 01003460..ba1a7280 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2027,7 +2027,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.3" +version = "3.2.5" dependencies = [ "serde", "serde_json", From 75d300250a6ca14548803ee754d615815f3229a0 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 3 Aug 2023 00:40:27 +0530 Subject: [PATCH 079/864] chore: update ubuntu build to ubuntu latest --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index a80ea842..fb73506d 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -46,7 +46,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-20.04, windows-latest ] + platform: [ macos-latest, ubuntu-latest, windows-latest ] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 4dcec675..9635d982 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -46,7 +46,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-20.04, windows-latest ] + platform: [ macos-latest, ubuntu-latest, windows-latest ] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 11938d6e..96b73ffd 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -46,7 +46,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-20.04, windows-latest ] + platform: [ macos-latest, ubuntu-latest, windows-latest ] runs-on: ${{ matrix.platform }} steps: From 343d0bb642806cdcada670c81343a1ea1fdee0e7 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 3 Aug 2023 00:48:34 +0530 Subject: [PATCH 080/864] chore: add libgtk3 lib --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 1 + .github/workflows/tauri-build-staging.yml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index fb73506d..cfc120e2 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -67,7 +67,7 @@ jobs: sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio sudo apt-get install -y gvfs sudo apt-get install -y libglib2.0-0 - + sudo apt-get install libgtk-3-dev - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 9635d982..71bbb90b 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -67,6 +67,7 @@ jobs: sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio sudo apt-get install -y gvfs sudo apt-get install -y libglib2.0-0 + sudo apt-get install libgtk-3-dev - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 96b73ffd..569ad618 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -67,6 +67,7 @@ jobs: sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio sudo apt-get install -y gvfs sudo apt-get install -y libglib2.0-0 + sudo apt-get install libgtk-3-dev - name: install frontend dependencies run: | npm install From 2301e7eb73a9b17dbfdd69286b7317ca6de860e8 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 3 Aug 2023 00:54:09 +0530 Subject: [PATCH 081/864] fix: update ubuntu on github action --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index cfc120e2..694bfbfc 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -61,7 +61,7 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-20.04' + if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 71bbb90b..09afbd64 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -61,7 +61,7 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-20.04' + if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 569ad618..3cf3ae0e 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -61,7 +61,7 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-20.04' + if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio From 3d77d390fecb078a96dcda1ddd74f20eacb9985b Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 3 Aug 2023 00:59:10 +0530 Subject: [PATCH 082/864] chore: remove dependency --- .github/workflows/tauri-build-dev.yml | 5 +---- .github/workflows/tauri-build-prod.yml | 5 +---- .github/workflows/tauri-build-staging.yml | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 694bfbfc..5a2120ba 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -64,10 +64,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - sudo apt-get install -y gvfs - sudo apt-get install -y libglib2.0-0 - sudo apt-get install libgtk-3-dev + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 09afbd64..d49f20f8 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -64,10 +64,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - sudo apt-get install -y gvfs - sudo apt-get install -y libglib2.0-0 - sudo apt-get install libgtk-3-dev + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 3cf3ae0e..69862b59 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -64,10 +64,7 @@ jobs: if: matrix.platform == 'ubuntu-latest' run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - sudo apt-get install -y gvfs - sudo apt-get install -y libglib2.0-0 - sudo apt-get install libgtk-3-dev + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - name: install frontend dependencies run: | npm install From 1d7bfbc4db45e4234ebb589ec292713f7b42337d Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 3 Aug 2023 01:43:44 +0530 Subject: [PATCH 083/864] chore: exp ubuntu --- .github/workflows/tauri-build-dev.yml | 4 ++++ .github/workflows/tauri-build-prod.yml | 4 ++++ .github/workflows/tauri-build-staging.yml | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 5a2120ba..e7e5f5d7 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -65,6 +65,10 @@ jobs: run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev + sudo apt-get install -y libwebrtc-audio-processing-dev + sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio + sudo apt-get install -y gvfs + - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index d49f20f8..6d4be6a3 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -65,6 +65,10 @@ jobs: run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev + sudo apt-get install -y libwebrtc-audio-processing-dev + sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio + sudo apt-get install -y gvfs + - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 69862b59..d8a27160 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -65,6 +65,10 @@ jobs: run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev + sudo apt-get install -y libwebrtc-audio-processing-dev + sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio + sudo apt-get install -y gvfs + - name: install frontend dependencies run: | npm install From 9aebb85eefc9f437ada9cc10e0f9ed5b668b3bac Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 3 Aug 2023 01:48:51 +0530 Subject: [PATCH 084/864] fix: ubuntu build failiure --- .github/workflows/tauri-build-dev.yml | 1 + .github/workflows/tauri-build-prod.yml | 1 + .github/workflows/tauri-build-staging.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index e7e5f5d7..6b21aa9a 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -66,6 +66,7 @@ jobs: sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev sudo apt-get install -y libwebrtc-audio-processing-dev + sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio sudo apt-get install -y gvfs diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 6d4be6a3..f40d8099 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -66,6 +66,7 @@ jobs: sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev sudo apt-get install -y libwebrtc-audio-processing-dev + sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio sudo apt-get install -y gvfs diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index d8a27160..b525ee42 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -66,6 +66,7 @@ jobs: sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev sudo apt-get install -y libwebrtc-audio-processing-dev + sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio sudo apt-get install -y gvfs From 3596522cd947cce8f4fc4e2b8064b98a8591ea5e Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 3 Aug 2023 02:27:48 +0530 Subject: [PATCH 085/864] chore: remove unwanted files --- .github/workflows/tauri-build-dev.yml | 2 -- .github/workflows/tauri-build-prod.yml | 2 -- .github/workflows/tauri-build-staging.yml | 2 -- 3 files changed, 6 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 6b21aa9a..345624b8 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -68,8 +68,6 @@ jobs: sudo apt-get install -y libwebrtc-audio-processing-dev sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - sudo apt-get install -y gvfs - - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index f40d8099..b05a434f 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -68,8 +68,6 @@ jobs: sudo apt-get install -y libwebrtc-audio-processing-dev sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - sudo apt-get install -y gvfs - - name: install frontend dependencies run: | npm install diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index b525ee42..b6061022 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -68,8 +68,6 @@ jobs: sudo apt-get install -y libwebrtc-audio-processing-dev sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - sudo apt-get install -y gvfs - - name: install frontend dependencies run: | npm install From 7bd96625c0817f907108aa64c7530e2870394af7 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 3 Aug 2023 02:30:14 +0530 Subject: [PATCH 086/864] chore: update ubuntu in github action to latest --- .github/workflows/tauri-build-dev.yml | 4 ++-- .github/workflows/tauri-build-prod.yml | 4 ++-- .github/workflows/tauri-build-staging.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 345624b8..35f073c1 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -8,7 +8,7 @@ jobs: create-release: permissions: contents: write - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest outputs: release_id: ${{ steps.create-release.outputs.result }} @@ -158,7 +158,7 @@ jobs: publish-release: permissions: contents: write - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest needs: [ create-release, build-tauri ] steps: diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index b05a434f..4e8714bb 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -8,7 +8,7 @@ jobs: create-release: permissions: contents: write - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest outputs: release_id: ${{ steps.create-release.outputs.result }} @@ -159,7 +159,7 @@ jobs: publish-release: permissions: contents: write - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest needs: [ create-release, build-tauri ] steps: diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index b6061022..68b3374c 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -8,7 +8,7 @@ jobs: create-release: permissions: contents: write - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest outputs: release_id: ${{ steps.create-release.outputs.result }} @@ -159,7 +159,7 @@ jobs: publish-release: permissions: contents: write - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest needs: [ create-release, build-tauri ] steps: From 5383287afce72857616638df758fc8aa20f43f67 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 3 Aug 2023 16:04:42 +0530 Subject: [PATCH 087/864] feat: resize window on startup --- src-tauri/Cargo.lock | 1 + src-tauri/Cargo.toml | 1 + src-tauri/src/boot_config.rs | 43 +++++++++++++++++++++++++ src-tauri/src/init.rs | 59 ++++++++++++++++++++++++++++++++++ src-tauri/src/main.rs | 10 +++++- src-tauri/src/utilities.rs | 61 ++++++++++++++++++++++++++++++++++++ src-tauri/tauri.conf.json | 2 +- 7 files changed, 175 insertions(+), 2 deletions(-) create mode 100644 src-tauri/src/boot_config.rs create mode 100644 src-tauri/src/init.rs create mode 100644 src-tauri/src/utilities.rs diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ba1a7280..35686328 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2029,6 +2029,7 @@ dependencies = [ name = "phoenix-code-ide" version = "3.2.5" dependencies = [ + "once_cell", "serde", "serde_json", "tauri", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1458ec06..09494cd8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -15,6 +15,7 @@ tauri-build = { version = "1.4.0", features = [] } [dependencies] serde_json = "1.0" +once_cell = "1.18.0" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.4.1", features = [ "updater", "shell-sidecar", "fs-all", "window-all", "devtools"] } diff --git a/src-tauri/src/boot_config.rs b/src-tauri/src/boot_config.rs new file mode 100644 index 00000000..c8dc204e --- /dev/null +++ b/src-tauri/src/boot_config.rs @@ -0,0 +1,43 @@ +use serde_json::Value; +use crate::utilities::read_json_file; +use std::path::PathBuf; + +pub struct BootConfig { + pub last_window_width: u32, + pub last_window_height: u32, +} +static BOOT_CONFIG_FILE_NAME: &'static str = "boot_config.json"; + +fn get_boot_config_file_path(app_data_dir: &PathBuf) -> PathBuf { + let mut config_file_path = app_data_dir.clone(); + config_file_path.push(BOOT_CONFIG_FILE_NAME); + return config_file_path; +} + +fn set_boot_config(boot_config: &mut BootConfig, value: &Value) { + boot_config.last_window_width = match value["last_window_width"].as_u64() { + Some(value) => value as u32, + None => 0 + }; + boot_config.last_window_height = match value["last_window_height"].as_u64() { + Some(value) => value as u32, + None => 0 + }; +} + +pub fn read_boot_config(app_data_dir: &PathBuf) -> BootConfig { + let boot_config_file_path = get_boot_config_file_path(app_data_dir); + let mut boot_config = BootConfig { + last_window_width: 0, + last_window_height: 0 + }; + match read_json_file(&boot_config_file_path) { + Some(value) =>{ + set_boot_config(&mut boot_config, &value); + } + None => { + eprintln!("No boot restore config file found {}", boot_config_file_path.display()); + } + } + return boot_config; +} diff --git a/src-tauri/src/init.rs b/src-tauri/src/init.rs new file mode 100644 index 00000000..8869150e --- /dev/null +++ b/src-tauri/src/init.rs @@ -0,0 +1,59 @@ +use std::sync::Arc; +use once_cell::sync::OnceCell; +use tauri::Manager; +use crate::utilities::ensure_dir_exists; +use crate::boot_config::read_boot_config; +use crate::boot_config::BootConfig; + +struct AppConstants { + tauri_config : Arc, + app_data_dir: std::path::PathBuf +} +static APP_CONSTANTS: OnceCell = OnceCell::new(); +static PREFERRED_WIDTH: u32 = 1366; +static PREFERRED_HEIGHT: u32 = 900; +static MAXIMIZE_SIZE: u32 = 0; + +fn get_window_size(last_saved_size: u32, screen_size: u32, preferred_size: u32) -> u32 { + if last_saved_size != 0 && last_saved_size <= screen_size { + return last_saved_size; + } + if preferred_size < screen_size { + return preferred_size; + } + return MAXIMIZE_SIZE; +} + +fn restore_window_size(app: &mut tauri::App, boot_config: &BootConfig){ + let main_window = app.get_window("main").unwrap(); + let current_monitor = main_window.current_monitor().unwrap().unwrap(); + let current_monitor_size = current_monitor.size(); + println!("current_monitor_size is {}, {}", current_monitor_size.width, current_monitor_size.height); + println!("saved window size is {}, {}", boot_config.last_window_width, boot_config.last_window_height); + let width = get_window_size(boot_config.last_window_width, current_monitor_size.width, PREFERRED_WIDTH); + let height = get_window_size(boot_config.last_window_height, current_monitor_size.height, PREFERRED_HEIGHT); + if width == MAXIMIZE_SIZE || height == MAXIMIZE_SIZE { + main_window.maximize().expect("unable to maximize"); + } else { + println!("resizing window to {}, {}", width, height); + let size = tauri::PhysicalSize::new(width, height); + main_window.set_size(size).expect("unable to resize"); + } +} + +pub fn init_app(app: &mut tauri::App) { + let config = app.config().clone(); + let _ = APP_CONSTANTS.set(AppConstants { + tauri_config: config.clone(), + app_data_dir: tauri::api::path::app_data_dir(&config).expect("failed to retrieve app_data_dir") + .canonicalize().expect("Failed to canonicalize app_data_dir") + }); + + // To get a value + if let Some(app_constants) = APP_CONSTANTS.get() { + println!("Appdata Dir is {}", app_constants.app_data_dir.display()); + ensure_dir_exists(&app_constants.app_data_dir); + let boot_config = read_boot_config(&app_constants.app_data_dir); + restore_window_size(app, &boot_config); + } +} \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 0e1086cd..757b7d13 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,6 +4,9 @@ windows_subsystem = "windows" )] use tauri::api::process::Command; +mod init; +mod utilities; +mod boot_config; // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command #[tauri::command] @@ -20,9 +23,10 @@ fn greet(handle: tauri::AppHandle, name: &str) -> String { format!("Hello, {}! You've been greeted from Rust!", name) } +static mut DEVTOOLS_LOADED:bool = false; + #[tauri::command] fn toggle_devtools(window: tauri::Window) { - static mut DEVTOOLS_LOADED:bool = false; unsafe { // though unsafe, this is fine as its just a view toggle and not mission critical. if !DEVTOOLS_LOADED { @@ -36,6 +40,10 @@ fn toggle_devtools(window: tauri::Window) { fn main() { tauri::Builder::default() + .setup(|app| { + init::init_app(app); + Ok(()) + }) .invoke_handler(tauri::generate_handler![greet, toggle_devtools]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src-tauri/src/utilities.rs b/src-tauri/src/utilities.rs new file mode 100644 index 00000000..fe17df26 --- /dev/null +++ b/src-tauri/src/utilities.rs @@ -0,0 +1,61 @@ +use std::fs; +use serde_json; +use std::path::PathBuf; +use std::fs::File; +use std::io::Read; +use serde_json::Value; + +/// This function prints the type of the input value. +/// +/// It uses Rust's reflection capabilities to determine and print the type +/// of the input. This can be useful for debugging and understanding +/// what types are being used in certain parts of your code. +/// +/// # Examples +/// +/// ``` +/// let x = 5; +/// print_type_of(&x); +/// // prints: "i32" +/// ``` +/// +/// # Panics +/// +/// This function does not panic. +/// +/// # Errors +/// +/// This function does not return any errors. +pub fn print_type_of(_: &T) { + println!("{}", std::any::type_name::()); +} + +pub fn ensure_dir_exists(path: &PathBuf){ + if let Err(e) = fs::create_dir_all(path) { + eprintln!("Failed to create directory: {}", e); + } else { + println!("Directory created successfully {}", path.display()); + } +} + +pub fn read_json_file(path: &PathBuf) -> Option { + let filename = match path.to_str() { + Some(file) => file.to_string(), // Convert &str to String + None => return None, // File not present or cannot be opened + }; + + let mut file = match File::open(filename) { + Ok(file) => file, + Err(_) => return None, // File not present or cannot be opened + }; + + let mut contents = String::new(); + if let Err(_) = file.read_to_string(&mut contents) { + return None; // Error reading the file + } + + match serde_json::from_str(&contents) { + Ok(data) => Some(data), + Err(_) => None, // JSON parsing error + } +} diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 424534e2..7f164a5d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -53,7 +53,7 @@ "icons/icon.icns", "icons/icon.ico" ], - "identifier": "dev.phcode", + "identifier": "io.phcode", "longDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", "macOS": { "entitlements": "../entitlements.plist", From 7608a527966e1b9b7618668ce1dc69da8627cddb Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 3 Aug 2023 18:01:06 +0530 Subject: [PATCH 088/864] chore: tauri window close event latch to save window sizes on exit --- src-tauri/src/boot_config.rs | 4 ++-- src-tauri/src/init.rs | 1 + src-tauri/src/main.rs | 9 +++++++++ src-tauri/src/utilities.rs | 4 ++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src-tauri/src/boot_config.rs b/src-tauri/src/boot_config.rs index c8dc204e..cd48ce29 100644 --- a/src-tauri/src/boot_config.rs +++ b/src-tauri/src/boot_config.rs @@ -14,7 +14,7 @@ fn get_boot_config_file_path(app_data_dir: &PathBuf) -> PathBuf { return config_file_path; } -fn set_boot_config(boot_config: &mut BootConfig, value: &Value) { +fn _set_boot_config(boot_config: &mut BootConfig, value: &Value) { boot_config.last_window_width = match value["last_window_width"].as_u64() { Some(value) => value as u32, None => 0 @@ -33,7 +33,7 @@ pub fn read_boot_config(app_data_dir: &PathBuf) -> BootConfig { }; match read_json_file(&boot_config_file_path) { Some(value) =>{ - set_boot_config(&mut boot_config, &value); + _set_boot_config(&mut boot_config, &value); } None => { eprintln!("No boot restore config file found {}", boot_config_file_path.display()); diff --git a/src-tauri/src/init.rs b/src-tauri/src/init.rs index 8869150e..7d3bd354 100644 --- a/src-tauri/src/init.rs +++ b/src-tauri/src/init.rs @@ -51,6 +51,7 @@ pub fn init_app(app: &mut tauri::App) { // To get a value if let Some(app_constants) = APP_CONSTANTS.get() { + println!("Bundle ID is {}", app_constants.tauri_config.tauri.bundle.identifier); println!("Appdata Dir is {}", app_constants.app_data_dir.display()); ensure_dir_exists(&app_constants.app_data_dir); let boot_config = read_boot_config(&app_constants.app_data_dir); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 757b7d13..a044cab5 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,6 +4,7 @@ windows_subsystem = "windows" )] use tauri::api::process::Command; +use tauri::GlobalWindowEvent; mod init; mod utilities; mod boot_config; @@ -38,12 +39,20 @@ fn toggle_devtools(window: tauri::Window) { } } +fn process_window_event(event: &GlobalWindowEvent) { + if let tauri::WindowEvent::CloseRequested { .. } = event.event() { + let size = event.window().outer_size().unwrap(); + println!("Window closing {}, {}", size.width, size.height); + } +} + fn main() { tauri::Builder::default() .setup(|app| { init::init_app(app); Ok(()) }) + .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![greet, toggle_devtools]) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/src-tauri/src/utilities.rs b/src-tauri/src/utilities.rs index fe17df26..12ee0391 100644 --- a/src-tauri/src/utilities.rs +++ b/src-tauri/src/utilities.rs @@ -15,7 +15,7 @@ use serde_json::Value; /// /// ``` /// let x = 5; -/// print_type_of(&x); +/// _print_type_of(&x); /// // prints: "i32" /// ``` /// @@ -26,7 +26,7 @@ use serde_json::Value; /// # Errors /// /// This function does not return any errors. -pub fn print_type_of(_: &T) { +pub fn _print_type_of(_: &T) { println!("{}", std::any::type_name::()); } From 7b8bd65ba53f07b6523e2b461ef721eef9cf0e21 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 3 Aug 2023 19:43:32 +0530 Subject: [PATCH 089/864] fix: window restore working --- src-tauri/src/boot_config.rs | 48 ++++++++++++++++++++++++++++++------ src-tauri/src/init.rs | 14 ++++------- src-tauri/src/main.rs | 7 +++--- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src-tauri/src/boot_config.rs b/src-tauri/src/boot_config.rs index cd48ce29..b88d20b4 100644 --- a/src-tauri/src/boot_config.rs +++ b/src-tauri/src/boot_config.rs @@ -1,7 +1,19 @@ +use std::sync::Arc; +use once_cell::sync::OnceCell; use serde_json::Value; +use serde::Serialize; use crate::utilities::read_json_file; use std::path::PathBuf; +use std::fs::File; +use std::io::Write; +pub struct AppConstants { + pub tauri_config : Arc, + pub app_data_dir: std::path::PathBuf +} +pub static APP_CONSTANTS: OnceCell = OnceCell::new(); + +#[derive(Serialize)] pub struct BootConfig { pub last_window_width: u32, pub last_window_height: u32, @@ -25,19 +37,39 @@ fn _set_boot_config(boot_config: &mut BootConfig, value: &Value) { }; } -pub fn read_boot_config(app_data_dir: &PathBuf) -> BootConfig { - let boot_config_file_path = get_boot_config_file_path(app_data_dir); +pub fn read_boot_config() -> BootConfig { let mut boot_config = BootConfig { last_window_width: 0, last_window_height: 0 }; - match read_json_file(&boot_config_file_path) { - Some(value) =>{ - _set_boot_config(&mut boot_config, &value); - } - None => { - eprintln!("No boot restore config file found {}", boot_config_file_path.display()); + if let Some(app_constants) = APP_CONSTANTS.get() { + let boot_config_file_path = get_boot_config_file_path(&app_constants.app_data_dir); + match read_json_file(&boot_config_file_path) { + Some(value) =>{ + _set_boot_config(&mut boot_config, &value); + } + None => { + eprintln!("No boot restore config file found {}", boot_config_file_path.display()); + } } } return boot_config; } + +fn _write_boot_config(boot_config: &BootConfig) { + if let Some(app_constants) = APP_CONSTANTS.get() { + let boot_config_file_path = get_boot_config_file_path(&app_constants.app_data_dir); + // Convert the BootConfig struct to JSON + let json_string = serde_json::to_string(boot_config).unwrap(); + let mut file = File::create(boot_config_file_path).expect("Failed to create file"); + file.write_all(json_string.as_bytes()) + .expect("Failed to write to boot config file"); + } +} + +pub fn write_boot_config(last_window_width: u32, last_window_height: u32) { + _write_boot_config(&BootConfig { + last_window_width, + last_window_height + }) +} \ No newline at end of file diff --git a/src-tauri/src/init.rs b/src-tauri/src/init.rs index 7d3bd354..53be4e1e 100644 --- a/src-tauri/src/init.rs +++ b/src-tauri/src/init.rs @@ -1,21 +1,17 @@ -use std::sync::Arc; -use once_cell::sync::OnceCell; use tauri::Manager; use crate::utilities::ensure_dir_exists; use crate::boot_config::read_boot_config; use crate::boot_config::BootConfig; +use crate::boot_config::APP_CONSTANTS; +use crate::boot_config::AppConstants; -struct AppConstants { - tauri_config : Arc, - app_data_dir: std::path::PathBuf -} -static APP_CONSTANTS: OnceCell = OnceCell::new(); static PREFERRED_WIDTH: u32 = 1366; static PREFERRED_HEIGHT: u32 = 900; static MAXIMIZE_SIZE: u32 = 0; fn get_window_size(last_saved_size: u32, screen_size: u32, preferred_size: u32) -> u32 { - if last_saved_size != 0 && last_saved_size <= screen_size { + if last_saved_size != 0 { + // we dont do last_saved_size Date: Fri, 4 Aug 2023 13:36:01 +0530 Subject: [PATCH 090/864] feat: allow all tauri apis as phcode is a devtool --- src-tauri/Cargo.lock | 548 +++++++++++++++++++++++++++++++++++++- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 7 +- 3 files changed, 546 insertions(+), 11 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 35686328..3c19287e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -71,6 +71,128 @@ version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +[[package]] +name = "async-broadcast" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" +dependencies = [ + "event-listener", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" +dependencies = [ + "async-lock", + "autocfg", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix", + "slab", + "socket2", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-process" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +dependencies = [ + "async-io", + "async-lock", + "autocfg", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix", + "signal-hook", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-recursion" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "async-task" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" + +[[package]] +name = "async-trait" +version = "0.1.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + [[package]] name = "atk" version = "0.15.1" @@ -95,6 +217,12 @@ dependencies = [ "system-deps 6.1.1", ] +[[package]] +name = "atomic-waker" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" + [[package]] name = "autocfg" version = "1.1.0" @@ -149,6 +277,21 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blocking" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", + "log", +] + [[package]] name = "brotli" version = "3.3.4" @@ -349,6 +492,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "concurrent-queue" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -514,6 +666,17 @@ dependencies = [ "syn 2.0.22", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -613,6 +776,27 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enumflags2" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + [[package]] name = "equivalent" version = "1.0.0" @@ -640,6 +824,12 @@ dependencies = [ "libc", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "fastrand" version = "1.9.0" @@ -664,7 +854,7 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ - "memoffset", + "memoffset 0.9.0", "rustc_version", ] @@ -762,6 +952,21 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.28" @@ -1544,6 +1749,19 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" +[[package]] +name = "mac-notification-sys" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abc434554ad0e640d772f7f262aa28e61d485212533d3673abe5f3d1729bd42a" +dependencies = [ + "cc", + "dirs-next", + "objc-foundation", + "objc_id", + "time", +] + [[package]] name = "malloc_buf" version = "0.0.6" @@ -1588,6 +1806,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.9.0" @@ -1682,12 +1909,38 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +[[package]] +name = "nix" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +dependencies = [ + "bitflags", + "cfg-if", + "libc", + "memoffset 0.7.1", + "static_assertions", +] + [[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "notify-rust" +version = "4.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bfa211d18e360f08e36c364308f394b5eb23a6629150690e109a916dc6f610e" +dependencies = [ + "log", + "mac-notification-sys", + "serde", + "tauri-winrt-notification", + "zbus", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1813,6 +2066,16 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "open" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" +dependencies = [ + "pathdiff", + "windows-sys 0.42.0", +] + [[package]] name = "openssl" version = "0.10.55" @@ -1857,6 +2120,27 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "os_info" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +dependencies = [ + "log", + "serde", + "winapi", +] + [[package]] name = "os_pipe" version = "1.1.4" @@ -1898,6 +2182,12 @@ dependencies = [ "system-deps 6.1.1", ] +[[package]] +name = "parking" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1918,9 +2208,15 @@ dependencies = [ "libc", "redox_syscall 0.3.5", "smallvec", - "windows-targets", + "windows-targets 0.48.1", ] +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "percent-encoding" version = "2.3.0" @@ -2063,7 +2359,7 @@ dependencies = [ "base64 0.21.2", "indexmap 1.9.3", "line-wrap", - "quick-xml", + "quick-xml 0.28.2", "serde", "time", ] @@ -2081,6 +2377,22 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2142,6 +2454,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-xml" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11bafc859c6815fbaffbbbf4229ecb767ac913fecb27f9ad4343662e9ef099ea" +dependencies = [ + "memchr", +] + [[package]] name = "quick-xml" version = "0.28.2" @@ -2623,6 +2944,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.7" @@ -2653,6 +2985,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + [[package]] name = "simd-adler32" version = "0.3.5" @@ -2733,6 +3084,12 @@ dependencies = [ "loom", ] +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string_cache" version = "0.8.7" @@ -2787,6 +3144,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sys-locale" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee" +dependencies = [ + "js-sys", + "libc", + "wasm-bindgen", + "web-sys", + "windows-sys 0.45.0", +] + [[package]] name = "system-deps" version = "5.0.0" @@ -2910,8 +3280,11 @@ dependencies = [ "http", "ignore", "minisign-verify", + "notify-rust", "objc", "once_cell", + "open", + "os_info", "os_pipe", "percent-encoding", "rand 0.8.5", @@ -2926,6 +3299,7 @@ dependencies = [ "serialize-to-javascript", "shared_child", "state", + "sys-locale", "tar", "tauri-macros", "tauri-runtime", @@ -3080,6 +3454,16 @@ dependencies = [ "toml 0.7.5", ] +[[package]] +name = "tauri-winrt-notification" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f5bff1d532fead7c43324a0fa33643b8621a47ce2944a633be4cb6c0240898f" +dependencies = [ + "quick-xml 0.23.1", + "windows 0.39.0", +] + [[package]] name = "tempfile" version = "3.6.0" @@ -3356,6 +3740,16 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "uds_windows" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +dependencies = [ + "tempfile", + "winapi", +] + [[package]] name = "unicode-bidi" version = "0.3.13" @@ -3460,6 +3854,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "walkdir" version = "2.3.3" @@ -3729,7 +4129,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -3773,13 +4173,37 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -4043,6 +4467,82 @@ dependencies = [ "libc", ] +[[package]] +name = "xdg-home" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" +dependencies = [ + "nix", + "winapi", +] + +[[package]] +name = "zbus" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "byteorder", + "derivative", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex", + "nix", + "once_cell", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "winapi", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "3.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + [[package]] name = "zip" version = "0.6.6" @@ -4053,3 +4553,41 @@ dependencies = [ "crc32fast", "crossbeam-utils", ] + +[[package]] +name = "zvariant" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c" +dependencies = [ + "byteorder", + "enumflags2", + "libc", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "3.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 09494cd8..3f072228 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,7 +17,7 @@ tauri-build = { version = "1.4.0", features = [] } serde_json = "1.0" once_cell = "1.18.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4.1", features = [ "updater", "shell-sidecar", "fs-all", "window-all", "devtools"] } +tauri = { version = "1.4.1", features = [ "api-all", "updater", "devtools"] } [features] # by default Tauri runs in production mode diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 7f164a5d..713bf6b2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -13,14 +13,11 @@ }, "tauri": { "allowlist": { - "all": false, - "window": { - "all": true - }, + "all": true, "fs": { "all": true, "scope": [ - "$RESOURCE/*" + "**" ] }, "shell": { From b637327fa7ca7e55b68fb2c4e3f8b9bfa92e0364 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 4 Aug 2023 08:12:58 +0000 Subject: [PATCH 091/864] ci: update phcode version to 3.2.6 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b61e8ba6..da5e8f9f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.5", + "version": "3.2.6", "type": "module", "scripts": { "tauri": "tauri", @@ -37,6 +37,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "33f9cc52669a82a66b106c5fa9f9cc89a65b0b06" + "commit": "4f1703cc879584cd8d1adea58e5048306d014d5f" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3f072228..81d6ef68 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.5" +version = "3.2.6" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 713bf6b2..4a7ef68e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code", - "version": "3.2.5" + "version": "3.2.6" }, "tauri": { "allowlist": { From e169fba6ed4e82b89e75651e2f758cfe3f046cee Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 4 Aug 2023 14:56:54 +0530 Subject: [PATCH 092/864] ci: change bundle id based on stage to create different browser webview profiles for stage --- package.json | 2 +- src-build/ci-createDistReleaseConfig.js | 4 ++++ src-build/constants.js | 6 ++++++ src-tauri/Cargo.lock | 2 +- src-tauri/tauri.conf.json | 5 +++-- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index da5e8f9f..9fbf42ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.6", + "version": "3.2.2", "type": "module", "scripts": { "tauri": "tauri", diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index 622a7f50..b1595fbc 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -2,6 +2,7 @@ import {fileURLToPath} from "url"; import {dirname, join} from "path"; import { PRODUCT_NAME_SUFFIX_FOR_STAGE, + BUNDLE_IDENTIFIER_FOR_STAGE, UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH, UPDATE_NOTIFICATIONS_BASE_URL } from "./constants.js"; @@ -75,6 +76,9 @@ async function ciCreateDistReleaseConfig() { configJson.tauri.updater.endpoints = [ `${UPDATE_NOTIFICATIONS_BASE_URL}${UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH[phoenixStage]}` ]; + const bundleIdentifier = BUNDLE_IDENTIFIER_FOR_STAGE[phoenixStage] || "io.phcode.unknown.stage"; + console.log("Product Bundle Identifier is: ", bundleIdentifier); + configJson.tauri.bundle.identifier = bundleIdentifier; console.log("Product update endpoints are: ", configJson.tauri.updater.endpoints); console.log("Writing new dist config json ", tauriConfigPath); fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); diff --git a/src-build/constants.js b/src-build/constants.js index 3d99ca53..ddbd426e 100644 --- a/src-build/constants.js +++ b/src-build/constants.js @@ -6,6 +6,12 @@ export const PRODUCT_NAME_SUFFIX_FOR_STAGE = { production: "" // has no suffix }; +export const BUNDLE_IDENTIFIER_FOR_STAGE = { + dev : "io.phcode.dev", + stage: "io.phcode.staging", + production: "io.phcode" +}; + export const UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH = { // do not change any of these names unless you want to nuke the updater for all the whole installation base!! // or you know what you are doing. diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 3c19287e..ae05625b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2323,7 +2323,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.5" +version = "3.2.6" dependencies = [ "once_cell", "serde", diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4a7ef68e..e3bbdab9 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -50,7 +50,7 @@ "icons/icon.icns", "icons/icon.ico" ], - "identifier": "io.phcode", + "identifier": "io.phcode.dev", "longDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", "macOS": { "entitlements": "../entitlements.plist", @@ -170,7 +170,8 @@ "resizable": true, "title": "Phoenix Code", "width": 1024, - "minWidth": 800 + "minWidth": 800, + "acceptFirstMouse": true } ] } From 1fd93c23f6b1ed1b99c67ddf9e45f7e25795d5a5 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 4 Aug 2023 14:59:07 +0530 Subject: [PATCH 093/864] fix: accidental version bump --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9fbf42ae..da5e8f9f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.2", + "version": "3.2.6", "type": "module", "scripts": { "tauri": "tauri", From 8b3238917c406b9f56075693d7a48fe6cab88734 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 4 Aug 2023 15:49:17 +0530 Subject: [PATCH 094/864] fix: crash on startup in mac and windows --- src-tauri/src/init.rs | 3 ++- src-tauri/tauri.conf.json | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/init.rs b/src-tauri/src/init.rs index 53be4e1e..77b8a9f1 100644 --- a/src-tauri/src/init.rs +++ b/src-tauri/src/init.rs @@ -39,6 +39,8 @@ fn restore_window_size(app: &mut tauri::App, boot_config: &BootConfig){ pub fn init_app(app: &mut tauri::App) { let config = app.config().clone(); + println!("Appdata path is {}", tauri::api::path::app_data_dir(&config).expect("failed to retrieve app_data_dir").display()); + ensure_dir_exists(&tauri::api::path::app_data_dir(&config).unwrap()); // canonicalize will work only if path exists let _ = APP_CONSTANTS.set(AppConstants { tauri_config: config.clone(), app_data_dir: tauri::api::path::app_data_dir(&config).expect("failed to retrieve app_data_dir") @@ -48,7 +50,6 @@ pub fn init_app(app: &mut tauri::App) { // To get a value if let Some(app_constants) = APP_CONSTANTS.get() { println!("Bundle ID is {}", app_constants.tauri_config.tauri.bundle.identifier); - println!("Appdata Dir is {}", app_constants.app_data_dir.display()); ensure_dir_exists(&app_constants.app_data_dir); let boot_config = read_boot_config(); restore_window_size(app, &boot_config); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index e3bbdab9..c27fb429 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ "withGlobalTauri": true }, "package": { - "productName": "Phoenix Code", + "productName": "Phoenix Code Experimental Build", "version": "3.2.6" }, "tauri": { @@ -168,7 +168,7 @@ "height": 768, "minHeight": 600, "resizable": true, - "title": "Phoenix Code", + "title": "Phoenix Code Experimental Build", "width": 1024, "minWidth": 800, "acceptFirstMouse": true From e344dab7d366d32d5b15b2d8e406f6e0ae6cc572 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 4 Aug 2023 18:39:01 +0530 Subject: [PATCH 095/864] fix: fail if download node from npm failed --- src-build/downloadNode.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src-build/downloadNode.js b/src-build/downloadNode.js index be8c68c0..ae4057d1 100644 --- a/src-build/downloadNode.js +++ b/src-build/downloadNode.js @@ -16,7 +16,7 @@ const LTS_URL_PREFIX = 'https://nodejs.org/dist/latest-v18.x/'; /** Fetches the latest Node.js version by making a request to a specified URL. @returns {Promise} A promise that resolves with the latest Node.js version string on success, - or rejects with an error if the latest version cannot be found. + or rejects with an error if the latest version cannot be found. */ async function fetchLatestNodeVersion() { return new Promise((resolve, reject) => { @@ -176,13 +176,19 @@ async function copyLatestNodeForBuild(platform, arch) { const fullPath = (platform === "win") ? `${__dirname}\\${fileName}` : `${__dirname}/${fileName}`; let nodeFolder = ""; - if (platform === "win") { - unzipFile(fullPath, __dirname); - nodeFolder = fileName.slice(0, -4); - } else { - await untarFile(fullPath, __dirname); - nodeFolder = fileName.slice(0, -7); + try { + if (platform === "win") { + unzipFile(fullPath, __dirname); + nodeFolder = fileName.slice(0, -4); + } else { + await untarFile(fullPath, __dirname); + nodeFolder = fileName.slice(0, -7); + } + } catch (e) { + console.error(e); + process.exit(1); } + console.log(nodeFolder); const fullPathUnzipFolder = (platform === "win") ? `${__dirname}\\${nodeFolder}` : `${__dirname}/${nodeFolder}`; const fullPathOfNode = (platform === "win") ? `${__dirname}\\node` : `${__dirname}/node`; From ed21a10495707402052f65282a6aeed22f7c454a Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 11 Aug 2023 13:16:07 +0530 Subject: [PATCH 096/864] chore: use local app data folder instead of app data folder --- package-lock.json | 4 ++-- src-tauri/src/boot_config.rs | 10 +++++----- src-tauri/src/init.rs | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 40506a3d..78edfd15 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.2.3", + "version": "3.2.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.3", + "version": "3.2.6", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.4.0", diff --git a/src-tauri/src/boot_config.rs b/src-tauri/src/boot_config.rs index b88d20b4..1dfa19dc 100644 --- a/src-tauri/src/boot_config.rs +++ b/src-tauri/src/boot_config.rs @@ -9,7 +9,7 @@ use std::io::Write; pub struct AppConstants { pub tauri_config : Arc, - pub app_data_dir: std::path::PathBuf + pub app_local_data_dir: std::path::PathBuf } pub static APP_CONSTANTS: OnceCell = OnceCell::new(); @@ -20,8 +20,8 @@ pub struct BootConfig { } static BOOT_CONFIG_FILE_NAME: &'static str = "boot_config.json"; -fn get_boot_config_file_path(app_data_dir: &PathBuf) -> PathBuf { - let mut config_file_path = app_data_dir.clone(); +fn get_boot_config_file_path(app_local_data_dir: &PathBuf) -> PathBuf { + let mut config_file_path = app_local_data_dir.clone(); config_file_path.push(BOOT_CONFIG_FILE_NAME); return config_file_path; } @@ -43,7 +43,7 @@ pub fn read_boot_config() -> BootConfig { last_window_height: 0 }; if let Some(app_constants) = APP_CONSTANTS.get() { - let boot_config_file_path = get_boot_config_file_path(&app_constants.app_data_dir); + let boot_config_file_path = get_boot_config_file_path(&app_constants.app_local_data_dir); match read_json_file(&boot_config_file_path) { Some(value) =>{ _set_boot_config(&mut boot_config, &value); @@ -58,7 +58,7 @@ pub fn read_boot_config() -> BootConfig { fn _write_boot_config(boot_config: &BootConfig) { if let Some(app_constants) = APP_CONSTANTS.get() { - let boot_config_file_path = get_boot_config_file_path(&app_constants.app_data_dir); + let boot_config_file_path = get_boot_config_file_path(&app_constants.app_local_data_dir); // Convert the BootConfig struct to JSON let json_string = serde_json::to_string(boot_config).unwrap(); let mut file = File::create(boot_config_file_path).expect("Failed to create file"); diff --git a/src-tauri/src/init.rs b/src-tauri/src/init.rs index 77b8a9f1..163d9ace 100644 --- a/src-tauri/src/init.rs +++ b/src-tauri/src/init.rs @@ -39,18 +39,18 @@ fn restore_window_size(app: &mut tauri::App, boot_config: &BootConfig){ pub fn init_app(app: &mut tauri::App) { let config = app.config().clone(); - println!("Appdata path is {}", tauri::api::path::app_data_dir(&config).expect("failed to retrieve app_data_dir").display()); - ensure_dir_exists(&tauri::api::path::app_data_dir(&config).unwrap()); // canonicalize will work only if path exists + println!("Appdata path is {}", tauri::api::path::app_local_data_dir(&config).expect("failed to retrieve app_local_data_dir").display()); + ensure_dir_exists(&tauri::api::path::app_local_data_dir(&config).unwrap()); // canonicalize will work only if path exists let _ = APP_CONSTANTS.set(AppConstants { tauri_config: config.clone(), - app_data_dir: tauri::api::path::app_data_dir(&config).expect("failed to retrieve app_data_dir") - .canonicalize().expect("Failed to canonicalize app_data_dir") + app_local_data_dir: tauri::api::path::app_local_data_dir(&config).expect("failed to retrieve app_local_data_dir") + .canonicalize().expect("Failed to canonicalize app_local_data_dir") }); // To get a value if let Some(app_constants) = APP_CONSTANTS.get() { println!("Bundle ID is {}", app_constants.tauri_config.tauri.bundle.identifier); - ensure_dir_exists(&app_constants.app_data_dir); + ensure_dir_exists(&app_constants.app_local_data_dir); let boot_config = read_boot_config(); restore_window_size(app, &boot_config); } From 39a191fca959a0e28d9272047d6be981f116f1c3 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 4 Oct 2023 20:52:17 +0530 Subject: [PATCH 097/864] feat: node integration first draft --- .gitignore | 1 + package-lock.json | 1224 +++++++++++++++++ package.json | 32 +- .../{cleanNode.js => cleanNodeBinary.js} | 16 +- ...{downloadNode.js => downloadNodeBinary.js} | 0 src-tauri/Cargo.lock | 14 + src-tauri/Cargo.toml | 2 + src-tauri/src/main.rs | 35 +- src-tauri/src/platform.rs | 43 + src-tauri/tauri.conf.json | 73 +- 10 files changed, 1401 insertions(+), 39 deletions(-) rename src-build/{cleanNode.js => cleanNodeBinary.js} (61%) rename src-build/{downloadNode.js => downloadNodeBinary.js} (100%) create mode 100644 src-tauri/src/platform.rs diff --git a/.gitignore b/.gitignore index b0057347..6ac2d84e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ lerna-debug.log* node-bins src-build/node-* src-tauri/node-* +src-tauri/src-node src-build/phnode-* src-tauri/phnode-* src-tauri/tauri-local.conf.json diff --git a/package-lock.json b/package-lock.json index 78edfd15..b5a76dbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,8 +11,10 @@ "devDependencies": { "@tauri-apps/cli": "1.4.0", "adm-zip": "0.5.10", + "chokidar-cli": "^3.0.0", "execa": "^7.1.1", "fs-extra": "11.1.1", + "shx": "^0.3.4", "tar": "6.1.15" } }, @@ -213,6 +215,131 @@ "node": ">=6.0" } }, + "node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar-cli": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz", + "integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "yargs": "^13.3.0" + }, + "bin": { + "chokidar": "index.js" + }, + "engines": { + "node": ">= 8.10.0" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -222,6 +349,38 @@ "node": ">=10" } }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -236,6 +395,21 @@ "node": ">= 8" } }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "node_modules/execa": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", @@ -259,6 +433,30 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/fs-extra": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", @@ -297,6 +495,35 @@ "node": ">=8" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -309,12 +536,53 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "node_modules/has": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/human-signals": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", @@ -324,6 +592,94 @@ "node": ">=14.18.0" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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, + "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, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -354,6 +710,31 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "dev": true + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -372,6 +753,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -418,6 +820,15 @@ "node": ">=10" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-path": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", @@ -445,6 +856,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, "node_modules/onetime": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", @@ -460,6 +880,60 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -469,6 +943,86 @@ "node": ">=8" } }, + "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 + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "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/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -490,12 +1044,71 @@ "node": ">=8" } }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/shx": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", + "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==", + "dev": true, + "dependencies": { + "minimist": "^1.2.3", + "shelljs": "^0.8.5" + }, + "bin": { + "shx": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "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 }, + "node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -508,6 +1121,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/tar": { "version": "6.1.15", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", @@ -525,6 +1150,18 @@ "node": ">=10" } }, + "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, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -549,11 +1186,71 @@ "node": ">= 8" } }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } }, "dependencies": { @@ -651,12 +1348,134 @@ "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", "dev": true }, + "ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chokidar-cli": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz", + "integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==", + "dev": true, + "requires": { + "chokidar": "^3.5.2", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "yargs": "^13.3.0" + } + }, "chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -668,6 +1487,18 @@ "which": "^2.0.1" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "execa": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", @@ -685,6 +1516,24 @@ "strip-final-newline": "^3.0.0" } }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, "fs-extra": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", @@ -716,24 +1565,139 @@ } } }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, "get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "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, + "requires": { + "is-glob": "^4.0.1" + } + }, "graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "has": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "dev": true + }, "human-signals": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", "dev": true }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true + }, + "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, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "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 + }, "is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -756,6 +1720,28 @@ "universalify": "^2.0.0" } }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "dev": true + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -768,6 +1754,21 @@ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, "minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -801,6 +1802,12 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, "npm-run-path": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", @@ -818,6 +1825,15 @@ } } }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, "onetime": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", @@ -827,12 +1843,107 @@ "mimic-fn": "^4.0.0" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, + "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 + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "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, + "requires": { + "resolve": "^1.1.6" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "resolve": { + "version": "1.22.6", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", + "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -848,18 +1959,65 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dev": true, + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, + "shx": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", + "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==", + "dev": true, + "requires": { + "minimist": "^1.2.3", + "shelljs": "^0.8.5" + } + }, "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 }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, "strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true }, + "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 + }, "tar": { "version": "6.1.15", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", @@ -874,6 +2032,15 @@ "yallist": "^4.0.0" } }, + "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, + "requires": { + "is-number": "^7.0.0" + } + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -889,11 +2056,68 @@ "isexe": "^2.0.0" } }, + "which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } } diff --git a/package.json b/package.json index da5e8f9f..4a554cf9 100644 --- a/package.json +++ b/package.json @@ -10,28 +10,34 @@ "_createDistReleaseConfig": "node src-build/createDistReleaseConfig.js", "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", - "releaseSrc": "npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseSrcDebug": "npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", - "releaseDist": "npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseDistDebug": "npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseSrc": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseSrcDebug": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseDist": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseDistDebug": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "_src-node_npm_install": "cd src-tauri/src-node && npm install --production && cd ../../", + "_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r ../phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", + "_make_src-node_debug_dev": "npm run _make_src-node && shx rm -rf src-tauri/target/debug/src-node && shx cp -r src-tauri/src-node src-tauri/target/debug/src-node", + "_ci_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", "_servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm install && npm run build && cd ..", - "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig", - "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig", - "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig", + "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", + "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", + "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", "_ci-update-phcode-build": "node src-build/update-phcode-build.js", - "serve": "npm run _servePhoenix && tauri dev", - "postinstall": "node ./src-build/downloadNode.js", - "cleanNode": "node src-build/cleanNode.js", - "preinstallNodeArmDarwin": "npm run cleanNode", - "installNodeArmDarwin": "node ./src-build/downloadNode.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", + "_watch_src-node": "chokidar '../phoenix/src-node/**/*' --ignore '../phoenix/src-node/node_modules/**/*' -c 'npm run _make_src-node_debug_dev'", + "serve": "npm run _servePhoenix && npm run _make_src-node && tauri dev", + "postinstall": "node ./src-build/downloadNodeBinary.js", + "cleanNodeBinary": "node src-build/cleanNodeBinary.js", + "installNodeArmDarwin": "node ./src-build/downloadNodeBinary.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { "@tauri-apps/cli": "1.4.0", "adm-zip": "0.5.10", + "chokidar-cli": "^3.0.0", "execa": "^7.1.1", "fs-extra": "11.1.1", + "shx": "^0.3.4", "tar": "6.1.15" }, "phoenixRepo": { @@ -39,4 +45,4 @@ "branch": "tauri", "commit": "4f1703cc879584cd8d1adea58e5048306d014d5f" } -} \ No newline at end of file +} diff --git a/src-build/cleanNode.js b/src-build/cleanNodeBinary.js similarity index 61% rename from src-build/cleanNode.js rename to src-build/cleanNodeBinary.js index f8e4caf5..f6aaa217 100644 --- a/src-build/cleanNode.js +++ b/src-build/cleanNodeBinary.js @@ -6,22 +6,26 @@ import {removeDir, listFilesAndFolders, getPlatformDetails} from "./utils.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -async function cleanNode() { +async function cleanNodeBinary() { + const platform = getPlatformDetails().platform; console.log('cleaning current node used by phcode from workspace'); - const listOfNodeFolders = await listFilesAndFolders(__dirname, "node"); + + const tauriBuildScriptsFolderNode = (platform === "win") ? `${__dirname}\\..\\src-build` + : `${__dirname}/../src-build`; + const listOfNodeFolders = await listFilesAndFolders(tauriBuildScriptsFolderNode, "node-"); + console.log("remove all node*", listOfNodeFolders); for (let files of listOfNodeFolders) { await removeDir(files); } - const platform = getPlatformDetails().platform; const tauriDestFolderNode = (platform === "win") ? `${__dirname}\\..\\src-tauri` : `${__dirname}/../src-tauri`; - const listOfNodeFoldersToDelete = await listFilesAndFolders(tauriDestFolderNode,"node-"); - console.log(listOfNodeFoldersToDelete); + const listOfNodeFoldersToDelete = await listFilesAndFolders(tauriDestFolderNode,"phnode-"); + console.log("removing all src-tauri/phnode-*", listOfNodeFoldersToDelete); for (let files of listOfNodeFoldersToDelete) { await removeDir(files); } } -await cleanNode(); +await cleanNodeBinary(); diff --git a/src-build/downloadNode.js b/src-build/downloadNodeBinary.js similarity index 100% rename from src-build/downloadNode.js rename to src-build/downloadNodeBinary.js diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ae05625b..06e54a7a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2330,6 +2330,8 @@ dependencies = [ "serde_json", "tauri", "tauri-build", + "tauri-plugin-fs-extra", + "winapi", ] [[package]] @@ -3374,6 +3376,18 @@ dependencies = [ "tauri-utils", ] +[[package]] +name = "tauri-plugin-fs-extra" +version = "0.0.0" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#5b814f56e6368fdec46c4ddb04a07e0923ff995a" +dependencies = [ + "log", + "serde", + "serde_json", + "tauri", + "thiserror", +] + [[package]] name = "tauri-runtime" version = "0.14.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 81d6ef68..b8c75018 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -18,6 +18,8 @@ serde_json = "1.0" once_cell = "1.18.0" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.4.1", features = [ "api-all", "updater", "devtools"] } +winapi = { version = "0.3", features = ["fileapi"] } +tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } [features] # by default Tauri runs in production mode diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 73a8e069..be4638fd 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -9,19 +9,27 @@ mod init; mod utilities; mod boot_config; +mod platform; + // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command #[tauri::command] -fn greet(handle: tauri::AppHandle, name: &str) -> String { - let resource_path = handle.path_resolver() - .resolve_resource("app/hello.js") - .expect("failed to resolve resource"); - Command::new_sidecar("phnode") - .expect("failed to create `my-sidecar` binary command") - .args(resource_path.as_path().to_str()) - .spawn() - .expect("Failed to spawn sidecar"); - println!("hello"); - format!("Hello, {}! You've been greeted from Rust!", name) +fn console_log(_handle: tauri::AppHandle, message: &str) { + println!("{}", message); +} + +#[tauri::command] +fn console_error(_handle: tauri::AppHandle, message: &str) { + eprintln!("{}", message); +} + +#[tauri::command] +fn _get_windows_drives() -> Option> { + platform::get_windows_drives() +} + +#[tauri::command] +fn _rename_path(old_path: &str, new_path: &str) -> Result<(), String> { + platform::rename_path(old_path, new_path) } static mut DEVTOOLS_LOADED:bool = false; @@ -49,8 +57,11 @@ fn process_window_event(event: &GlobalWindowEvent) { fn main() { tauri::Builder::default() + .plugin(tauri_plugin_fs_extra::init()) .on_window_event(|event| process_window_event(&event)) - .invoke_handler(tauri::generate_handler![greet, toggle_devtools]) + .invoke_handler(tauri::generate_handler![ + toggle_devtools, console_log, console_error, + _get_windows_drives, _rename_path]) .setup(|app| { init::init_app(app); Ok(()) diff --git a/src-tauri/src/platform.rs b/src-tauri/src/platform.rs new file mode 100644 index 00000000..c8b1ac88 --- /dev/null +++ b/src-tauri/src/platform.rs @@ -0,0 +1,43 @@ +// platform.rs +// IMPORTANT!!!: Editing this file is a Major version change + +#[cfg(target_os = "windows")] +extern crate winapi; +use std::fs; + +#[cfg(target_os = "windows")] +use winapi::um::fileapi::GetLogicalDriveStringsW; + +pub fn get_windows_drives() -> Option> { + #[cfg(target_os = "windows")] { + let mut buffer: [u16; 1024] = [0; 1024]; + + unsafe { + let res = GetLogicalDriveStringsW(1024, buffer.as_mut_ptr()); + if res == 0 { + return None; + } + + let drives: Vec = buffer + .chunks(4) // Each drive letter representation is 4 bytes (letter, colon, slash, null terminator) + .filter_map(|chunk| { + if chunk[0] != 0 { + Some(chunk[0] as u8 as char) + } else { + None + } + }) + .collect(); + + Some(drives) + } + } + + #[cfg(not(target_os = "windows"))] { + None + } +} + +pub fn rename_path(old_path: &str, new_path: &str) -> Result<(), String> { + fs::rename(old_path, new_path).map_err(|e| e.to_string()) +} \ No newline at end of file diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c27fb429..ecbd3949 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -2,7 +2,7 @@ "$schema": "../node_modules/@tauri-apps/cli/schema.json", "build": { "beforeBuildCommand": "", - "beforeDevCommand": "", + "beforeDevCommand": "npm run _watch_src-node", "devPath": "http://localhost:8000/src/", "distDir": "../src/", "withGlobalTauri": true @@ -17,15 +17,72 @@ "fs": { "all": true, "scope": [ - "**" + "$APPCONFIG/**", + "$APPDATA/**", + "$APPLOCALDATA/**", + "$APPCACHE/**", + "$APPLOG/**", + "$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/**/*.*", + "$AUDIO/**/*.*", + "$CACHE/**/*.*", + "$CONFIG/**/*.*", + "$DATA/**/*.*", + "$LOCALDATA/**/*.*", + "$DESKTOP/**/*.*", + "$DOCUMENT/**/*.*", + "$DOWNLOAD/**/*.*", + "$EXE/**/*.*", + "$FONT/**/*.*", + "$HOME/**/*.*", + "$PICTURE/**/*.*", + "$PUBLIC/**/*.*", + "$RUNTIME/**/*.*", + "$TEMPLATE/**/*.*", + "$VIDEO/**/*.*", + "$RESOURCE/**/*.*", + "$APP/**/*.*", + "$LOG/**/*.*", + "$TEMP/**/*.*", + "**/*.*", + "**/**/*.*" ] }, "shell": { + "all": true, + "execute": true, "sidecar": true, + "open": true, "scope": [ { "name": "phnode", - "sidecar": true + "sidecar": true, + "args": [{ "validator": "\\S*" }, { "validator": "\\S*" }] } ] } @@ -38,10 +95,10 @@ "depends": [] }, "appimage": { - "bundleMediaFramework": true + "bundleMediaFramework": false }, "externalBin": [ - "./phnode" + "phnode" ], "icon": [ "icons/32x32.png", @@ -60,7 +117,7 @@ "signingIdentity": null }, "resources": [ - "app/*" + "src-node/*" ], "shortDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", "targets": [ @@ -165,11 +222,11 @@ "windows": [ { "fullscreen": false, - "height": 768, + "height": 900, "minHeight": 600, "resizable": true, "title": "Phoenix Code Experimental Build", - "width": 1024, + "width": 1366, "minWidth": 800, "acceptFirstMouse": true } From 19ac51d86730e578aeebb2a2ca05927cdd61df6e Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 5 Oct 2023 11:01:37 +0530 Subject: [PATCH 098/864] build: change npm run releaseSrc and releaseDist command to not build installers due to hand issues on installer gen --- src-build/createDistReleaseConfig.js | 4 ++-- src-build/createSrcReleaseConfig.js | 4 ++-- src-tauri/src/main.rs | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index 7a32c088..411824f4 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -15,8 +15,8 @@ async function createDistReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - delete configJson.tauri.updater; - delete configJson.tauri.bundle.windows.certificateThumbprint; + console.log('\x1b[34m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") + configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist/' console.log("Writing new local config json ", tauriLocalConfigPath); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index ff2ef1da..a887392a 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -15,8 +15,8 @@ async function createSrcReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - delete configJson.tauri.updater; - delete configJson.tauri.bundle.windows.certificateThumbprint; + console.log('\x1b[34m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") + configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/src/' console.log("Writing new local config json ", tauriLocalConfigPath); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index be4638fd..1d5c9885 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,7 +3,6 @@ all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows" )] -use tauri::api::process::Command; use tauri::GlobalWindowEvent; mod init; mod utilities; From a648e9a145425bc08e0a045d2b1ea26fb814efb5 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 5 Oct 2023 13:10:12 +0530 Subject: [PATCH 099/864] build: create releaseDistTest target to build phoenix tester bins --- package.json | 3 + src-build/createDistTestReleaseConfig.js | 25 +++++++++ src-tauri/Cargo.lock | 70 +++++++++++++++++++++++- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 11 ++++ 5 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 src-build/createDistTestReleaseConfig.js diff --git a/package.json b/package.json index 4a554cf9..98e539ad 100644 --- a/package.json +++ b/package.json @@ -8,12 +8,15 @@ "build": "", "_createSrcReleaseConfig": "node src-build/createSrcReleaseConfig.js", "_createDistReleaseConfig": "node src-build/createDistReleaseConfig.js", + "_createDistTestReleaseConfig": "node src-build/createDistTestReleaseConfig.js", "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", "releaseSrc": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseSrcDebug": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "releaseDist": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistDebug": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", + "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "_src-node_npm_install": "cd src-tauri/src-node && npm install --production && cd ../../", "_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r ../phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", "_make_src-node_debug_dev": "npm run _make_src-node && shx rm -rf src-tauri/target/debug/src-node && shx cp -r src-tauri/src-node src-tauri/target/debug/src-node", diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js new file mode 100644 index 00000000..149338db --- /dev/null +++ b/src-build/createDistTestReleaseConfig.js @@ -0,0 +1,25 @@ +import {fileURLToPath} from "url"; +import {dirname} from "path"; +import fs from 'fs'; + +import {getPlatformDetails} from "./utils.js"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +async function createDistTestReleaseConfig() { + const platform = getPlatformDetails().platform; + const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` + : `${__dirname}/../src-tauri/tauri.conf.json`; + const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` + : `${__dirname}/../src-tauri/tauri-local.conf.json`; + console.log("Reading config file: ", tauriConfigPath); + let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + console.log('\x1b[34m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") + configJson.tauri.bundle.active = false; + configJson.build.distDir = '../../phoenix/dist-test/' + console.log("Writing new local config json ", tauriLocalConfigPath); + fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); +} + +await createDistTestReleaseConfig(); diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 06e54a7a..0bd2c5dd 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -223,6 +223,17 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -445,6 +456,30 @@ dependencies = [ "winapi", ] +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags", + "clap_lex", + "indexmap 1.9.3", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "cocoa" version = "0.24.1" @@ -1359,6 +1394,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.3.1" @@ -1586,7 +1630,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.1", "libc", "windows-sys 0.48.0", ] @@ -1987,7 +2031,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.1", "libc", ] @@ -2151,6 +2195,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "os_str_bytes" +version = "6.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" + [[package]] name = "overload" version = "0.1.1" @@ -3269,6 +3319,7 @@ dependencies = [ "anyhow", "base64 0.21.2", "bytes", + "clap", "cocoa", "dirs-next", "embed_plist", @@ -3503,6 +3554,21 @@ dependencies = [ "utf-8", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + [[package]] name = "thin-slice" version = "0.1.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b8c75018..e667802b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,7 +17,7 @@ tauri-build = { version = "1.4.0", features = [] } serde_json = "1.0" once_cell = "1.18.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4.1", features = [ "api-all", "updater", "devtools"] } +tauri = { version = "1.4.1", features = [ "cli", "api-all", "updater", "devtools"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ecbd3949..1a8d00b6 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -87,6 +87,17 @@ ] } }, + "cli": { + "description": "Phoenix Code cli", + "longDescription": "CLI to open project, run tests amd other things", + "beforeHelp": "", + "afterHelp": "", + "args": [{ + "name": "quit-when-done", + "description": "Quit after whatever the task assigned from CLI is done.", + "short": "q" + }] + }, "bundle": { "active": true, "category": "DeveloperTool", From 950c84c5c350ebf526a609ec41e0b16658263a8a Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 5 Oct 2023 17:29:07 +0530 Subject: [PATCH 100/864] build: add CLI to run tests like './phcode --run-tests unit' --- src-tauri/tauri.conf.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1a8d00b6..234edba3 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -96,6 +96,10 @@ "name": "quit-when-done", "description": "Quit after whatever the task assigned from CLI is done.", "short": "q" + }, { + "name": "run-tests", + "description": "run all tests in the given category", + "takesValue": true }] }, "bundle": { From 994441b487192b3a224bf9197a2f9b6cb6f48c11 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 6 Oct 2023 12:14:07 +0530 Subject: [PATCH 101/864] build: change test runner bin name to phoenix-test --- src-build/createDistTestReleaseConfig.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index 149338db..6f86f2d2 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -15,6 +15,8 @@ async function createDistTestReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + configJson.package.productName = "phoenix-test"; + configJson.tauri.windows[0].title = "phoenix-tester"; console.log('\x1b[34m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist-test/' From b4fe868a6ed8d528afe853138f7c0feb1616a1f9 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 6 Oct 2023 16:08:47 +0530 Subject: [PATCH 102/864] build: color purple for some info messages --- src-build/createDistReleaseConfig.js | 2 +- src-build/createDistTestReleaseConfig.js | 2 +- src-build/createSrcReleaseConfig.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index 411824f4..a6b43486 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -15,7 +15,7 @@ async function createDistReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log('\x1b[34m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") + console.log('\x1b[35m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist/' console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index 6f86f2d2..7d4a429c 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -17,7 +17,7 @@ async function createDistTestReleaseConfig() { let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); configJson.package.productName = "phoenix-test"; configJson.tauri.windows[0].title = "phoenix-tester"; - console.log('\x1b[34m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") + console.log('\x1b[35m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist-test/' console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index a887392a..11fb8dd5 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -15,7 +15,7 @@ async function createSrcReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log('\x1b[34m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") + console.log('\x1b[35m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/src/' console.log("Writing new local config json ", tauriLocalConfigPath); From 10b314332bf89175816a164d73c7e7d6d5815b3e Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 6 Oct 2023 16:14:41 +0530 Subject: [PATCH 103/864] build: color purple for some info messages --- package-lock.json | 19 +++++++++++++++++++ package.json | 1 + src-build/createDistReleaseConfig.js | 3 ++- src-build/createDistTestReleaseConfig.js | 3 ++- src-build/createSrcReleaseConfig.js | 3 ++- 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index b5a76dbd..da2bccbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.4.0", "adm-zip": "0.5.10", + "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^7.1.1", "fs-extra": "11.1.1", @@ -295,6 +296,18 @@ "node": ">=6" } }, + "node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1410,6 +1423,12 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true + }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", diff --git a/package.json b/package.json index 98e539ad..ee904de4 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "devDependencies": { "@tauri-apps/cli": "1.4.0", "adm-zip": "0.5.10", + "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^7.1.1", "fs-extra": "11.1.1", diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index a6b43486..7b769e10 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -1,6 +1,7 @@ import {fileURLToPath} from "url"; import {dirname} from "path"; import fs from 'fs'; +import chalk from 'chalk'; import {getPlatformDetails} from "./utils.js"; @@ -15,7 +16,7 @@ async function createDistReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log('\x1b[35m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") + console.log(chalk.magenta("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist/' console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index 7d4a429c..0e3d1dbd 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -3,6 +3,7 @@ import {dirname} from "path"; import fs from 'fs'; import {getPlatformDetails} from "./utils.js"; +import chalk from "chalk"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -17,7 +18,7 @@ async function createDistTestReleaseConfig() { let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); configJson.package.productName = "phoenix-test"; configJson.tauri.windows[0].title = "phoenix-tester"; - console.log('\x1b[35m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") + console.log(chalk.magenta("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist-test/' console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index 11fb8dd5..35c0db3f 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -3,6 +3,7 @@ import {dirname} from "path"; import fs from 'fs'; import {getPlatformDetails} from "./utils.js"; +import chalk from "chalk"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -15,7 +16,7 @@ async function createSrcReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log('\x1b[35m%s\x1b[0m', "\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n") + console.log(chalk.magenta("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/src/' console.log("Writing new local config json ", tauriLocalConfigPath); From 0d0bcd06ac46fe99c9edae7198cc6c16a3f91c7c Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 6 Oct 2023 16:26:57 +0530 Subject: [PATCH 104/864] build: color change to cyan as magenta is not supported in powershell --- src-build/createDistReleaseConfig.js | 2 +- src-build/createDistTestReleaseConfig.js | 2 +- src-build/createSrcReleaseConfig.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index 7b769e10..9a53aba2 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -16,7 +16,7 @@ async function createDistReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log(chalk.magenta("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); + console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist/' console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index 0e3d1dbd..da7d7895 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -18,7 +18,7 @@ async function createDistTestReleaseConfig() { let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); configJson.package.productName = "phoenix-test"; configJson.tauri.windows[0].title = "phoenix-tester"; - console.log(chalk.magenta("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); + console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist-test/' console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index 35c0db3f..8f916c0b 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -16,7 +16,7 @@ async function createSrcReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log(chalk.magenta("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); + console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/src/' console.log("Writing new local config json ", tauriLocalConfigPath); From 388c880f7bdf36a12064f05f277cd3f5ee6848a0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:19:47 +0000 Subject: [PATCH 105/864] chore(deps): update tauri monorepo --- package-lock.json | 174 +++++++++++++++++++++---------------------- package.json | 2 +- src-tauri/Cargo.lock | 104 +++++++++++++++++++------- src-tauri/Cargo.toml | 4 +- 4 files changed, 169 insertions(+), 115 deletions(-) diff --git a/package-lock.json b/package-lock.json index da2bccbf..3b99ffa1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.2.6", "hasInstallScript": true, "devDependencies": { - "@tauri-apps/cli": "1.4.0", + "@tauri-apps/cli": "1.5.1", "adm-zip": "0.5.10", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -20,9 +20,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.4.0.tgz", - "integrity": "sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.1.tgz", + "integrity": "sha512-Ssj30axil5vPBV3W5ScHXk4umTKu6BhfmMdljfKDOG9K55gAqzBAE2VBC5e/ouclSxZfN+6YNL9VhDXFu/UyeA==", "dev": true, "bin": { "tauri": "tauri.js" @@ -35,22 +35,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.4.0", - "@tauri-apps/cli-darwin-x64": "1.4.0", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.4.0", - "@tauri-apps/cli-linux-arm64-gnu": "1.4.0", - "@tauri-apps/cli-linux-arm64-musl": "1.4.0", - "@tauri-apps/cli-linux-x64-gnu": "1.4.0", - "@tauri-apps/cli-linux-x64-musl": "1.4.0", - "@tauri-apps/cli-win32-arm64-msvc": "1.4.0", - "@tauri-apps/cli-win32-ia32-msvc": "1.4.0", - "@tauri-apps/cli-win32-x64-msvc": "1.4.0" + "@tauri-apps/cli-darwin-arm64": "1.5.1", + "@tauri-apps/cli-darwin-x64": "1.5.1", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.1", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.1", + "@tauri-apps/cli-linux-arm64-musl": "1.5.1", + "@tauri-apps/cli-linux-x64-gnu": "1.5.1", + "@tauri-apps/cli-linux-x64-musl": "1.5.1", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.1", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.1", + "@tauri-apps/cli-win32-x64-msvc": "1.5.1" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.4.0.tgz", - "integrity": "sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.1.tgz", + "integrity": "sha512-o2FSGj72gqJjlVtuScXQZUgiRs90PS9gG7YAz0Hgr4nV1MfIn9U6JVj6R+mnAEZBCK8qdy5jdemhmNKDDoiYQg==", "cpu": [ "arm64" ], @@ -64,9 +64,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.4.0.tgz", - "integrity": "sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.1.tgz", + "integrity": "sha512-G1/v6AJPP5oIcjsOxZshag28wdmDx1Fis2yz545aUk7oKU86A3ZJpz0b8BaXkr93w04xGcmGAaspZeXMmTvrbw==", "cpu": [ "x64" ], @@ -80,9 +80,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.4.0.tgz", - "integrity": "sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.1.tgz", + "integrity": "sha512-hPDOUMviffyX5BySk6RuD7IZZeMuNUJzKWHxVWa0NHJPfxQOIPWwYWbk6TascrVk9GZYAImcB0yKfrll8I0VTg==", "cpu": [ "arm" ], @@ -96,9 +96,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.4.0.tgz", - "integrity": "sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.1.tgz", + "integrity": "sha512-EJjTXqZchFLVrFgfxwstrQj7NwVDirffLhw5hRWS3L3Iys3IvqzIMVIA+GrY7KsaPwq7qaSqE1CDtP1wejE/9g==", "cpu": [ "arm64" ], @@ -112,9 +112,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.4.0.tgz", - "integrity": "sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.1.tgz", + "integrity": "sha512-XgJIk0AcxRL4pWVjfj0wiC9WnIZoUIVLPcQs86dNxoqzwAvADdNYp+McXf3/MDxX8uGEzpgdvlqr4T+50c8f6w==", "cpu": [ "arm64" ], @@ -128,9 +128,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.4.0.tgz", - "integrity": "sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-VoVrIn7b+F2n0LJoDkLGXQJsPV/U1h3QnjRNE+Tcju6xVPBx64H0vfb7lC3S4QfVpiQ4Uc+1UD3Slvn4jGpL/A==", "cpu": [ "x64" ], @@ -144,9 +144,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.4.0.tgz", - "integrity": "sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.1.tgz", + "integrity": "sha512-tQi2K0LYW80BLud7ZFOy3WxCM2VjDRxuhxOYhtcLG39cIeGqsSz07LwiCFNBn4vy2J47TnZ+8XDRAOtxSFe25w==", "cpu": [ "x64" ], @@ -160,9 +160,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.4.0.tgz", - "integrity": "sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.1.tgz", + "integrity": "sha512-BdVwzVXY2JWBtWEO/G0//jIWXeWR52+KG0+kyoHO6QTxkncLrN5q2RldvXOe7CvhKe/qmgbkNosj5jWi7t49kQ==", "cpu": [ "arm64" ], @@ -176,9 +176,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.4.0.tgz", - "integrity": "sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.1.tgz", + "integrity": "sha512-Q0ei4ZUHlGu/b4DP4Cm6WnI5zxpLxnf/vSwR2BYO3XO65TdLee1gTyuwYuSZJYu5jxqSoSusmLyL4F43jHhf9Q==", "cpu": [ "ia32" ], @@ -192,9 +192,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.4.0.tgz", - "integrity": "sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.1.tgz", + "integrity": "sha512-chpsJ5PIwMOdn1IIJ6bj2G7jv9jQryVvhujU0k3kt/5kE7OuLRDYbI5BAIzMOaLoOTgoo8oxcFXQ+enELSxlMQ==", "cpu": [ "x64" ], @@ -1268,90 +1268,90 @@ }, "dependencies": { "@tauri-apps/cli": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.4.0.tgz", - "integrity": "sha512-VXYr2i2iVFl98etQSQsqLzXgX96bnWiNZd1YADgatqwy/qecbd6Kl5ZAPB5R4ynsgE8A1gU7Fbzh7dCEQYFfmA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.1.tgz", + "integrity": "sha512-Ssj30axil5vPBV3W5ScHXk4umTKu6BhfmMdljfKDOG9K55gAqzBAE2VBC5e/ouclSxZfN+6YNL9VhDXFu/UyeA==", "dev": true, "requires": { - "@tauri-apps/cli-darwin-arm64": "1.4.0", - "@tauri-apps/cli-darwin-x64": "1.4.0", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.4.0", - "@tauri-apps/cli-linux-arm64-gnu": "1.4.0", - "@tauri-apps/cli-linux-arm64-musl": "1.4.0", - "@tauri-apps/cli-linux-x64-gnu": "1.4.0", - "@tauri-apps/cli-linux-x64-musl": "1.4.0", - "@tauri-apps/cli-win32-arm64-msvc": "1.4.0", - "@tauri-apps/cli-win32-ia32-msvc": "1.4.0", - "@tauri-apps/cli-win32-x64-msvc": "1.4.0" + "@tauri-apps/cli-darwin-arm64": "1.5.1", + "@tauri-apps/cli-darwin-x64": "1.5.1", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.1", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.1", + "@tauri-apps/cli-linux-arm64-musl": "1.5.1", + "@tauri-apps/cli-linux-x64-gnu": "1.5.1", + "@tauri-apps/cli-linux-x64-musl": "1.5.1", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.1", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.1", + "@tauri-apps/cli-win32-x64-msvc": "1.5.1" } }, "@tauri-apps/cli-darwin-arm64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.4.0.tgz", - "integrity": "sha512-nA/ml0SfUt6/CYLVbHmT500Y+ijqsuv5+s9EBnVXYSLVg9kbPUZJJHluEYK+xKuOj6xzyuT/+rZFMRapmJD3jQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.1.tgz", + "integrity": "sha512-o2FSGj72gqJjlVtuScXQZUgiRs90PS9gG7YAz0Hgr4nV1MfIn9U6JVj6R+mnAEZBCK8qdy5jdemhmNKDDoiYQg==", "dev": true, "optional": true }, "@tauri-apps/cli-darwin-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.4.0.tgz", - "integrity": "sha512-ov/F6Zr+dg9B0PtRu65stFo2G0ow2TUlneqYYrkj+vA3n+moWDHfVty0raDjMLQbQt3rv3uayFMXGPMgble9OA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.1.tgz", + "integrity": "sha512-G1/v6AJPP5oIcjsOxZshag28wdmDx1Fis2yz545aUk7oKU86A3ZJpz0b8BaXkr93w04xGcmGAaspZeXMmTvrbw==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.4.0.tgz", - "integrity": "sha512-zwjbiMncycXDV7doovymyKD7sCg53ouAmfgpUqEBOTY3vgBi9TwijyPhJOqoG5vUVWhouNBC08akGmE4dja15g==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.1.tgz", + "integrity": "sha512-hPDOUMviffyX5BySk6RuD7IZZeMuNUJzKWHxVWa0NHJPfxQOIPWwYWbk6TascrVk9GZYAImcB0yKfrll8I0VTg==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.4.0.tgz", - "integrity": "sha512-5MCBcziqXC72mMXnkZU68mutXIR6zavDxopArE2gQtK841IlE06bIgtLi0kUUhlFJk2nhPRgiDgdLbrPlyt7fw==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.1.tgz", + "integrity": "sha512-EJjTXqZchFLVrFgfxwstrQj7NwVDirffLhw5hRWS3L3Iys3IvqzIMVIA+GrY7KsaPwq7qaSqE1CDtP1wejE/9g==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.4.0.tgz", - "integrity": "sha512-7J3pRB6n6uNYgIfCeKt2Oz8J7oSaz2s8GGFRRH2HPxuTHrBNCinzVYm68UhVpJrL3bnGkU0ziVZLsW/iaOGfUg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.1.tgz", + "integrity": "sha512-XgJIk0AcxRL4pWVjfj0wiC9WnIZoUIVLPcQs86dNxoqzwAvADdNYp+McXf3/MDxX8uGEzpgdvlqr4T+50c8f6w==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-gnu": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.4.0.tgz", - "integrity": "sha512-Zh5gfAJxOv5AVWxcwuueaQ2vIAhlg0d6nZui6nMyfIJ8dbf3aZQ5ZzP38sYow5h/fbvgL+3GSQxZRBIa3c2E1w==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.1.tgz", + "integrity": "sha512-VoVrIn7b+F2n0LJoDkLGXQJsPV/U1h3QnjRNE+Tcju6xVPBx64H0vfb7lC3S4QfVpiQ4Uc+1UD3Slvn4jGpL/A==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-musl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.4.0.tgz", - "integrity": "sha512-OLAYoICU3FaYiTdBsI+lQTKnDHeMmFMXIApN0M+xGiOkoIOQcV9CConMPjgmJQ867+NHRNgUGlvBEAh9CiJodQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.1.tgz", + "integrity": "sha512-tQi2K0LYW80BLud7ZFOy3WxCM2VjDRxuhxOYhtcLG39cIeGqsSz07LwiCFNBn4vy2J47TnZ+8XDRAOtxSFe25w==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.4.0.tgz", - "integrity": "sha512-gZ05GENFbI6CB5MlOUsLlU0kZ9UtHn9riYtSXKT6MYs8HSPRffPHaHSL0WxsJweWh9nR5Hgh/TUU8uW3sYCzCg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.1.tgz", + "integrity": "sha512-BdVwzVXY2JWBtWEO/G0//jIWXeWR52+KG0+kyoHO6QTxkncLrN5q2RldvXOe7CvhKe/qmgbkNosj5jWi7t49kQ==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.4.0.tgz", - "integrity": "sha512-JsetT/lTx/Zq98eo8T5CiRyF1nKeX04RO8JlJrI3ZOYsZpp/A5RJvMd/szQ17iOzwiHdge+tx7k2jHysR6oBlQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.1.tgz", + "integrity": "sha512-Q0ei4ZUHlGu/b4DP4Cm6WnI5zxpLxnf/vSwR2BYO3XO65TdLee1gTyuwYuSZJYu5jxqSoSusmLyL4F43jHhf9Q==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-x64-msvc": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.4.0.tgz", - "integrity": "sha512-z8Olcnwp5aYhzqUAarFjqF+oELCjuYWnB2HAJHlfsYNfDCAORY5kct3Fklz8PSsubC3U2EugWn8n42DwnThurg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.1.tgz", + "integrity": "sha512-chpsJ5PIwMOdn1IIJ6bj2G7jv9jQryVvhujU0k3kt/5kE7OuLRDYbI5BAIzMOaLoOTgoo8oxcFXQ+enELSxlMQ==", "dev": true, "optional": true }, diff --git a/package.json b/package.json index ee904de4..9e096326 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { - "@tauri-apps/cli": "1.4.0", + "@tauri-apps/cli": "1.5.1", "adm-zip": "0.5.10", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0bd2c5dd..320b6e2c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1423,7 +1423,21 @@ checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" dependencies = [ "log", "mac", - "markup5ever", + "markup5ever 0.10.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "html5ever" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" +dependencies = [ + "log", + "mac", + "markup5ever 0.11.0", "proc-macro2", "quote", "syn 1.0.109", @@ -1724,7 +1738,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" dependencies = [ "cssparser", - "html5ever", + "html5ever 0.25.2", + "matches", + "selectors", +] + +[[package]] +name = "kuchikiki" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" +dependencies = [ + "cssparser", + "html5ever 0.26.0", + "indexmap 1.9.3", "matches", "selectors", ] @@ -1768,9 +1795,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "loom" @@ -1823,7 +1850,21 @@ checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" dependencies = [ "log", "phf 0.8.0", - "phf_codegen", + "phf_codegen 0.8.0", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "markup5ever" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" +dependencies = [ + "log", + "phf 0.10.1", + "phf_codegen 0.10.0", "string_cache", "string_cache_codegen", "tendril", @@ -2305,6 +2346,16 @@ dependencies = [ "phf_shared 0.8.0", ] +[[package]] +name = "phf_codegen" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", +] + [[package]] name = "phf_generator" version = "0.8.0" @@ -2857,7 +2908,7 @@ dependencies = [ "log", "matches", "phf 0.8.0", - "phf_codegen", + "phf_codegen 0.8.0", "precomputed-hash", "servo_arc", "smallvec", @@ -3312,9 +3363,9 @@ checksum = "1b1c7f239eb94671427157bd93b3694320f3668d4e1eff08c7285366fd777fac" [[package]] name = "tauri" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbe522898e35407a8e60dc3870f7579fea2fc262a6a6072eccdd37ae1e1d91e" +checksum = "0238c5063bf9613054149a1b6bce4935922e532b7d8211f36989a490a79806be" dependencies = [ "anyhow", "base64 0.21.2", @@ -3372,12 +3423,13 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d2edd6a259b5591c8efdeb9d5702cb53515b82a6affebd55c7fd6d3a27b7d1b" +checksum = "defbfc551bd38ab997e5f8e458f87396d2559d05ce32095076ad6c30f7fc5f9c" dependencies = [ "anyhow", "cargo_toml", + "dirs-next", "heck 0.4.1", "json-patch", "semver", @@ -3385,13 +3437,14 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", + "walkdir", ] [[package]] name = "tauri-codegen" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ad2d49fdeab4a08717f5b49a163bdc72efc3b1950b6758245fcde79b645e1a" +checksum = "7b3475e55acec0b4a50fb96435f19631fb58cbcd31923e1a213de5c382536bbb" dependencies = [ "base64 0.21.2", "brotli", @@ -3415,9 +3468,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb12a2454e747896929338d93b0642144bb51e0dddbb36e579035731f0d76b7" +checksum = "613740228de92d9196b795ac455091d3a5fbdac2654abb8bb07d010b62ab43af" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -3441,9 +3494,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "108683199cb18f96d2d4134187bb789964143c845d2d154848dda209191fd769" +checksum = "07f8e9e53e00e9f41212c115749e87d5cd2a9eebccafca77a19722eeecd56d43" dependencies = [ "gtk", "http", @@ -3462,9 +3515,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7aa256a1407a3a091b5d843eccc1a5042289baf0a43d1179d9f0fcfea37c1b" +checksum = "8141d72b6b65f2008911e9ef5b98a68d1e3413b7a1464e8f85eb3673bb19a895" dependencies = [ "cocoa", "gtk", @@ -3482,19 +3535,20 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fc02bb6072bb397e1d473c6f76c953cda48b4a2d0cce605df284aa74a12e84" +checksum = "34d55e185904a84a419308d523c2c6891d5e2dbcee740c4997eb42e75a7b0f46" dependencies = [ "brotli", "ctor", "dunce", "glob", "heck 0.4.1", - "html5ever", + "html5ever 0.26.0", "infer", "json-patch", - "kuchiki", + "kuchikiki", + "log", "memchr", "phf 0.10.1", "proc-macro2", @@ -4481,9 +4535,9 @@ dependencies = [ [[package]] name = "wry" -version = "0.24.3" +version = "0.24.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33748f35413c8a98d45f7a08832d848c0c5915501803d1faade5a4ebcd258cea" +checksum = "88ef04bdad49eba2e01f06e53688c8413bd6a87b0bc14b72284465cf96e3578e" dependencies = [ "base64 0.13.1", "block", @@ -4495,7 +4549,7 @@ dependencies = [ "gio", "glib", "gtk", - "html5ever", + "html5ever 0.25.2", "http", "kuchiki", "libc", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index e667802b..0bfb7a98 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -11,13 +11,13 @@ rust-version = "1.70" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] -tauri-build = { version = "1.4.0", features = [] } +tauri-build = { version = "1.5.0", features = [] } [dependencies] serde_json = "1.0" once_cell = "1.18.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.4.1", features = [ "cli", "api-all", "updater", "devtools"] } +tauri = { version = "1.5.1", features = [ "cli", "api-all", "updater", "devtools"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From d8cb2bb3ee71c6b66d6ef97f93b9f4b75cb10880 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:19:09 +0000 Subject: [PATCH 106/864] chore(deps): update dependency tar to v6.2.0 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3b99ffa1..cd56371f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,7 +16,7 @@ "execa": "^7.1.1", "fs-extra": "11.1.1", "shx": "^0.3.4", - "tar": "6.1.15" + "tar": "6.2.0" } }, "node_modules/@tauri-apps/cli": { @@ -1147,9 +1147,9 @@ } }, "node_modules/tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dev": true, "dependencies": { "chownr": "^2.0.0", @@ -2038,9 +2038,9 @@ "dev": true }, "tar": { - "version": "6.1.15", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", - "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", "dev": true, "requires": { "chownr": "^2.0.0", diff --git a/package.json b/package.json index 9e096326..e66d2bf5 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "execa": "^7.1.1", "fs-extra": "11.1.1", "shx": "^0.3.4", - "tar": "6.1.15" + "tar": "6.2.0" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From 9aa6b5b529c4c55253e3636994839bab5312b29e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:20:02 +0000 Subject: [PATCH 107/864] chore(deps): update dependency execa to v8 --- package-lock.json | 76 +++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/package-lock.json b/package-lock.json index cd56371f..ccdb9e89 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "adm-zip": "0.5.10", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", - "execa": "^7.1.1", + "execa": "^8.0.0", "fs-extra": "11.1.1", "shx": "^0.3.4", "tar": "6.2.0" @@ -424,23 +424,23 @@ "dev": true }, "node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", - "signal-exit": "^3.0.7", + "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" }, "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + "node": ">=16.17" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" @@ -538,12 +538,12 @@ } }, "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -597,12 +597,12 @@ } }, "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, "engines": { - "node": ">=14.18.0" + "node": ">=16.17.0" } }, "node_modules/inflight": { @@ -1091,10 +1091,16 @@ } }, "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 + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, "node_modules/string-width": { "version": "3.1.0", @@ -1519,19 +1525,19 @@ "dev": true }, "execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "requires": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", - "signal-exit": "^3.0.7", + "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, @@ -1604,9 +1610,9 @@ "dev": true }, "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true }, "glob": { @@ -1645,9 +1651,9 @@ "dev": true }, "human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true }, "inflight": { @@ -2000,9 +2006,9 @@ } }, "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==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true }, "string-width": { diff --git a/package.json b/package.json index e66d2bf5..9f4cab85 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "adm-zip": "0.5.10", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", - "execa": "^7.1.1", + "execa": "^8.0.0", "fs-extra": "11.1.1", "shx": "^0.3.4", "tar": "6.2.0" From 1a09fb90c4fcc0f3489b05e86131e4d05e247285 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 6 Oct 2023 13:34:15 +0000 Subject: [PATCH 108/864] ci: update phcode version to 3.2.8 --- package.json | 6 +++--- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 32 +++++++++++++++++++++----------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index 9f4cab85..c549f3be 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.6", + "version": "3.2.8", "type": "module", "scripts": { "tauri": "tauri", @@ -47,6 +47,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "4f1703cc879584cd8d1adea58e5048306d014d5f" + "commit": "3bb7646d19257101f078c5001d1aa820e38a47bd" } -} +} \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 0bfb7a98..8ba19c24 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.6" +version = "3.2.8" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 234edba3..b8c6af6e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.6" + "version": "3.2.8" }, "tauri": { "allowlist": { @@ -82,7 +82,14 @@ { "name": "phnode", "sidecar": true, - "args": [{ "validator": "\\S*" }, { "validator": "\\S*" }] + "args": [ + { + "validator": "\\S*" + }, + { + "validator": "\\S*" + } + ] } ] } @@ -92,15 +99,18 @@ "longDescription": "CLI to open project, run tests amd other things", "beforeHelp": "", "afterHelp": "", - "args": [{ - "name": "quit-when-done", - "description": "Quit after whatever the task assigned from CLI is done.", - "short": "q" - }, { - "name": "run-tests", - "description": "run all tests in the given category", - "takesValue": true - }] + "args": [ + { + "name": "quit-when-done", + "description": "Quit after whatever the task assigned from CLI is done.", + "short": "q" + }, + { + "name": "run-tests", + "description": "run all tests in the given category", + "takesValue": true + } + ] }, "bundle": { "active": true, From a9bb8f79e264766f055f6404905d6ce042caf27b Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 7 Oct 2023 18:06:08 +0530 Subject: [PATCH 109/864] build: consistency - npm install should honor package lock file --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- .github/workflows/update-phcode-build.yml | 2 +- package.json | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 35f073c1..bddea949 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -70,7 +70,7 @@ jobs: sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies run: | - npm install + npm ci npm run _ci-release:dev - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 4e8714bb..e1e27a93 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -70,7 +70,7 @@ jobs: sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies run: | - npm install + npm ci npm run _ci-release:prod - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 68b3374c..eae46468 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -70,7 +70,7 @@ jobs: sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies run: | - npm install + npm ci npm run _ci-release:staging - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index a21e39e9..6997918d 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -24,7 +24,7 @@ jobs: - name: Update phcode and version run: | - npm install + npm ci npm run _ci-update-phcode-build ${{ github.event.client_payload.sha }} git status phoenix_version=`node -p "require('./package.json').version"` diff --git a/package.json b/package.json index c549f3be..a1690428 100644 --- a/package.json +++ b/package.json @@ -17,12 +17,12 @@ "releaseDistDebug": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", - "_src-node_npm_install": "cd src-tauri/src-node && npm install --production && cd ../../", + "_src-node_npm_install": "cd src-tauri/src-node && npm ci --production && cd ../../", "_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r ../phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", "_make_src-node_debug_dev": "npm run _make_src-node && shx rm -rf src-tauri/target/debug/src-node && shx cp -r src-tauri/src-node src-tauri/target/debug/src-node", "_ci_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", "_servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", - "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm install && npm run build && cd ..", + "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm ci && npm run build && cd ..", "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", From 67f4f9429c787361da8797359174167718df47c4 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 10 Oct 2023 12:59:41 +0530 Subject: [PATCH 110/864] build: enable tauri assets urls --- package-lock.json | 4 ++-- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 12 +++++++++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ccdb9e89..a09d36aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.2.6", + "version": "3.2.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.6", + "version": "3.2.8", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.1", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 320b6e2c..e0c11fb0 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2424,7 +2424,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.6" +version = "3.2.8" dependencies = [ "once_cell", "serde", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8ba19c24..52b79f23 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,7 +17,7 @@ tauri-build = { version = "1.5.0", features = [] } serde_json = "1.0" once_cell = "1.18.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.5.1", features = [ "cli", "api-all", "updater", "devtools"] } +tauri = { version = "1.5.1", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index b8c6af6e..f4d6cd70 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -73,6 +73,15 @@ "**/**/*.*" ] }, + "protocol": { + "asset": true, + "assetScope": { + "allow": [ + "$APPLOCALDATA/assets/**", + "$APPLOCALDATA/assets/**/*.*" + ] + } + }, "shell": { "all": true, "execute": true, @@ -231,7 +240,8 @@ } }, "security": { - "csp": null + "csp": null, + "dangerousDisableAssetCspModification": true }, "updater": { "active": true, From a32fba6103fee8de671af08701ac56322bc84b3a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 8 Oct 2023 16:23:49 +0000 Subject: [PATCH 111/864] chore(deps): update dependency @tauri-apps/cli to v1.5.2 --- package-lock.json | 174 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 88 insertions(+), 88 deletions(-) diff --git a/package-lock.json b/package-lock.json index a09d36aa..13e459ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.2.8", "hasInstallScript": true, "devDependencies": { - "@tauri-apps/cli": "1.5.1", + "@tauri-apps/cli": "1.5.2", "adm-zip": "0.5.10", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -20,9 +20,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.1.tgz", - "integrity": "sha512-Ssj30axil5vPBV3W5ScHXk4umTKu6BhfmMdljfKDOG9K55gAqzBAE2VBC5e/ouclSxZfN+6YNL9VhDXFu/UyeA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.2.tgz", + "integrity": "sha512-x4rPinrdyWLdTU5TbV7wrXudOyMilv0nmi1rngm/jwN3MmZdAj5J2xaS2rYtA8BU3oM/SE34qQwYxv1a2sM9ug==", "dev": true, "bin": { "tauri": "tauri.js" @@ -35,22 +35,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.5.1", - "@tauri-apps/cli-darwin-x64": "1.5.1", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.1", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.1", - "@tauri-apps/cli-linux-arm64-musl": "1.5.1", - "@tauri-apps/cli-linux-x64-gnu": "1.5.1", - "@tauri-apps/cli-linux-x64-musl": "1.5.1", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.1", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.1", - "@tauri-apps/cli-win32-x64-msvc": "1.5.1" + "@tauri-apps/cli-darwin-arm64": "1.5.2", + "@tauri-apps/cli-darwin-x64": "1.5.2", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.2", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.2", + "@tauri-apps/cli-linux-arm64-musl": "1.5.2", + "@tauri-apps/cli-linux-x64-gnu": "1.5.2", + "@tauri-apps/cli-linux-x64-musl": "1.5.2", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.2", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.2", + "@tauri-apps/cli-win32-x64-msvc": "1.5.2" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.1.tgz", - "integrity": "sha512-o2FSGj72gqJjlVtuScXQZUgiRs90PS9gG7YAz0Hgr4nV1MfIn9U6JVj6R+mnAEZBCK8qdy5jdemhmNKDDoiYQg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.2.tgz", + "integrity": "sha512-3mYN15jpYjuuHRWii5Xk6JvB3ZLEgAZkeVgc5Hg7k3Yw1ZBrEGiUNe3Ku4DjbkYWL/QDd7oteIJnQk3j0mXwEg==", "cpu": [ "arm64" ], @@ -64,9 +64,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.1.tgz", - "integrity": "sha512-G1/v6AJPP5oIcjsOxZshag28wdmDx1Fis2yz545aUk7oKU86A3ZJpz0b8BaXkr93w04xGcmGAaspZeXMmTvrbw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.2.tgz", + "integrity": "sha512-8Jsl+EKBGdBoRUIR5ohjiTV6uG+pFpkNwHB4WaOzzR//v6p0lGULk2ohPIjJxhoQIFIN9oBd8bsSSNbZO/57/g==", "cpu": [ "x64" ], @@ -80,9 +80,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.1.tgz", - "integrity": "sha512-hPDOUMviffyX5BySk6RuD7IZZeMuNUJzKWHxVWa0NHJPfxQOIPWwYWbk6TascrVk9GZYAImcB0yKfrll8I0VTg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.2.tgz", + "integrity": "sha512-oWzcQtZogchdCSdQ+eEbDJHjJO9BGPO9EZNfvI2u3JzS/hJj4wCwnGHvZGI4jJ/6cnmcNvtt9ZftYYN4rpQW7A==", "cpu": [ "arm" ], @@ -96,9 +96,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.1.tgz", - "integrity": "sha512-EJjTXqZchFLVrFgfxwstrQj7NwVDirffLhw5hRWS3L3Iys3IvqzIMVIA+GrY7KsaPwq7qaSqE1CDtP1wejE/9g==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.2.tgz", + "integrity": "sha512-hfIUtys+SrrGEpLhQJwmL16g1FDhfObR4AGahCMqvMwA25uQKhtzRhxieO4X3k03vBeboTyJla5a2rX4TQ4lXA==", "cpu": [ "arm64" ], @@ -112,9 +112,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.1.tgz", - "integrity": "sha512-XgJIk0AcxRL4pWVjfj0wiC9WnIZoUIVLPcQs86dNxoqzwAvADdNYp+McXf3/MDxX8uGEzpgdvlqr4T+50c8f6w==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.2.tgz", + "integrity": "sha512-ZpFX4HyjkJHfF0geVVpq5fNjEXG8766LRg/BL4/wKy8MNbqcc/aW3sLEpVj0GvdulxOnd2trDb1FJdZ206Kp8g==", "cpu": [ "arm64" ], @@ -128,9 +128,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.1.tgz", - "integrity": "sha512-VoVrIn7b+F2n0LJoDkLGXQJsPV/U1h3QnjRNE+Tcju6xVPBx64H0vfb7lC3S4QfVpiQ4Uc+1UD3Slvn4jGpL/A==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.2.tgz", + "integrity": "sha512-/kEZrDVZv1+qYpZigtLntX4s+gx7WQqp8cmxKZL5GrzAjUNSTnfWK5VL7o0lYm09QBJAdTvjcJu2aPzNHLDS+Q==", "cpu": [ "x64" ], @@ -144,9 +144,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.1.tgz", - "integrity": "sha512-tQi2K0LYW80BLud7ZFOy3WxCM2VjDRxuhxOYhtcLG39cIeGqsSz07LwiCFNBn4vy2J47TnZ+8XDRAOtxSFe25w==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.2.tgz", + "integrity": "sha512-vOrTqfW7NZLYmB1ZXjEq9JC8Z5knIHVGltN3jfyq9UY+tu7d6jNaSHuDdsVHLaKIRQajTHz+5cphDMoL+6/MUQ==", "cpu": [ "x64" ], @@ -160,9 +160,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.1.tgz", - "integrity": "sha512-BdVwzVXY2JWBtWEO/G0//jIWXeWR52+KG0+kyoHO6QTxkncLrN5q2RldvXOe7CvhKe/qmgbkNosj5jWi7t49kQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.2.tgz", + "integrity": "sha512-PCAIxH8TvIy1PlJK2qrdwpRCa7pZV648whRhmoLwj9lvn9PR4+vwuUWhSTXmp1ISHWZm/mEJpYuVq0ZxJDQKZQ==", "cpu": [ "arm64" ], @@ -176,9 +176,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.1.tgz", - "integrity": "sha512-Q0ei4ZUHlGu/b4DP4Cm6WnI5zxpLxnf/vSwR2BYO3XO65TdLee1gTyuwYuSZJYu5jxqSoSusmLyL4F43jHhf9Q==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.2.tgz", + "integrity": "sha512-0rCXZC/9qyWZI2cgVnsT4JEjcxjQcZlrZjaSwhGynPUMkIUUBsWDimzkQeOP8abw5j/kLS2QPQRHAHqd0IF6Rg==", "cpu": [ "ia32" ], @@ -192,9 +192,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.1.tgz", - "integrity": "sha512-chpsJ5PIwMOdn1IIJ6bj2G7jv9jQryVvhujU0k3kt/5kE7OuLRDYbI5BAIzMOaLoOTgoo8oxcFXQ+enELSxlMQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.2.tgz", + "integrity": "sha512-HrOwIujKTql8yUOvR+IEGW/SXwMwPrGWrcM35cDfCxpkLH6h3F5i4JtRqYTAiFdSfTk1J2rcFVQXfFJYIDntnA==", "cpu": [ "x64" ], @@ -1274,90 +1274,90 @@ }, "dependencies": { "@tauri-apps/cli": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.1.tgz", - "integrity": "sha512-Ssj30axil5vPBV3W5ScHXk4umTKu6BhfmMdljfKDOG9K55gAqzBAE2VBC5e/ouclSxZfN+6YNL9VhDXFu/UyeA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.2.tgz", + "integrity": "sha512-x4rPinrdyWLdTU5TbV7wrXudOyMilv0nmi1rngm/jwN3MmZdAj5J2xaS2rYtA8BU3oM/SE34qQwYxv1a2sM9ug==", "dev": true, "requires": { - "@tauri-apps/cli-darwin-arm64": "1.5.1", - "@tauri-apps/cli-darwin-x64": "1.5.1", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.1", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.1", - "@tauri-apps/cli-linux-arm64-musl": "1.5.1", - "@tauri-apps/cli-linux-x64-gnu": "1.5.1", - "@tauri-apps/cli-linux-x64-musl": "1.5.1", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.1", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.1", - "@tauri-apps/cli-win32-x64-msvc": "1.5.1" + "@tauri-apps/cli-darwin-arm64": "1.5.2", + "@tauri-apps/cli-darwin-x64": "1.5.2", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.2", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.2", + "@tauri-apps/cli-linux-arm64-musl": "1.5.2", + "@tauri-apps/cli-linux-x64-gnu": "1.5.2", + "@tauri-apps/cli-linux-x64-musl": "1.5.2", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.2", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.2", + "@tauri-apps/cli-win32-x64-msvc": "1.5.2" } }, "@tauri-apps/cli-darwin-arm64": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.1.tgz", - "integrity": "sha512-o2FSGj72gqJjlVtuScXQZUgiRs90PS9gG7YAz0Hgr4nV1MfIn9U6JVj6R+mnAEZBCK8qdy5jdemhmNKDDoiYQg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.2.tgz", + "integrity": "sha512-3mYN15jpYjuuHRWii5Xk6JvB3ZLEgAZkeVgc5Hg7k3Yw1ZBrEGiUNe3Ku4DjbkYWL/QDd7oteIJnQk3j0mXwEg==", "dev": true, "optional": true }, "@tauri-apps/cli-darwin-x64": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.1.tgz", - "integrity": "sha512-G1/v6AJPP5oIcjsOxZshag28wdmDx1Fis2yz545aUk7oKU86A3ZJpz0b8BaXkr93w04xGcmGAaspZeXMmTvrbw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.2.tgz", + "integrity": "sha512-8Jsl+EKBGdBoRUIR5ohjiTV6uG+pFpkNwHB4WaOzzR//v6p0lGULk2ohPIjJxhoQIFIN9oBd8bsSSNbZO/57/g==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.1.tgz", - "integrity": "sha512-hPDOUMviffyX5BySk6RuD7IZZeMuNUJzKWHxVWa0NHJPfxQOIPWwYWbk6TascrVk9GZYAImcB0yKfrll8I0VTg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.2.tgz", + "integrity": "sha512-oWzcQtZogchdCSdQ+eEbDJHjJO9BGPO9EZNfvI2u3JzS/hJj4wCwnGHvZGI4jJ/6cnmcNvtt9ZftYYN4rpQW7A==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.1.tgz", - "integrity": "sha512-EJjTXqZchFLVrFgfxwstrQj7NwVDirffLhw5hRWS3L3Iys3IvqzIMVIA+GrY7KsaPwq7qaSqE1CDtP1wejE/9g==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.2.tgz", + "integrity": "sha512-hfIUtys+SrrGEpLhQJwmL16g1FDhfObR4AGahCMqvMwA25uQKhtzRhxieO4X3k03vBeboTyJla5a2rX4TQ4lXA==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.1.tgz", - "integrity": "sha512-XgJIk0AcxRL4pWVjfj0wiC9WnIZoUIVLPcQs86dNxoqzwAvADdNYp+McXf3/MDxX8uGEzpgdvlqr4T+50c8f6w==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.2.tgz", + "integrity": "sha512-ZpFX4HyjkJHfF0geVVpq5fNjEXG8766LRg/BL4/wKy8MNbqcc/aW3sLEpVj0GvdulxOnd2trDb1FJdZ206Kp8g==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.1.tgz", - "integrity": "sha512-VoVrIn7b+F2n0LJoDkLGXQJsPV/U1h3QnjRNE+Tcju6xVPBx64H0vfb7lC3S4QfVpiQ4Uc+1UD3Slvn4jGpL/A==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.2.tgz", + "integrity": "sha512-/kEZrDVZv1+qYpZigtLntX4s+gx7WQqp8cmxKZL5GrzAjUNSTnfWK5VL7o0lYm09QBJAdTvjcJu2aPzNHLDS+Q==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.1.tgz", - "integrity": "sha512-tQi2K0LYW80BLud7ZFOy3WxCM2VjDRxuhxOYhtcLG39cIeGqsSz07LwiCFNBn4vy2J47TnZ+8XDRAOtxSFe25w==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.2.tgz", + "integrity": "sha512-vOrTqfW7NZLYmB1ZXjEq9JC8Z5knIHVGltN3jfyq9UY+tu7d6jNaSHuDdsVHLaKIRQajTHz+5cphDMoL+6/MUQ==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.1.tgz", - "integrity": "sha512-BdVwzVXY2JWBtWEO/G0//jIWXeWR52+KG0+kyoHO6QTxkncLrN5q2RldvXOe7CvhKe/qmgbkNosj5jWi7t49kQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.2.tgz", + "integrity": "sha512-PCAIxH8TvIy1PlJK2qrdwpRCa7pZV648whRhmoLwj9lvn9PR4+vwuUWhSTXmp1ISHWZm/mEJpYuVq0ZxJDQKZQ==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.1.tgz", - "integrity": "sha512-Q0ei4ZUHlGu/b4DP4Cm6WnI5zxpLxnf/vSwR2BYO3XO65TdLee1gTyuwYuSZJYu5jxqSoSusmLyL4F43jHhf9Q==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.2.tgz", + "integrity": "sha512-0rCXZC/9qyWZI2cgVnsT4JEjcxjQcZlrZjaSwhGynPUMkIUUBsWDimzkQeOP8abw5j/kLS2QPQRHAHqd0IF6Rg==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.1.tgz", - "integrity": "sha512-chpsJ5PIwMOdn1IIJ6bj2G7jv9jQryVvhujU0k3kt/5kE7OuLRDYbI5BAIzMOaLoOTgoo8oxcFXQ+enELSxlMQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.2.tgz", + "integrity": "sha512-HrOwIujKTql8yUOvR+IEGW/SXwMwPrGWrcM35cDfCxpkLH6h3F5i4JtRqYTAiFdSfTk1J2rcFVQXfFJYIDntnA==", "dev": true, "optional": true }, diff --git a/package.json b/package.json index a1690428..377ed976 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { - "@tauri-apps/cli": "1.5.1", + "@tauri-apps/cli": "1.5.2", "adm-zip": "0.5.10", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", From 328e53dae67e03a809ba68ae5fea088eaeb9e54b Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 11 Oct 2023 19:51:11 +0530 Subject: [PATCH 112/864] feat tauri api to get system temp folder --- src-tauri/src/main.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1d5c9885..123f0676 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -46,6 +46,11 @@ fn toggle_devtools(window: tauri::Window) { } } +#[tauri::command] +fn get_temp_dir() -> String { + std::env::temp_dir().into_os_string().into_string().unwrap() +} + fn process_window_event(event: &GlobalWindowEvent) { if let tauri::WindowEvent::CloseRequested { .. } = event.event() { let size = event.window().outer_size().unwrap(); @@ -60,7 +65,7 @@ fn main() { .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ toggle_devtools, console_log, console_error, - _get_windows_drives, _rename_path]) + _get_windows_drives, _rename_path, get_temp_dir]) .setup(|app| { init::init_app(app); Ok(()) From cf66f0c2d7f835a1f8cdc2bc4345199090f69398 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 12 Oct 2023 16:57:14 +0530 Subject: [PATCH 113/864] fix: tauri file corruption on write issue --- src-tauri/Cargo.lock | 4 ++-- src-tauri/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e0c11fb0..769ff8bc 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3363,9 +3363,9 @@ checksum = "1b1c7f239eb94671427157bd93b3694320f3668d4e1eff08c7285366fd777fac" [[package]] name = "tauri" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0238c5063bf9613054149a1b6bce4935922e532b7d8211f36989a490a79806be" +checksum = "9bfe673cf125ef364d6f56b15e8ce7537d9ca7e4dae1cf6fbbdeed2e024db3d9" dependencies = [ "anyhow", "base64 0.21.2", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 52b79f23..48299161 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,7 +17,7 @@ tauri-build = { version = "1.5.0", features = [] } serde_json = "1.0" once_cell = "1.18.0" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.5.1", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } +tauri = { version = "1.5.2", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From 0bb252431f871bbda1440770b777a6ca778363b6 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 12 Oct 2023 17:36:39 +0530 Subject: [PATCH 114/864] refactor: tauri already has os.tempdir api, so removing our impl --- src-tauri/src/main.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 123f0676..1d5c9885 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -46,11 +46,6 @@ fn toggle_devtools(window: tauri::Window) { } } -#[tauri::command] -fn get_temp_dir() -> String { - std::env::temp_dir().into_os_string().into_string().unwrap() -} - fn process_window_event(event: &GlobalWindowEvent) { if let tauri::WindowEvent::CloseRequested { .. } = event.event() { let size = event.window().outer_size().unwrap(); @@ -65,7 +60,7 @@ fn main() { .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ toggle_devtools, console_log, console_error, - _get_windows_drives, _rename_path, get_temp_dir]) + _get_windows_drives, _rename_path]) .setup(|app| { init::init_app(app); Ok(()) From b09ba378f54ba7118a129947b038df071e1679da Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 12 Oct 2023 18:14:04 +0530 Subject: [PATCH 115/864] fix: window size jumps on successive launches --- src-tauri/src/init.rs | 19 +++++++++++++++---- src-tauri/src/main.rs | 3 +-- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src-tauri/src/init.rs b/src-tauri/src/init.rs index 163d9ace..e5be0a02 100644 --- a/src-tauri/src/init.rs +++ b/src-tauri/src/init.rs @@ -24,14 +24,23 @@ fn restore_window_size(app: &mut tauri::App, boot_config: &BootConfig){ let main_window = app.get_window("main").unwrap(); let current_monitor = main_window.current_monitor().unwrap().unwrap(); let current_monitor_size = current_monitor.size(); - println!("current_monitor_size is {}, {}", current_monitor_size.width, current_monitor_size.height); - println!("saved window size is {}, {}", boot_config.last_window_width, boot_config.last_window_height); + + #[cfg(debug_assertions)] + { + println!("current_monitor_size is {}, {}", current_monitor_size.width, current_monitor_size.height); + println!("saved window size is {}, {}", boot_config.last_window_width, boot_config.last_window_height); + } + let width = get_window_size(boot_config.last_window_width, current_monitor_size.width, PREFERRED_WIDTH); let height = get_window_size(boot_config.last_window_height, current_monitor_size.height, PREFERRED_HEIGHT); if width == MAXIMIZE_SIZE || height == MAXIMIZE_SIZE { main_window.maximize().expect("unable to maximize"); } else { - println!("resizing window to {}, {}", width, height); + + #[cfg(debug_assertions)]{ + println!("resizing window to {}, {}", width, height); + } + let size = tauri::PhysicalSize::new(width, height); main_window.set_size(size).expect("unable to resize"); } @@ -49,7 +58,9 @@ pub fn init_app(app: &mut tauri::App) { // To get a value if let Some(app_constants) = APP_CONSTANTS.get() { - println!("Bundle ID is {}", app_constants.tauri_config.tauri.bundle.identifier); + #[cfg(debug_assertions)]{ + println!("Bundle ID is {}", app_constants.tauri_config.tauri.bundle.identifier); + } ensure_dir_exists(&app_constants.app_local_data_dir); let boot_config = read_boot_config(); restore_window_size(app, &boot_config); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1d5c9885..4d865b95 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -48,8 +48,7 @@ fn toggle_devtools(window: tauri::Window) { fn process_window_event(event: &GlobalWindowEvent) { if let tauri::WindowEvent::CloseRequested { .. } = event.event() { - let size = event.window().outer_size().unwrap(); - println!("Window closing size {}, {}", size.width, size.height); + let size = event.window().inner_size().unwrap(); boot_config::write_boot_config(size.width, size.height); } } From b34a0c667f5626a5e9e264efcd6e568971f0dec5 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 12 Oct 2023 18:17:05 +0530 Subject: [PATCH 116/864] chore: cur prod logs, logs in debug only --- src-tauri/src/utilities.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/utilities.rs b/src-tauri/src/utilities.rs index 12ee0391..3458647d 100644 --- a/src-tauri/src/utilities.rs +++ b/src-tauri/src/utilities.rs @@ -34,7 +34,9 @@ pub fn ensure_dir_exists(path: &PathBuf){ if let Err(e) = fs::create_dir_all(path) { eprintln!("Failed to create directory: {}", e); } else { - println!("Directory created successfully {}", path.display()); + #[cfg(debug_assertions)]{ + println!("Directory created successfully {}", path.display()); + } } } From e12982032e6c6400589322db55ce28c0b4b03dc8 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 21 Oct 2023 17:11:45 +0000 Subject: [PATCH 117/864] ci: update phcode version to 3.2.9 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 377ed976..a9f29aae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.8", + "version": "3.2.9", "type": "module", "scripts": { "tauri": "tauri", @@ -47,6 +47,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "3bb7646d19257101f078c5001d1aa820e38a47bd" + "commit": "0b313944720d136871f8be3d3207da952391e286" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 48299161..6191a7bb 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.8" +version = "3.2.9" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f4d6cd70..8997c04f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.8" + "version": "3.2.9" }, "tauri": { "allowlist": { From 52cd01dac46cdaa481a54dbf28d3d8029055ab3c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 17:44:52 +0000 Subject: [PATCH 118/864] chore(deps): update actions/setup-node action to v4 --- .github/workflows/tauri-build-dev.yml | 4 ++-- .github/workflows/tauri-build-prod.yml | 4 ++-- .github/workflows/tauri-build-staging.yml | 4 ++-- .github/workflows/update-phcode-build.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index bddea949..ad36aa11 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - name: get version @@ -55,7 +55,7 @@ jobs: shell: bash run: echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - name: install Rust stable diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index e1e27a93..d04ca766 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - name: get version @@ -55,7 +55,7 @@ jobs: shell: bash run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - name: install Rust stable diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index eae46468..94864a99 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - name: get version @@ -55,7 +55,7 @@ jobs: shell: bash run: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* - name: install Rust stable diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 6997918d..72788ff2 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -18,7 +18,7 @@ jobs: echo source: ${{github.event.client_payload.source}}, workflow: ${{github.event.client_payload.workflow}}, action_run_id: ${{github.event.client_payload.run_id}}, action_run_number: ${{github.event.client_payload.run_number}}, sha: ${{ github.event.client_payload.sha }}, github_ref: ${{ github.event.client_payload.ref }} - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: lts/* From 7f6c6df83f973a7b6b143084768d9ac7df257fe7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:54:36 +0000 Subject: [PATCH 119/864] chore(deps): update actions/checkout action to v4 --- .github/workflows/tauri-build-dev.yml | 6 +++--- .github/workflows/tauri-build-prod.yml | 6 +++--- .github/workflows/tauri-build-staging.yml | 6 +++--- .github/workflows/update-phcode-build.yml | 2 +- .github/workflows/updateNotification.yml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index ad36aa11..b070e9dd 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -13,7 +13,7 @@ jobs: release_id: ${{ steps.create-release.outputs.result }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: @@ -50,7 +50,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get Git Tag shell: bash run: echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV @@ -162,7 +162,7 @@ jobs: needs: [ create-release, build-tauri ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get Git Tag run: echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: publish release diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index d04ca766..31a4013c 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -13,7 +13,7 @@ jobs: release_id: ${{ steps.create-release.outputs.result }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: @@ -50,7 +50,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get Git Tag shell: bash run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV @@ -163,7 +163,7 @@ jobs: needs: [ create-release, build-tauri ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get Git Tag run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: publish release diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 94864a99..7f64b144 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -13,7 +13,7 @@ jobs: release_id: ${{ steps.create-release.outputs.result }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: @@ -50,7 +50,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get Git Tag shell: bash run: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV @@ -163,7 +163,7 @@ jobs: needs: [ create-release, build-tauri ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: get Git Tag run: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: publish release diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 72788ff2..3c68ca76 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -12,7 +12,7 @@ jobs: build-tasks: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Event triggered by run: | echo source: ${{github.event.client_payload.source}}, workflow: ${{github.event.client_payload.workflow}}, action_run_id: ${{github.event.client_payload.run_id}}, action_run_number: ${{github.event.client_payload.run_number}}, sha: ${{ github.event.client_payload.sha }}, github_ref: ${{ github.event.client_payload.ref }} diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml index 740e3225..a1ba66e1 100644 --- a/.github/workflows/updateNotification.yml +++ b/.github/workflows/updateNotification.yml @@ -19,7 +19,7 @@ jobs: echo '${{ toJSON(github) }}' echo "$GITHUB_REF repo=${{github.event.repository.full_name}}" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: main - uses: actions/github-script@v6 From a75208c62b02d0bcad07d6202c5a47d97787e49b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:50:37 +0000 Subject: [PATCH 120/864] build(deps): bump rustix from 0.37.21 to 0.37.25 in /src-tauri Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.37.21 to 0.37.25. - [Release notes](https://github.com/bytecodealliance/rustix/releases) - [Commits](https://github.com/bytecodealliance/rustix/compare/v0.37.21...v0.37.25) --- updated-dependencies: - dependency-name: rustix dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 769ff8bc..9d51218f 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2812,9 +2812,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.21" +version = "0.37.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25693a73057a1b4cb56179dd3c7ea21a7c6c5ee7d85781f5749b46f34b79c" +checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" dependencies = [ "bitflags", "errno", From b4f4f6eac7e47280a1bec428bffb407593a9c2e7 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Tue, 24 Oct 2023 10:56:16 +0000 Subject: [PATCH 121/864] ci: update phcode version to 3.2.10 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index a9f29aae..cd484041 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.9", + "version": "3.2.10", "type": "module", "scripts": { "tauri": "tauri", @@ -47,6 +47,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "0b313944720d136871f8be3d3207da952391e286" + "commit": "53bb60c25b662b30d52ee39b8019dbd11a895151" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6191a7bb..264a29a1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.9" +version = "3.2.10" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8997c04f..817c3981 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.9" + "version": "3.2.10" }, "tauri": { "allowlist": { From e03db509108555f85c205593f8295ee5720e9f4a Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 21 Oct 2023 22:11:46 +0530 Subject: [PATCH 122/864] ci: add integ test run on pull requests --- .github/workflows/desktop-linux-test-pull.yml | 68 +++++++++++++ .github/workflows/desktop-mac-test-pull.yml | 61 ++++++++++++ .../workflows/desktop-windows-test-pull.yml | 97 +++++++++++++++++++ package.json | 1 + src-build/clonePhoenixForTests.js | 34 +++++++ 5 files changed, 261 insertions(+) create mode 100644 .github/workflows/desktop-linux-test-pull.yml create mode 100644 .github/workflows/desktop-mac-test-pull.yml create mode 100644 .github/workflows/desktop-windows-test-pull.yml create mode 100644 src-build/clonePhoenixForTests.js diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml new file mode 100644 index 00000000..f70704e8 --- /dev/null +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -0,0 +1,68 @@ +name: 'Desktop-Linux full test suite run on pull request' +on: [pull_request] + +concurrency: + group: pr-desktop-linux-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + test-desktop-linux: + runs-on: ubuntu-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: install dependencies (ubuntu only) + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + sudo apt install build-essential curl wget file libssl-dev libayatana-appindicator3-dev + sudo apt-get install xvfb + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:dev + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=unit -q + + - name: Run tauri integration tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=integration -q + + - name: Run tauri mainview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + + - name: Run tauri LegacyInteg tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 20 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml new file mode 100644 index 00000000..10e5d9bf --- /dev/null +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -0,0 +1,61 @@ +name: 'Desktop-mac full test suite run on pull request' +on: [pull_request] + +concurrency: + group: pr-desktop-mac-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + test-desktop-mac: + runs-on: macos-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:dev + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q + + - name: Run tauri integration tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q + + - name: Run tauri mainview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + + - name: Run tauri LegacyInteg tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 30 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml new file mode 100644 index 00000000..7acc62c8 --- /dev/null +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -0,0 +1,97 @@ +name: 'Desktop-Windows full test suite run on pull request' +on: [pull_request] + +concurrency: + group: pr-desktop-windows-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + test-desktop-windows: + runs-on: windows-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:dev + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests in windows + # GUI apps in windows doesn't log on console. so we capture the output to a text file and print it, then fail on error. + uses: nick-fields/retry@v2 + id: windowsRunUnit + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=unit -q > output-unit.txt 2>&1 + shell: cmd + + - name: Print windows unit test output to console + run: type output-unit.txt + shell: cmd + + - name: Run tauri integration tests in windows + uses: nick-fields/retry@v2 + id: windowsRunIntegration + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=integration -q > output-integration.txt 2>&1 + shell: cmd + + - name: Print windows integration test output to console + run: type output-integration.txt + shell: cmd + + - name: Run tauri mainview tests in windows + uses: nick-fields/retry@v2 + id: windowsRunMainview + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=mainview -q > output-mainview.txt 2>&1 + shell: cmd + + - name: Print windows mainview test output to console + run: type output-mainview.txt + shell: cmd + + - name: Run tauri LegacyInteg tests in windows + uses: nick-fields/retry@v2 + id: windowsRunLegacyInteg + continue-on-error: true + with: + timeout_minutes: 30 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=LegacyInteg -q > output-LegacyInteg.txt 2>&1 + shell: cmd + + - name: Print windows LegacyInteg test output to console + run: type output-LegacyInteg.txt + shell: cmd + + - name: Fail on test runs failed in windows + if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' + run: | + echo "Windows tests failed, marking step as failed" + exit 1 + shell: cmd diff --git a/package.json b/package.json index cd484041..988a97cc 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "_make_src-node_debug_dev": "npm run _make_src-node && shx rm -rf src-tauri/target/debug/src-node && shx cp -r src-tauri/src-node src-tauri/target/debug/src-node", "_ci_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", "_servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", + "_ci-clonePhoenixForTests": "npm run _ci-env-warn && node ./src-build/clonePhoenixForTests.js", "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm ci && npm run build && cd ..", "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", diff --git a/src-build/clonePhoenixForTests.js b/src-build/clonePhoenixForTests.js new file mode 100644 index 00000000..334d1573 --- /dev/null +++ b/src-build/clonePhoenixForTests.js @@ -0,0 +1,34 @@ +import {$} from 'execa'; // https://www.npmjs.com/package/execa +import fs from 'fs'; +import path from 'path' + +console.log("Cloning phoenix..."); +async function pwd() { + const pwd = process.cwd(); + console.log("current dir: ", pwd); + return pwd; +} + +const projectDir = await pwd(); +const phoenixProjectPath = path.join(projectDir, "..", "phoenix"); + +let packageJSONPath = path.join(projectDir, 'package.json'); +console.log('loading package.json: ', packageJSONPath); + +let packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf-8')); +const phoenixRepo = packageJSON.phoenixRepo; + +process.chdir('..'); +await pwd(); + +console.log(`Cloning`, phoenixRepo); +if(!fs.existsSync(phoenixProjectPath)){ + await $`git clone ${phoenixRepo.gitClonrUrl} --branch ${phoenixRepo.branch}`; +} +process.chdir('phoenix'); +await pwd(); +console.log('checking out commit: ', phoenixRepo.commit); +await $`git checkout ${phoenixRepo.commit}`; + +process.chdir(projectDir); +await pwd(); From 87ad72c2c75168d235d21c816b8c97445fc30a3c Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 21 Oct 2023 22:15:12 +0530 Subject: [PATCH 123/864] ci: add integ test run on pull requests --- .github/workflows/desktop-linux-test-pull.yml | 3 +++ .github/workflows/desktop-mac-test-pull.yml | 3 +++ .github/workflows/desktop-windows-test-pull.yml | 3 +++ 3 files changed, 9 insertions(+) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index f70704e8..02cd35ff 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -25,6 +25,9 @@ jobs: sudo apt install build-essential curl wget file libssl-dev libayatana-appindicator3-dev sudo apt-get install xvfb + - name: npm install ci deps + run: npm ci + - name: Download phoenix and build build phoenix dist-test run: | npm run _ci-clonePhoenixForTests diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 10e5d9bf..a07c7e47 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -18,6 +18,9 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable + - name: npm install ci deps + run: npm ci + - name: Download phoenix and build build phoenix dist-test run: | npm run _ci-clonePhoenixForTests diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index 7acc62c8..6e9cf1ae 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -18,6 +18,9 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable + - name: npm install ci deps + run: npm ci + - name: Download phoenix and build build phoenix dist-test run: | npm run _ci-clonePhoenixForTests From e586af95c991db6101bee83f6ef770ffccc97dd0 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 22 Oct 2023 09:48:07 +0530 Subject: [PATCH 124/864] ci: add full test suite runs on push to staging and prod branch --- .../workflows/prod-desktop-tests-on-push.yml | 261 ++++++++++++++++++ .../staging-desktop-tests-on-push.yml | 261 ++++++++++++++++++ 2 files changed, 522 insertions(+) create mode 100644 .github/workflows/prod-desktop-tests-on-push.yml create mode 100644 .github/workflows/staging-desktop-tests-on-push.yml diff --git a/.github/workflows/prod-desktop-tests-on-push.yml b/.github/workflows/prod-desktop-tests-on-push.yml new file mode 100644 index 00000000..ffb6f67c --- /dev/null +++ b/.github/workflows/prod-desktop-tests-on-push.yml @@ -0,0 +1,261 @@ +name: On-Push prod Win/Mac/Linux run full tests suite + +on: + push: + branches: [ prod ] + +permissions: + contents: read + issues: write + +jobs: + + testDesktopLinux: + runs-on: ubuntu-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: install dependencies (ubuntu only) + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + sudo apt install build-essential curl wget file libssl-dev libayatana-appindicator3-dev + sudo apt-get install xvfb + + - name: npm install ci deps + run: npm ci + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:prod + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=unit -q + + - name: Run tauri integration tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=integration -q + + - name: Run tauri mainview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + + - name: Run tauri LegacyInteg tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 20 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + + testDesktopMac: + runs-on: macos-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: npm install ci deps + run: npm ci + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:prod + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q + + - name: Run tauri integration tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q + + - name: Run tauri mainview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + + - name: Run tauri LegacyInteg tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 30 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + + testDesktopWindows: + runs-on: windows-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: npm install ci deps + run: npm ci + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:prod + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests in windows + # GUI apps in windows doesn't log on console. so we capture the output to a text file and print it, then fail on error. + uses: nick-fields/retry@v2 + id: windowsRunUnit + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=unit -q > output-unit.txt 2>&1 + shell: cmd + + - name: Print windows unit test output to console + run: type output-unit.txt + shell: cmd + + - name: Run tauri integration tests in windows + uses: nick-fields/retry@v2 + id: windowsRunIntegration + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=integration -q > output-integration.txt 2>&1 + shell: cmd + + - name: Print windows integration test output to console + run: type output-integration.txt + shell: cmd + + - name: Run tauri mainview tests in windows + uses: nick-fields/retry@v2 + id: windowsRunMainview + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=mainview -q > output-mainview.txt 2>&1 + shell: cmd + + - name: Print windows mainview test output to console + run: type output-mainview.txt + shell: cmd + + - name: Run tauri LegacyInteg tests in windows + uses: nick-fields/retry@v2 + id: windowsRunLegacyInteg + continue-on-error: true + with: + timeout_minutes: 30 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=LegacyInteg -q > output-LegacyInteg.txt 2>&1 + shell: cmd + + - name: Print windows LegacyInteg test output to console + run: type output-LegacyInteg.txt + shell: cmd + + - name: Fail on test runs failed in windows + if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' + run: | + echo "Windows tests failed, marking step as failed" + exit 1 + shell: cmd + + raiseIssue: + needs: [ testDesktopLinux, testDesktopMac, testDesktopWindows] + runs-on: ubuntu-latest + if: | + always() && ( # This ensures that this job runs even if the previous jobs failed + needs.testDesktopLinux.result == 'failure' || + needs.testDesktopMac.result == 'failure' || + needs.testDesktopWindows.result == 'failure' + ) + steps: + - name: Check for failures and raise an issue + uses: actions/github-script@v5 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const issueTitle = "Test failure on push to prod branch: commit ${{github.sha}}"; + const runURL = `https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}`; + let issueBody = `There was a test failure. Please investigate.\n\n[Check the failed run here](${runURL})\n\n`; + + if (needs.testDesktopLinux.result == 'failure') { + issueBody += " - Desktop Linux tests failed.\n"; + } + if (needs.testDesktopMac.result == 'failure') { + issueBody += " - Desktop MacOS tests failed.\n"; + } + if (needs.testDesktopWindows.result == 'failure') { + issueBody += " - Desktop Windows tests failed.\n"; + } + + github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: issueTitle, + body: issueBody + }); diff --git a/.github/workflows/staging-desktop-tests-on-push.yml b/.github/workflows/staging-desktop-tests-on-push.yml new file mode 100644 index 00000000..68ebc22c --- /dev/null +++ b/.github/workflows/staging-desktop-tests-on-push.yml @@ -0,0 +1,261 @@ +name: On-Push staging Win/Mac/Linux run full tests suite + +on: + push: + branches: [ staging ] + +permissions: + contents: read + issues: write + +jobs: + + testDesktopLinux: + runs-on: ubuntu-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: install dependencies (ubuntu only) + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf + sudo apt install build-essential curl wget file libssl-dev libayatana-appindicator3-dev + sudo apt-get install xvfb + + - name: npm install ci deps + run: npm ci + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:staging + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=unit -q + + - name: Run tauri integration tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=integration -q + + - name: Run tauri mainview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + + - name: Run tauri LegacyInteg tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 20 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + + testDesktopMac: + runs-on: macos-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: npm install ci deps + run: npm ci + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:staging + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q + + - name: Run tauri integration tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q + + - name: Run tauri mainview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + + - name: Run tauri LegacyInteg tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 30 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + + testDesktopWindows: + runs-on: windows-latest + timeout-minutes: 90 + steps: + - uses: actions/checkout@v3 + - name: setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: npm install ci deps + run: npm ci + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:staging + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests in windows + # GUI apps in windows doesn't log on console. so we capture the output to a text file and print it, then fail on error. + uses: nick-fields/retry@v2 + id: windowsRunUnit + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=unit -q > output-unit.txt 2>&1 + shell: cmd + + - name: Print windows unit test output to console + run: type output-unit.txt + shell: cmd + + - name: Run tauri integration tests in windows + uses: nick-fields/retry@v2 + id: windowsRunIntegration + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=integration -q > output-integration.txt 2>&1 + shell: cmd + + - name: Print windows integration test output to console + run: type output-integration.txt + shell: cmd + + - name: Run tauri mainview tests in windows + uses: nick-fields/retry@v2 + id: windowsRunMainview + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=mainview -q > output-mainview.txt 2>&1 + shell: cmd + + - name: Print windows mainview test output to console + run: type output-mainview.txt + shell: cmd + + - name: Run tauri LegacyInteg tests in windows + uses: nick-fields/retry@v2 + id: windowsRunLegacyInteg + continue-on-error: true + with: + timeout_minutes: 30 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=LegacyInteg -q > output-LegacyInteg.txt 2>&1 + shell: cmd + + - name: Print windows LegacyInteg test output to console + run: type output-LegacyInteg.txt + shell: cmd + + - name: Fail on test runs failed in windows + if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' + run: | + echo "Windows tests failed, marking step as failed" + exit 1 + shell: cmd + + raiseIssue: + needs: [ testDesktopLinux, testDesktopMac, testDesktopWindows] + runs-on: ubuntu-latest + if: | + always() && ( # This ensures that this job runs even if the previous jobs failed + needs.testDesktopLinux.result == 'failure' || + needs.testDesktopMac.result == 'failure' || + needs.testDesktopWindows.result == 'failure' + ) + steps: + - name: Check for failures and raise an issue + uses: actions/github-script@v5 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const issueTitle = "Test failure on push to staging branch: commit ${{github.sha}}"; + const runURL = `https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}`; + let issueBody = `There was a test failure. Please investigate.\n\n[Check the failed run here](${runURL})\n\n`; + + if (needs.testDesktopLinux.result == 'failure') { + issueBody += " - Desktop Linux tests failed.\n"; + } + if (needs.testDesktopMac.result == 'failure') { + issueBody += " - Desktop MacOS tests failed.\n"; + } + if (needs.testDesktopWindows.result == 'failure') { + issueBody += " - Desktop Windows tests failed.\n"; + } + + github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: issueTitle, + body: issueBody + }); From e6808f0a8c119b65b09dbb078b40edf4a5745bb8 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 24 Oct 2023 16:35:54 +0530 Subject: [PATCH 125/864] build: update package locks --- package-lock.json | 4 ++-- src-tauri/Cargo.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 13e459ac..1e9f05ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.2.8", + "version": "3.2.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.8", + "version": "3.2.10", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.2", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9d51218f..e9e39628 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2424,7 +2424,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.8" +version = "3.2.10" dependencies = [ "once_cell", "serde", From 6d12fab715a71850361bb248c239e493e9868133 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 26 Oct 2023 14:37:33 +0530 Subject: [PATCH 126/864] feat: custom phcode:// protocol instead of tauri protocol for cacheing and csp header rewrite in future --- src-build/ci-createDistReleaseConfig.js | 11 ++- src-build/createDistReleaseConfig.js | 9 +- src-build/createDistTestReleaseConfig.js | 9 +- src-build/createSrcReleaseConfig.js | 7 ++ src-tauri/Cargo.lock | 1 + src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 37 ++++++++ src-tauri/tauri.conf.json | 109 +++++++++++------------ 8 files changed, 121 insertions(+), 63 deletions(-) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index b1595fbc..93e129c9 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -66,13 +66,18 @@ async function ciCreateDistReleaseConfig() { console.log("write version in tauri.conf.json", tauriConfigPath); configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - configJson.build.distDir = '../phoenix/dist/' - // delete configJson.tauri.updater; // #uncomment_line_for_local_build_1 - // delete configJson.tauri.bundle.windows.certificateThumbprint // #uncomment_line_for_local_build_1 + configJson.build.distDir = '../phoenix/dist/'; + // configJson.tauri.bundle.active = false; // #uncomment_line_for_local_build_1 configJson.package.version = phoenixVersion; configJson.package.productName = _getProductName(configJson.package.productName, phoenixStage); console.log("Product name is: ", configJson.package.productName); configJson.tauri.windows[0].title = configJson.package.productName; + if(os.platform() === 'win32'){ + configJson.tauri.windows[0].url = "https://phcode.localhost/"; + } else { + configJson.tauri.windows[0].url = "phcode://localhost/"; + } + console.log("Window Boot url is: ", configJson.tauri.windows[0].url); configJson.tauri.updater.endpoints = [ `${UPDATE_NOTIFICATIONS_BASE_URL}${UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH[phoenixStage]}` ]; diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index 9a53aba2..411865ba 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -4,6 +4,7 @@ import fs from 'fs'; import chalk from 'chalk'; import {getPlatformDetails} from "./utils.js"; +import os from "os"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -18,7 +19,13 @@ async function createDistReleaseConfig() { let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; - configJson.build.distDir = '../../phoenix/dist/' + configJson.build.distDir = '../../phoenix/dist/'; + if(os.platform() === 'win32'){ + configJson.tauri.windows[0].url = "https://phcode.localhost/"; + } else { + configJson.tauri.windows[0].url = "phcode://localhost/"; + } + console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); } diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index da7d7895..753df83e 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -4,6 +4,7 @@ import fs from 'fs'; import {getPlatformDetails} from "./utils.js"; import chalk from "chalk"; +import os from "os"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -20,7 +21,13 @@ async function createDistTestReleaseConfig() { configJson.tauri.windows[0].title = "phoenix-tester"; console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; - configJson.build.distDir = '../../phoenix/dist-test/' + configJson.build.distDir = '../../phoenix/dist-test/'; + if(os.platform() === 'win32'){ + configJson.tauri.windows[0].url = "https://phcode.localhost/"; + } else { + configJson.tauri.windows[0].url = "phcode://localhost/"; + } + console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); } diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index 8f916c0b..e8124e35 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -1,6 +1,7 @@ import {fileURLToPath} from "url"; import {dirname} from "path"; import fs from 'fs'; +import * as os from 'os'; import {getPlatformDetails} from "./utils.js"; import chalk from "chalk"; @@ -19,6 +20,12 @@ async function createSrcReleaseConfig() { console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/src/' + if(os.platform() === 'win32'){ + configJson.tauri.windows[0].url = "https://phcode.localhost/"; + } else { + configJson.tauri.windows[0].url = "phcode://localhost/"; + } + console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e9e39628..f4cd6d57 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2427,6 +2427,7 @@ name = "phoenix-code-ide" version = "3.2.10" dependencies = [ "once_cell", + "percent-encoding", "serde", "serde_json", "tauri", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 264a29a1..5a9de439 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,6 +16,7 @@ tauri-build = { version = "1.5.0", features = [] } [dependencies] serde_json = "1.0" once_cell = "1.18.0" +percent-encoding = "2.1" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.2", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 4d865b95..f745df9f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,6 +3,8 @@ all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows" )] +extern crate percent_encoding; +use tauri::http::ResponseBuilder; use tauri::GlobalWindowEvent; mod init; mod utilities; @@ -55,6 +57,41 @@ fn process_window_event(event: &GlobalWindowEvent) { fn main() { tauri::Builder::default() + .register_uri_scheme_protocol("phcode", move |app, request| { // can't use `tauri` because that's already in use + let path = request.uri().strip_prefix("phcode://localhost").unwrap(); + let path = percent_encoding::percent_decode(path.as_bytes()) + .decode_utf8_lossy() + .to_string(); + // Remove query string and fragment + let path_without_query_or_fragment = path.split('?').next().unwrap_or(&path); + let final_path = path_without_query_or_fragment.split('#').next().unwrap_or(path_without_query_or_fragment).to_string(); + + let asset_option = app.asset_resolver().get(final_path.clone()); + if asset_option.is_none() { + let not_found_response = ResponseBuilder::new() + .status(404) + .mimetype("text/html") + .body("Asset not found".as_bytes().to_vec()) + .unwrap(); + return Ok(not_found_response); + } + + let asset = asset_option.unwrap(); + + #[cfg(windows)] + let window_origin = "https://phcode.localhost"; + #[cfg(not(windows))] + let window_origin = "phcode://localhost"; + + let builder = ResponseBuilder::new() + .header("Access-Control-Allow-Origin", window_origin) + .header("Origin", window_origin) + .header("Cache-Control", "private, max-age=31536000, immutable") // 1 year cache age expiry + .mimetype(&asset.mime_type); + + let response = builder.body(asset.bytes)?; + Ok(response) + }) .plugin(tauri_plugin_fs_extra::init()) .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 817c3981..d61c82d6 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -16,62 +16,38 @@ "all": true, "fs": { "all": true, - "scope": [ - "$APPCONFIG/**", - "$APPDATA/**", - "$APPLOCALDATA/**", - "$APPCACHE/**", - "$APPLOG/**", - "$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/**/*.*", - "$AUDIO/**/*.*", - "$CACHE/**/*.*", - "$CONFIG/**/*.*", - "$DATA/**/*.*", - "$LOCALDATA/**/*.*", - "$DESKTOP/**/*.*", - "$DOCUMENT/**/*.*", - "$DOWNLOAD/**/*.*", - "$EXE/**/*.*", - "$FONT/**/*.*", - "$HOME/**/*.*", - "$PICTURE/**/*.*", - "$PUBLIC/**/*.*", - "$RUNTIME/**/*.*", - "$TEMPLATE/**/*.*", - "$VIDEO/**/*.*", - "$RESOURCE/**/*.*", - "$APP/**/*.*", - "$LOG/**/*.*", - "$TEMP/**/*.*", - "**/*.*", - "**/**/*.*" - ] + "scope":{ + "allow": [ + "$APPCONFIG/**", + "$APPDATA/**", + "$APPLOCALDATA/**", + "$APPCACHE/**", + "$APPLOG/**", + "$AUDIO/**", + "$CACHE/**", + "$CONFIG/**", + "$DATA/**", + "$LOCALDATA/**", + "$DESKTOP/**", + "$DOCUMENT/**", + "$DOWNLOAD/**", + "$EXE/**", + "$FONT/**", + "$HOME/**", + "$PICTURE/**", + "$PUBLIC/**", + "$RUNTIME/**", + "$TEMPLATE/**", + "$VIDEO/**", + "$RESOURCE/**", + "$APP/**", + "$LOG/**", + "$TEMP/**", + "**", + "**/**" + ], + "requireLiteralLeadingDot": false + } }, "protocol": { "asset": true, @@ -79,7 +55,8 @@ "allow": [ "$APPLOCALDATA/assets/**", "$APPLOCALDATA/assets/**/*.*" - ] + ], + "requireLiteralLeadingDot": false } }, "shell": { @@ -241,7 +218,23 @@ }, "security": { "csp": null, - "dangerousDisableAssetCspModification": true + "dangerousDisableAssetCspModification": true, + "dangerousRemoteDomainIpcAccess": [ + { + "scheme": "phcode", + "domain": "localhost", + "enableTauriAPI": true, + "plugins": ["fs-extra"], + "windows": ["main"] + }, + { + "scheme": "https", + "domain": "phcode.localhost", + "enableTauriAPI": true, + "plugins": ["fs-extra"], + "windows": ["main"] + } + ] }, "updater": { "active": true, From 36a83f9ab94fe510667d9f6a7ce4d10e246d8b9b Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 26 Oct 2023 10:44:09 +0000 Subject: [PATCH 127/864] ci: update phcode version to 3.2.11 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 20 ++++++++++++++------ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 988a97cc..aadab5ed 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.10", + "version": "3.2.11", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "53bb60c25b662b30d52ee39b8019dbd11a895151" + "commit": "76237ba61bb1a9b2dccff2afaad751f6bd04f87c" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5a9de439..7fdbe105 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.10" +version = "3.2.11" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index d61c82d6..a89e2dd3 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,14 +9,14 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.10" + "version": "3.2.11" }, "tauri": { "allowlist": { "all": true, "fs": { "all": true, - "scope":{ + "scope": { "allow": [ "$APPCONFIG/**", "$APPDATA/**", @@ -224,15 +224,23 @@ "scheme": "phcode", "domain": "localhost", "enableTauriAPI": true, - "plugins": ["fs-extra"], - "windows": ["main"] + "plugins": [ + "fs-extra" + ], + "windows": [ + "main" + ] }, { "scheme": "https", "domain": "phcode.localhost", "enableTauriAPI": true, - "plugins": ["fs-extra"], - "windows": ["main"] + "plugins": [ + "fs-extra" + ], + "windows": [ + "main" + ] } ] }, From 0ac7593f4aa808d947d896b66333082cab0810ba Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 26 Oct 2023 10:46:29 +0000 Subject: [PATCH 128/864] fix(deps): update rust crate percent-encoding to 2.3 --- src-tauri/Cargo.lock | 2 +- src-tauri/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f4cd6d57..be52580c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2424,7 +2424,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.10" +version = "3.2.11" dependencies = [ "once_cell", "percent-encoding", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 7fdbe105..860477d1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,7 +16,7 @@ tauri-build = { version = "1.5.0", features = [] } [dependencies] serde_json = "1.0" once_cell = "1.18.0" -percent-encoding = "2.1" +percent-encoding = "2.3" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.2", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } From ad455e66ba19b1aa037e4414ec24eec17fbf77de Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 27 Oct 2023 15:31:46 +0530 Subject: [PATCH 129/864] feat: show_in_folder api to open file in system explorer --- src-tauri/src/main.rs | 56 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index f745df9f..dc6c1971 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,6 +3,11 @@ all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows" )] +#[cfg(target_os = "linux")] +use std::fs::metadata; +use std::path::PathBuf; +use std::process::Command; + extern crate percent_encoding; use tauri::http::ResponseBuilder; use tauri::GlobalWindowEvent; @@ -48,6 +53,55 @@ fn toggle_devtools(window: tauri::Window) { } } +#[tauri::command] +fn show_in_folder(path: String) { + #[cfg(target_os = "windows")] + { + Command::new("explorer") + .args(["/select,", &path]) // The comma after select is not a typo + .spawn() + .unwrap(); + } + + #[cfg(target_os = "linux")] + { + if path.contains(",") { + // see https://gitlab.freedesktop.org/dbus/dbus/-/issues/76 + let new_path = match metadata(&path).unwrap().is_dir() { + true => path, + false => { + let mut path2 = PathBuf::from(path); + path2.pop(); + path2.into_os_string().into_string().unwrap() + } + }; + Command::new("xdg-open") + .arg(&new_path) + .spawn() + .unwrap(); + } else { + Command::new("dbus-send") + .arg("--session") + .arg("--dest=org.freedesktop.FileManager1") + .arg("--type=method_call") + .arg("/org/freedesktop/FileManager1") + .arg("org.freedesktop.FileManager1.ShowItems") + .arg(format!("array:string:file:///{}", path)) + .arg("string:\"\"") + .spawn() + .unwrap(); + } + } + + #[cfg(target_os = "macos")] + { + Command::new("open") + .args(["-R", &path]) + .spawn() + .unwrap(); + } +} + fn process_window_event(event: &GlobalWindowEvent) { if let tauri::WindowEvent::CloseRequested { .. } = event.event() { let size = event.window().inner_size().unwrap(); @@ -96,7 +150,7 @@ fn main() { .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ toggle_devtools, console_log, console_error, - _get_windows_drives, _rename_path]) + _get_windows_drives, _rename_path, show_in_folder]) .setup(|app| { init::init_app(app); Ok(()) From 9de84ed4f325fc786df98d90ecc7b805a5869c0e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 10:17:01 +0000 Subject: [PATCH 130/864] chore(deps): update actions/setup-node action to v4 --- .github/workflows/desktop-linux-test-pull.yml | 2 +- .github/workflows/desktop-mac-test-pull.yml | 2 +- .github/workflows/desktop-windows-test-pull.yml | 2 +- .github/workflows/prod-desktop-tests-on-push.yml | 6 +++--- .github/workflows/staging-desktop-tests-on-push.yml | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index 02cd35ff..c7c317bf 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: install Rust stable diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index a07c7e47..634feb3a 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: install Rust stable diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index 6e9cf1ae..b8916eff 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -12,7 +12,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: install Rust stable diff --git a/.github/workflows/prod-desktop-tests-on-push.yml b/.github/workflows/prod-desktop-tests-on-push.yml index ffb6f67c..764ebd16 100644 --- a/.github/workflows/prod-desktop-tests-on-push.yml +++ b/.github/workflows/prod-desktop-tests-on-push.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: install Rust stable @@ -80,7 +80,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: install Rust stable @@ -137,7 +137,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: install Rust stable diff --git a/.github/workflows/staging-desktop-tests-on-push.yml b/.github/workflows/staging-desktop-tests-on-push.yml index 68ebc22c..769254e6 100644 --- a/.github/workflows/staging-desktop-tests-on-push.yml +++ b/.github/workflows/staging-desktop-tests-on-push.yml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: install Rust stable @@ -80,7 +80,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: install Rust stable @@ -137,7 +137,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: 18 - name: install Rust stable From 5a7a3eaac75a3761aaba54759f532146e42294b1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 08:11:27 +0000 Subject: [PATCH 131/864] chore(deps): update actions/checkout action to v4 --- .github/workflows/desktop-linux-test-pull.yml | 2 +- .github/workflows/desktop-mac-test-pull.yml | 2 +- .github/workflows/desktop-windows-test-pull.yml | 2 +- .github/workflows/prod-desktop-tests-on-push.yml | 6 +++--- .github/workflows/staging-desktop-tests-on-push.yml | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index c7c317bf..ff4422f7 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 634feb3a..1b354ee6 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -10,7 +10,7 @@ jobs: runs-on: macos-latest timeout-minutes: 90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index b8916eff..8083965a 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -10,7 +10,7 @@ jobs: runs-on: windows-latest timeout-minutes: 90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: diff --git a/.github/workflows/prod-desktop-tests-on-push.yml b/.github/workflows/prod-desktop-tests-on-push.yml index 764ebd16..e660ef83 100644 --- a/.github/workflows/prod-desktop-tests-on-push.yml +++ b/.github/workflows/prod-desktop-tests-on-push.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: @@ -78,7 +78,7 @@ jobs: runs-on: macos-latest timeout-minutes: 90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: @@ -135,7 +135,7 @@ jobs: runs-on: windows-latest timeout-minutes: 90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: diff --git a/.github/workflows/staging-desktop-tests-on-push.yml b/.github/workflows/staging-desktop-tests-on-push.yml index 769254e6..2d63c9b8 100644 --- a/.github/workflows/staging-desktop-tests-on-push.yml +++ b/.github/workflows/staging-desktop-tests-on-push.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: @@ -78,7 +78,7 @@ jobs: runs-on: macos-latest timeout-minutes: 90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: @@ -135,7 +135,7 @@ jobs: runs-on: windows-latest timeout-minutes: 90 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: setup node uses: actions/setup-node@v4 with: From 7a8430e9ed06de71524ed89b017210939e635554 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 25 Oct 2023 08:11:31 +0000 Subject: [PATCH 132/864] chore(deps): update actions/github-script action to v6 --- .github/workflows/prod-desktop-tests-on-push.yml | 2 +- .github/workflows/staging-desktop-tests-on-push.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/prod-desktop-tests-on-push.yml b/.github/workflows/prod-desktop-tests-on-push.yml index e660ef83..b8910ee3 100644 --- a/.github/workflows/prod-desktop-tests-on-push.yml +++ b/.github/workflows/prod-desktop-tests-on-push.yml @@ -235,7 +235,7 @@ jobs: ) steps: - name: Check for failures and raise an issue - uses: actions/github-script@v5 + uses: actions/github-script@v6 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | diff --git a/.github/workflows/staging-desktop-tests-on-push.yml b/.github/workflows/staging-desktop-tests-on-push.yml index 2d63c9b8..4922550f 100644 --- a/.github/workflows/staging-desktop-tests-on-push.yml +++ b/.github/workflows/staging-desktop-tests-on-push.yml @@ -235,7 +235,7 @@ jobs: ) steps: - name: Check for failures and raise an issue - uses: actions/github-script@v5 + uses: actions/github-script@v6 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | From 266dcee51b180bf4b0c5cd7c9b6a2ca5d3b89b0b Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 31 Oct 2023 19:13:42 +0530 Subject: [PATCH 133/864] chore: cache bursting using version prefixes --- src-build/ci-createDistReleaseConfig.js | 4 ++-- src-build/createDistReleaseConfig.js | 5 ++-- src-build/createDistTestReleaseConfig.js | 5 ++-- src-build/createSrcReleaseConfig.js | 5 ++-- src-tauri/Cargo.lock | 29 +++++++++++++++++------- src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 10 +++++++- 7 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index 93e129c9..22a589d6 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -73,9 +73,9 @@ async function ciCreateDistReleaseConfig() { console.log("Product name is: ", configJson.package.productName); configJson.tauri.windows[0].title = configJson.package.productName; if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = "https://phcode.localhost/"; + configJson.tauri.windows[0].url = `https://phcode.localhost/v${phoenixVersion}/`; } else { - configJson.tauri.windows[0].url = "phcode://localhost/"; + configJson.tauri.windows[0].url = `phcode://localhost/v${phoenixVersion}/`; } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); configJson.tauri.updater.endpoints = [ diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index 411865ba..dade900f 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -20,10 +20,11 @@ async function createDistReleaseConfig() { console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist/'; + const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = "https://phcode.localhost/"; + configJson.tauri.windows[0].url = `https://phcode.localhost/v${phoenixVersion}/`; } else { - configJson.tauri.windows[0].url = "phcode://localhost/"; + configJson.tauri.windows[0].url = `phcode://localhost/v${phoenixVersion}/`; } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index 753df83e..d754aea3 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -22,10 +22,11 @@ async function createDistTestReleaseConfig() { console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist-test/'; + const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = "https://phcode.localhost/"; + configJson.tauri.windows[0].url = `https://phcode.localhost/v${phoenixVersion}/`; } else { - configJson.tauri.windows[0].url = "phcode://localhost/"; + configJson.tauri.windows[0].url = `phcode://localhost/v${phoenixVersion}/`; } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index e8124e35..b2a08928 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -20,10 +20,11 @@ async function createSrcReleaseConfig() { console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/src/' + const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = "https://phcode.localhost/"; + configJson.tauri.windows[0].url = `https://phcode.localhost/v${phoenixVersion}/`; } else { - configJson.tauri.windows[0].url = "phcode://localhost/"; + configJson.tauri.windows[0].url = `phcode://localhost/v${phoenixVersion}/`; } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index be52580c..d763d265 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1876,7 +1876,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -1887,9 +1887,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -2428,6 +2428,7 @@ version = "3.2.11" dependencies = [ "once_cell", "percent-encoding", + "regex", "serde", "serde_json", "tauri", @@ -2703,13 +2704,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick 1.0.2", "memchr", - "regex-syntax 0.7.2", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -2721,6 +2723,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick 1.0.2", + "memchr", + "regex-syntax 0.8.2", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -2729,9 +2742,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 860477d1..e8c9f0da 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,6 +17,7 @@ tauri-build = { version = "1.5.0", features = [] } serde_json = "1.0" once_cell = "1.18.0" percent-encoding = "2.3" +regex = "1.9.1" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.2", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index dc6c1971..1a14a47c 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -8,6 +8,7 @@ use std::fs::metadata; use std::path::PathBuf; use std::process::Command; +use regex::Regex; extern crate percent_encoding; use tauri::http::ResponseBuilder; use tauri::GlobalWindowEvent; @@ -109,10 +110,17 @@ fn process_window_event(event: &GlobalWindowEvent) { } } +// convert url of form "protocol://host/v1.2.3/path/to/something" to "protocol://host/path/to/something" +fn remove_version_from_url(url: &str) -> String { + let re = Regex::new(r"([a-zA-Z]+://[^/]+)/v[\d+\.]+/").unwrap(); + re.replace(url, "$1/").to_string() +} + fn main() { tauri::Builder::default() .register_uri_scheme_protocol("phcode", move |app, request| { // can't use `tauri` because that's already in use - let path = request.uri().strip_prefix("phcode://localhost").unwrap(); + let path = remove_version_from_url(request.uri()); + let path = path.strip_prefix("phcode://localhost").unwrap(); let path = percent_encoding::percent_decode(path.as_bytes()) .decode_utf8_lossy() .to_string(); From c646cd243657c952e8339616b5c5ceee0f6fd6f2 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 31 Oct 2023 19:40:35 +0530 Subject: [PATCH 134/864] chore: change cache ttl to 3 months instead of a year --- src-tauri/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1a14a47c..5eb3710a 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -148,7 +148,7 @@ fn main() { let builder = ResponseBuilder::new() .header("Access-Control-Allow-Origin", window_origin) .header("Origin", window_origin) - .header("Cache-Control", "private, max-age=31536000, immutable") // 1 year cache age expiry + .header("Cache-Control", "private, max-age=7776000, immutable") // 3 month cache age expiry .mimetype(&asset.mime_type); let response = builder.body(asset.bytes)?; From d50fb98c6b15a3ed04febd2fc08b53bee2ae3bd2 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 31 Oct 2023 19:54:39 +0530 Subject: [PATCH 135/864] chore: 30 tauri windows can use tauri apis at a time --- src-tauri/tauri.conf.json | 65 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a89e2dd3..0b6dafb1 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -228,8 +228,39 @@ "fs-extra" ], "windows": [ - "main" + "main", + "phcode-1", + "phcode-2", + "phcode-3", + "phcode-4", + "phcode-5", + "phcode-6", + "phcode-7", + "phcode-8", + "phcode-9", + "phcode-10", + "phcode-11", + "phcode-12", + "phcode-13", + "phcode-14", + "phcode-15", + "phcode-16", + "phcode-17", + "phcode-18", + "phcode-19", + "phcode-20", + "phcode-21", + "phcode-22", + "phcode-23", + "phcode-24", + "phcode-25", + "phcode-26", + "phcode-27", + "phcode-28", + "phcode-29", + "phcode-30" ] + }, { "scheme": "https", @@ -239,7 +270,37 @@ "fs-extra" ], "windows": [ - "main" + "main", + "phcode-1", + "phcode-2", + "phcode-3", + "phcode-4", + "phcode-5", + "phcode-6", + "phcode-7", + "phcode-8", + "phcode-9", + "phcode-10", + "phcode-11", + "phcode-12", + "phcode-13", + "phcode-14", + "phcode-15", + "phcode-16", + "phcode-17", + "phcode-18", + "phcode-19", + "phcode-20", + "phcode-21", + "phcode-22", + "phcode-23", + "phcode-24", + "phcode-25", + "phcode-26", + "phcode-27", + "phcode-28", + "phcode-29", + "phcode-30" ] } ] From 210394d01d098537f88754bc1b925350631c3882 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 31 Oct 2023 14:59:44 +0000 Subject: [PATCH 136/864] fix(deps): update rust crate regex to 1.10.2 --- src-tauri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index e8c9f0da..4e8e56e6 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,7 +17,7 @@ tauri-build = { version = "1.5.0", features = [] } serde_json = "1.0" once_cell = "1.18.0" percent-encoding = "2.3" -regex = "1.9.1" +regex = "1.10.2" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.2", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } From fe7b398c1fb207e5433b2e43da0f5253c60e02cc Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 31 Oct 2023 22:34:12 +0530 Subject: [PATCH 137/864] feat: download node from git repo --- package-lock.json | 350 +++++++++++++++++++++++++++++++- package.json | 4 +- src-build/downloadNodeBinary.js | 128 ++++++------ 3 files changed, 416 insertions(+), 66 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1e9f05ea..f1e0dd06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,22 @@ { "name": "phoenix-code-ide", - "version": "3.2.10", + "version": "3.2.11", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.10", + "version": "3.2.11", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.2", "adm-zip": "0.5.10", + "axios": "1.6.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", "fs-extra": "11.1.1", + "progress-stream": "2.0.0", "shx": "^0.3.4", "tar": "6.2.0" } @@ -250,6 +252,23 @@ "node": ">= 8" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -388,12 +407,30 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -417,6 +454,15 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -470,6 +516,40 @@ "node": ">=6" } }, + "node_modules/follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs-extra": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", @@ -705,6 +785,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -754,6 +840,27 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -974,6 +1081,43 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/progress-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-2.0.0.tgz", + "integrity": "sha512-xJwOWR46jcXUq6EH9yYyqp+I52skPySOeHfkxOZ2IY1AiBi/sFJhbhAKHoV3OTw/omQ45KTio9215dRJ2Yxd3Q==", + "dev": true, + "dependencies": { + "speedometer": "~1.0.0", + "through2": "~2.0.3" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1030,6 +1174,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -1102,6 +1252,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/speedometer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-1.0.0.tgz", + "integrity": "sha512-lgxErLl/7A5+vgIIXsh9MbeukOaCb2axgQ+bKCdIE+ibNT4XNYGNCR1qFEGq6F+YDASXK3Fh/c5FgtZchFolxw==", + "dev": true + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -1169,6 +1334,16 @@ "node": ">=10" } }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1190,6 +1365,12 @@ "node": ">= 10.0.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1231,6 +1412,15 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -1392,6 +1582,23 @@ "picomatch": "^2.0.4" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "dev": true, + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1495,12 +1702,27 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1518,6 +1740,12 @@ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -1559,6 +1787,23 @@ "locate-path": "^3.0.0" } }, + "follow-redirects": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "dev": true + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fs-extra": { "version": "11.1.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", @@ -1729,6 +1974,12 @@ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1773,6 +2024,21 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, "mimic-fn": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", @@ -1922,6 +2188,43 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-2.0.0.tgz", + "integrity": "sha512-xJwOWR46jcXUq6EH9yYyqp+I52skPySOeHfkxOZ2IY1AiBi/sFJhbhAKHoV3OTw/omQ45KTio9215dRJ2Yxd3Q==", + "dev": true, + "requires": { + "speedometer": "~1.0.0", + "through2": "~2.0.3" + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1963,6 +2266,12 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -2011,6 +2320,21 @@ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true }, + "speedometer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-1.0.0.tgz", + "integrity": "sha512-lgxErLl/7A5+vgIIXsh9MbeukOaCb2axgQ+bKCdIE+ibNT4XNYGNCR1qFEGq6F+YDASXK3Fh/c5FgtZchFolxw==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -2057,6 +2381,16 @@ "yallist": "^4.0.0" } }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2072,6 +2406,12 @@ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2104,6 +2444,12 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", diff --git a/package.json b/package.json index aadab5ed..15c3add0 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,9 @@ "execa": "^8.0.0", "fs-extra": "11.1.1", "shx": "^0.3.4", - "tar": "6.2.0" + "tar": "6.2.0", + "axios": "1.6.0", + "progress-stream":"2.0.0" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index ae4057d1..1c824ac7 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -7,38 +7,12 @@ import {fileURLToPath} from 'url'; import {dirname} from 'path'; import * as fsExtra from "fs-extra"; import {getPlatformDetails, getSideCarBinName, removeDir} from "./utils.js"; +import axios from 'axios'; +import progress from 'progress-stream'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -const LTS_URL_PREFIX = 'https://nodejs.org/dist/latest-v18.x/'; - -/** - Fetches the latest Node.js version by making a request to a specified URL. - @returns {Promise} A promise that resolves with the latest Node.js version string on success, - or rejects with an error if the latest version cannot be found. - */ -async function fetchLatestNodeVersion() { - return new Promise((resolve, reject) => { - https.get(LTS_URL_PREFIX, (res) => { - let data = ''; - - res.on('data', (chunk) => { - data += chunk; - }); - res.on('end', () => { - - const versionMatch = /node-v(\d+\.\d+\.\d+)/.exec(data); - if (versionMatch) { - resolve(versionMatch[1]); - } else { - reject(new Error('Could not find latest Node.js version')); - } - }); - }).on('error', reject); - }); -} - /** * Downloads a Node.js binary file from a specified version, platform, and architecture. * @param {string} version - The version of Node.js to download (e.g., "14.17.0"). @@ -48,45 +22,74 @@ async function fetchLatestNodeVersion() { * @throws {Error} - If the file fails to download after the maximum number of retries. */ -async function downloadNodeBinary(version, platform, arch) { - const extension = (platform === "win") ? "zip" : "tar.gz"; - const fileName = `node-v${version}-${platform}-${arch}.${extension}`; +async function downloadNodeBinary(platform, arch, maxRetries = 3) { + try { + // Step 1: Get the latest release information from phcode-dev/phnode + const url = 'https://api.github.com/repos/phcode-dev/phnode/releases/latest'; + const releaseResponse = await axios.get(url); - const fullPath = `${__dirname}/${fileName}` - // Check if the file already exists - if (fs.existsSync(fullPath)) { - console.log(`File ${fileName} already exists. No need to download.`); - return fileName; - } - const MAX_RETRIES = 3 - console.log(`downloading node ${version} for ${platform} ${arch}`); - for (let attempt = 0; attempt < MAX_RETRIES; attempt++) { - try { - const file = fs.createWriteStream(fullPath); - await new Promise((resolve, reject) => { - const downloadUrl = `${LTS_URL_PREFIX}node-v${version}-${platform}-${arch}.${extension}`; - console.log(downloadUrl); - https.get(downloadUrl, (res) => { - res.pipe(file); - res.on('end', () => resolve(fileName)); - res.on('error', (err) => { - fs.unlinkSync(fileName); // Remove the file on error - reject(err); - }); - }); + // Determine file extension based on platform + const extension = platform === 'win' ? 'zip' : 'tar.gz'; + + // Adjusting the regex pattern to match the new file name format + const regex = new RegExp(`node-v[\\d.]+-${platform}-${arch}\\.${extension}`); + const asset = releaseResponse.data.assets.find(a => regex.test(a.name)); + + if (!asset) { + throw new Error(`No asset found for platform: ${platform}, arch: ${arch}`); + } + + // Step 2: Check if file already exists + const outputPath = path.resolve(__dirname, asset.name); + if (fs.existsSync(outputPath)) { + console.log('File already downloaded:', asset.name); + return asset.name; + } + + // Step 3: Download the asset with progress + const writer = fs.createWriteStream(outputPath); + const { data, headers } = await axios({ + url: asset.browser_download_url, + method: 'GET', + responseType: 'stream', + timeout: 10000 // timeout in 10 seconds + }); + + const str = progress({ + length: headers['content-length'], + time: 100 /* ms */ + }); + + str.on('progress', progress => { + process.stdout.clearLine(0); + process.stdout.cursorTo(0); + process.stdout.write(`Downloading... ${Math.round(progress.percentage)}%`); + }); + + data.pipe(str).pipe(writer); + + return new Promise((resolve, reject) => { + writer.on('finish', () => { + console.log('\nDownload completed:', asset.name); + resolve(asset.name); }); - return fileName; // If the download was successful, return the file name - } catch (err) { - console.error(`Download attempt ${attempt + 1} failed.`); - if (attempt < MAX_RETRIES - 1) { - console.log(`Retrying download...`); - } + writer.on('error', err => { + fs.unlinkSync(outputPath); // remove the partially downloaded file + reject(err); + }); + }); + + } catch (err) { + console.error('Error:', err.message); + if (maxRetries > 0) { + console.log('Retrying download...'); + return downloadNodeBinary(platform, arch, maxRetries - 1); + } else { + throw new Error('Max retries reached, download failed.'); } } - throw new Error(`Failed to download file after ${MAX_RETRIES} attempts.`); } - /** * Extracts a tar archive file to the specified output directory. * @param {string} inputFile - The path of the tar archive file to be extracted. @@ -171,8 +174,7 @@ function unzipFile(zipFilePath, extractPath) { * @returns {Promise} - A Promise that resolves when the Node.js binary is copied successfully. */ async function copyLatestNodeForBuild(platform, arch) { - const version = await fetchLatestNodeVersion(); - const fileName = await downloadNodeBinary(version, platform, arch); + const fileName = await downloadNodeBinary(platform, arch); const fullPath = (platform === "win") ? `${__dirname}\\${fileName}` : `${__dirname}/${fileName}`; let nodeFolder = ""; From 2d8ed6e77ad8299af557b3c48359d5efc41ff10e Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 31 Oct 2023 22:37:08 +0530 Subject: [PATCH 138/864] doc: update jsdoc for downloadNodeBinary --- src-build/downloadNodeBinary.js | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index 1c824ac7..d991e8d4 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -14,14 +14,25 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); /** - * Downloads a Node.js binary file from a specified version, platform, and architecture. - * @param {string} version - The version of Node.js to download (e.g., "14.17.0"). - * @param {string} platform - The platform for which to download the binary (e.g., "win","linux","darwin"). - * @param {string} arch - The architecture for which to download the binary (e.g., "x64","arm64"). - * @returns {Promise} - A Promise that resolves to the downloaded file name if successful. - * @throws {Error} - If the file fails to download after the maximum number of retries. + * Downloads the latest Node.js binary for the specified platform and architecture. + * If the file already exists, it will not be downloaded again. If the download fails, + * the function will retry up to the maximum specified number of retries. + * + * @param {string} platform - The operating system for which to download the Node.js binary. + * Possible values are 'darwin', 'win', and 'linux'. + * @param {string} arch - The architecture for which to download the Node.js binary. + * Possible values are 'arm64' and 'x64'. + * @param {number} [maxRetries=3] - The maximum number of times to retry the download + * in case of failure. Defaults to 3. + * + * @returns {Promise} A promise that resolves to the name of the downloaded file + * (not the full path), or rejects with an error message. + * + * @example + * downloadNodeBinary('darwin', 'x64') + * .then(fileName => console.log('Downloaded:', fileName)) + * .catch(err => console.error('Download failed:', err)); */ - async function downloadNodeBinary(platform, arch, maxRetries = 3) { try { // Step 1: Get the latest release information from phcode-dev/phnode From 0cfd215554e3308eea21de8309b6112ff961bed5 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 31 Oct 2023 23:01:23 +0530 Subject: [PATCH 139/864] fix: process.stdout.clearLine is not a function --- src-build/downloadNodeBinary.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index d991e8d4..b426dc76 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -72,9 +72,14 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { }); str.on('progress', progress => { - process.stdout.clearLine(0); - process.stdout.cursorTo(0); + if (process.stdout.isTTY) { + process.stdout.clearLine(0); + process.stdout.cursorTo(0); + } process.stdout.write(`Downloading... ${Math.round(progress.percentage)}%`); + if (!process.stdout.isTTY) { + process.stdout.write('\n'); + } }); data.pipe(str).pipe(writer); From 0ed6b43827baded75a8e1c4f79ded61f3b60cfa5 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 31 Oct 2023 23:09:03 +0530 Subject: [PATCH 140/864] fix: unable to see progress of download in github action --- src-build/downloadNodeBinary.js | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index b426dc76..1356eab4 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -35,14 +35,9 @@ const __dirname = dirname(__filename); */ async function downloadNodeBinary(platform, arch, maxRetries = 3) { try { - // Step 1: Get the latest release information from phcode-dev/phnode const url = 'https://api.github.com/repos/phcode-dev/phnode/releases/latest'; const releaseResponse = await axios.get(url); - - // Determine file extension based on platform const extension = platform === 'win' ? 'zip' : 'tar.gz'; - - // Adjusting the regex pattern to match the new file name format const regex = new RegExp(`node-v[\\d.]+-${platform}-${arch}\\.${extension}`); const asset = releaseResponse.data.assets.find(a => regex.test(a.name)); @@ -50,35 +45,31 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { throw new Error(`No asset found for platform: ${platform}, arch: ${arch}`); } - // Step 2: Check if file already exists const outputPath = path.resolve(__dirname, asset.name); if (fs.existsSync(outputPath)) { console.log('File already downloaded:', asset.name); return asset.name; } - // Step 3: Download the asset with progress const writer = fs.createWriteStream(outputPath); const { data, headers } = await axios({ url: asset.browser_download_url, method: 'GET', responseType: 'stream', - timeout: 10000 // timeout in 10 seconds + timeout: 10000 }); const str = progress({ length: headers['content-length'], - time: 100 /* ms */ + time: 100 }); + let lastLoggedPercentage = -1; str.on('progress', progress => { - if (process.stdout.isTTY) { - process.stdout.clearLine(0); - process.stdout.cursorTo(0); - } - process.stdout.write(`Downloading... ${Math.round(progress.percentage)}%`); - if (!process.stdout.isTTY) { - process.stdout.write('\n'); + const percentage = Math.round(progress.percentage); + if (percentage !== lastLoggedPercentage && percentage % 10 === 0) { + console.log(`Downloading... ${percentage}%`); + lastLoggedPercentage = percentage; } }); From 65246addbdcff5be3b53e8620e19f7cbfff98335 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 31 Oct 2023 23:21:03 +0530 Subject: [PATCH 141/864] fix: removed download progress --- src-build/downloadNodeBinary.js | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index 1356eab4..814d8262 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -52,32 +52,18 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { } const writer = fs.createWriteStream(outputPath); - const { data, headers } = await axios({ + const { data } = await axios({ url: asset.browser_download_url, method: 'GET', responseType: 'stream', timeout: 10000 }); - const str = progress({ - length: headers['content-length'], - time: 100 - }); - - let lastLoggedPercentage = -1; - str.on('progress', progress => { - const percentage = Math.round(progress.percentage); - if (percentage !== lastLoggedPercentage && percentage % 10 === 0) { - console.log(`Downloading... ${percentage}%`); - lastLoggedPercentage = percentage; - } - }); - - data.pipe(str).pipe(writer); + data.pipe(writer); return new Promise((resolve, reject) => { writer.on('finish', () => { - console.log('\nDownload completed:', asset.name); + console.log('Download completed:', asset.name); resolve(asset.name); }); writer.on('error', err => { @@ -97,6 +83,7 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { } } + /** * Extracts a tar archive file to the specified output directory. * @param {string} inputFile - The path of the tar archive file to be extracted. @@ -246,4 +233,4 @@ console.log(args); const platformDetails = (args.length === 1) ? JSON.parse(args[0]) : getPlatformDetails(); console.log(platformDetails); -await copyLatestNodeForBuild(platformDetails.platform, platformDetails.arch); +await copyLatestNodeForBuild(platformDetails.platform, platformDetails.arch); \ No newline at end of file From f4e4612f172e75e9a6b2313808383273bc748604 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 31 Oct 2023 23:44:33 +0530 Subject: [PATCH 142/864] chore: add dummy commit --- src-build/downloadNodeBinary.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index 814d8262..0b8a6964 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -33,6 +33,7 @@ const __dirname = dirname(__filename); * .then(fileName => console.log('Downloaded:', fileName)) * .catch(err => console.error('Download failed:', err)); */ + async function downloadNodeBinary(platform, arch, maxRetries = 3) { try { const url = 'https://api.github.com/repos/phcode-dev/phnode/releases/latest'; From 5895cd221887a779fd6316723dc85214c0f7ee56 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 1 Nov 2023 00:58:34 +0530 Subject: [PATCH 143/864] chore: code clean up --- package.json | 3 +-- src-build/downloadNodeBinary.js | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/package.json b/package.json index 15c3add0..b94e858b 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,7 @@ "fs-extra": "11.1.1", "shx": "^0.3.4", "tar": "6.2.0", - "axios": "1.6.0", - "progress-stream":"2.0.0" + "axios": "1.6.0" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index 0b8a6964..4359f56e 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -1,4 +1,3 @@ -import * as https from "https"; import * as fs from "fs"; import tar from "tar"; import * as path from "path"; @@ -8,7 +7,6 @@ import {dirname} from 'path'; import * as fsExtra from "fs-extra"; import {getPlatformDetails, getSideCarBinName, removeDir} from "./utils.js"; import axios from 'axios'; -import progress from 'progress-stream'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); From 14d9255ae68406e2abd52999e19dfbca2892311f Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 1 Nov 2023 18:46:20 +0530 Subject: [PATCH 144/864] build: npm run tauriBuildDemoApp to build demo app --- README.md | 9 +++++++++ package.json | 2 +- src-build/createDemoReleaseConfig.js | 26 ++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 src-build/createDemoReleaseConfig.js diff --git a/README.md b/README.md index 92dc3490..5a1246e6 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,15 @@ The actual release artifacts will then be built by the tauri action `tauri-apps/ Remember, the `npm run _ci-*` commands are designed to execute in the GitHub Actions environment. They're not typically used for local machine executions unless you're working on or testing the GitHub Actions workflows themselves. +### Building the demo app +If you dont want to build phcode and just build a demo app with similar config as phcode(You may do this +if you are working on the release generation or build tooling and don't want to wait for phcode to build +every time you want to test the build). Just run this command: + +```bash +npm run tauriBuildDemoApp +``` + # License GNU AGPL-3.0 License diff --git a/package.json b/package.json index b94e858b..6f15c407 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "tauri": "tauri", - "build": "", + "tauriBuildDemoApp": "node src-build/createDemoReleaseConfig.js && tauri build --config ./src-tauri/tauri-local.conf.json", "_createSrcReleaseConfig": "node src-build/createSrcReleaseConfig.js", "_createDistReleaseConfig": "node src-build/createDistReleaseConfig.js", "_createDistTestReleaseConfig": "node src-build/createDistTestReleaseConfig.js", diff --git a/src-build/createDemoReleaseConfig.js b/src-build/createDemoReleaseConfig.js new file mode 100644 index 00000000..6fb49169 --- /dev/null +++ b/src-build/createDemoReleaseConfig.js @@ -0,0 +1,26 @@ +import {fileURLToPath} from "url"; +import {dirname} from "path"; +import fs from 'fs'; +import * as os from 'os'; + +import {getPlatformDetails} from "./utils.js"; +import chalk from "chalk"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +async function createSrcReleaseConfig() { + const platform = getPlatformDetails().platform; + const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` + : `${__dirname}/../src-tauri/tauri.conf.json`; + const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` + : `${__dirname}/../src-tauri/tauri-local.conf.json`; + console.log("Reading config file: ", tauriConfigPath); + let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + console.log(chalk.cyan("\n!Creating the demo app!\n")); + configJson.tauri.bundle.resources = []; // no resources packaged in demo app + console.log("Writing new local config json ", tauriLocalConfigPath); + fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); +} + +await createSrcReleaseConfig(); From da94cd9a1402d0a3b049c4d0add0c0bbcc99ccfd Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 2 Nov 2023 18:51:35 +0530 Subject: [PATCH 145/864] fix: release build generation fail --- src-build/ci-createDistReleaseConfig.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index 22a589d6..1e0a4b0a 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -7,6 +7,7 @@ import { UPDATE_NOTIFICATIONS_BASE_URL } from "./constants.js"; import { EOL } from "os"; +import os from "os"; import fs from 'fs'; const __filename = fileURLToPath(import.meta.url); From af11df82ef49a220cd5d3a9d5892ff8685fe91ab Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 2 Nov 2023 21:12:43 +0530 Subject: [PATCH 146/864] fix: apple team id for code sign in mac --- .github/workflows/tauri-build-dev.yml | 2 ++ .github/workflows/tauri-build-prod.yml | 2 ++ .github/workflows/tauri-build-staging.yml | 2 ++ 3 files changed, 6 insertions(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index b070e9dd..39ff9a5a 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -127,6 +127,7 @@ jobs: APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true @@ -150,6 +151,7 @@ jobs: APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 31a4013c..582e08f3 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -127,6 +127,7 @@ jobs: APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true @@ -150,6 +151,7 @@ jobs: APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 7f64b144..1022edec 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -125,6 +125,7 @@ jobs: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} with: @@ -148,6 +149,7 @@ jobs: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} with: From 870b293053b70a7e7408be06c19c3837b887660b Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 2 Nov 2023 22:18:52 +0530 Subject: [PATCH 147/864] chore: dummy commit --- src-build/downloadNodeBinary.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index 4359f56e..7e5482ff 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -81,8 +81,6 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { } } } - - /** * Extracts a tar archive file to the specified output directory. * @param {string} inputFile - The path of the tar archive file to be extracted. From 36a224ca917087f6bcee0f33ec25ae4723ac7f00 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 2 Nov 2023 22:45:32 +0530 Subject: [PATCH 148/864] chore: check if APPLE_TEAM_ID set correctly --- .github/workflows/tauri-build-dev.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 39ff9a5a..9f02a30e 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -116,6 +116,15 @@ jobs: # Write the content back to the file Set-Content -Path "./secrets.json" -Value $content shell: powershell + - name: Check APPLE_TEAM_ID environment variable + run: | + if [ -z "${{ secrets.APPLE_TEAM_ID }}" ]; then + echo "APPLE_TEAM_ID is not set" + exit 1 + else + echo "APPLE_TEAM_ID is set" + fi + shell: bash - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From d0ff7551691757be59390531909d539447d7ed01 Mon Sep 17 00:00:00 2001 From: "charly@core.ai" Date: Fri, 3 Nov 2023 14:36:27 +0530 Subject: [PATCH 149/864] fix: mac sign fail in dev branch --- .github/workflows/tauri-build-dev.yml | 13 ++++++------- src-build/mac/filesToSign | 1 + 2 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 src-build/mac/filesToSign diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 9f02a30e..79ebc400 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -116,15 +116,14 @@ jobs: # Write the content back to the file Set-Content -Path "./secrets.json" -Value $content shell: powershell - - name: Check APPLE_TEAM_ID environment variable + - name: Sign embedded executables for Mac + if: matrix.platform == 'macos-latest' + env : + CERTIFICATE: ${{ secrets.APPLE_EXTERNAL_BINARY_SIGN_CERTIFICATE }} run: | - if [ -z "${{ secrets.APPLE_TEAM_ID }}" ]; then - echo "APPLE_TEAM_ID is not set" - exit 1 - else - echo "APPLE_TEAM_ID is set" - fi + cat ./src-build/mac/filesToSign | xargs codesign -s "$CERTIFICATE" --timestamp --options runtime shell: bash + - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/src-build/mac/filesToSign b/src-build/mac/filesToSign new file mode 100644 index 00000000..7b2190ff --- /dev/null +++ b/src-build/mac/filesToSign @@ -0,0 +1 @@ +src-tauri/src-node/node_modules/fsevents/fsevents.node From b5f454cd03b8e9ecc2de2f9c292798b0fd920979 Mon Sep 17 00:00:00 2001 From: "charly@core.ai" Date: Fri, 3 Nov 2023 15:11:34 +0530 Subject: [PATCH 150/864] fix: unable to add sign key missing in keychain --- .github/workflows/tauri-build-dev.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 79ebc400..9c540bbf 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -119,11 +119,17 @@ jobs: - name: Sign embedded executables for Mac if: matrix.platform == 'macos-latest' env : - CERTIFICATE: ${{ secrets.APPLE_EXTERNAL_BINARY_SIGN_CERTIFICATE }} + CERTIFICATE_NAME: ${{ secrets.APPLE_EXTERNAL_BINARY_SIGN_CERTIFICATE }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} run: | - cat ./src-build/mac/filesToSign | xargs codesign -s "$CERTIFICATE" --timestamp --options runtime + CERT_FILE="Certificate.p12" + cat "$APPLE_CERTIFICATE" | base64 --decode > $CERT_FILE + security import $CERT_FILE -k ~/Library/Keychains/login.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign + rm $CERT_FILE + cat ./src-build/mac/filesToSign | xargs codesign -s "$CERTIFICATE_NAME" --timestamp --options runtime shell: bash - + - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 11c7638105bc59597831f66ad59e2fa357c43733 Mon Sep 17 00:00:00 2001 From: "charly@core.ai" Date: Fri, 3 Nov 2023 15:17:11 +0530 Subject: [PATCH 151/864] fix: changing cat to echo --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 9c540bbf..de6c30f0 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -124,7 +124,7 @@ jobs: APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} run: | CERT_FILE="Certificate.p12" - cat "$APPLE_CERTIFICATE" | base64 --decode > $CERT_FILE + echo "$APPLE_CERTIFICATE" | base64 --decode > $CERT_FILE security import $CERT_FILE -k ~/Library/Keychains/login.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign rm $CERT_FILE cat ./src-build/mac/filesToSign | xargs codesign -s "$CERTIFICATE_NAME" --timestamp --options runtime From aadf7d986636ed072bf82ec37f7b97ed2b76d054 Mon Sep 17 00:00:00 2001 From: "charly@core.ai" Date: Fri, 3 Nov 2023 15:50:44 +0530 Subject: [PATCH 152/864] chore: debug code --- .github/workflows/tauri-build-dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index de6c30f0..d1bf76c9 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -123,6 +123,7 @@ jobs: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} run: | + cat ./src-build/mac/filesToSign CERT_FILE="Certificate.p12" echo "$APPLE_CERTIFICATE" | base64 --decode > $CERT_FILE security import $CERT_FILE -k ~/Library/Keychains/login.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign From 17768a45414a7851e959ab57ffe80fe4b5de6cbb Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 3 Nov 2023 16:48:58 +0530 Subject: [PATCH 153/864] chore: try signing with key chain --- .github/workflows/tauri-build-dev.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index d1bf76c9..b31f9e8a 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -122,13 +122,17 @@ jobs: CERTIFICATE_NAME: ${{ secrets.APPLE_EXTERNAL_BINARY_SIGN_CERTIFICATE }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + KEYCHAIN_PWD: ${{ secrets.KEYCHAIN_PWD }} + KEYCHAIN_ID: ${{ secrets.KEYCHAIN_ID }} run: | + security create-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_ID" + security unlock-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_ID" cat ./src-build/mac/filesToSign CERT_FILE="Certificate.p12" echo "$APPLE_CERTIFICATE" | base64 --decode > $CERT_FILE - security import $CERT_FILE -k ~/Library/Keychains/login.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign + security import $CERT_FILE -k "$KEYCHAIN_ID" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign rm $CERT_FILE - cat ./src-build/mac/filesToSign | xargs codesign -s "$CERTIFICATE_NAME" --timestamp --options runtime + cat ./src-build/mac/filesToSign | xargs codesign -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime shell: bash - uses: tauri-apps/tauri-action@v0 From 2d7f86b0f8092480d2a22d793e9a811fda4a6a64 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 3 Nov 2023 17:02:11 +0530 Subject: [PATCH 154/864] fix: remove hardcoded certificate --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index b31f9e8a..e44d5e72 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -132,7 +132,7 @@ jobs: echo "$APPLE_CERTIFICATE" | base64 --decode > $CERT_FILE security import $CERT_FILE -k "$KEYCHAIN_ID" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign rm $CERT_FILE - cat ./src-build/mac/filesToSign | xargs codesign -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime + cat ./src-build/mac/filesToSign | xargs codesign --keychain "$KEYCHAIN_ID" --timestamp --options runtime shell: bash - uses: tauri-apps/tauri-action@v0 From 4453924e6fbe38847ea2a83aee82648b293297af Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 3 Nov 2023 17:20:09 +0530 Subject: [PATCH 155/864] chore: added permsions to key --- .github/workflows/tauri-build-dev.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index e44d5e72..64d49d0c 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -132,7 +132,9 @@ jobs: echo "$APPLE_CERTIFICATE" | base64 --decode > $CERT_FILE security import $CERT_FILE -k "$KEYCHAIN_ID" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign rm $CERT_FILE - cat ./src-build/mac/filesToSign | xargs codesign --keychain "$KEYCHAIN_ID" --timestamp --options runtime + security set-keychain-settings -t 3600 -u "$KEYCHAIN_ID" + security set-key-partition-list -S "apple-tool:,apple:,codesign:" -s -k "$KEYCHAIN_PWD" "$KEYCHAIN_ID" + cat ./src-build/mac/filesToSign | xargs codesign --force" -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime shell: bash - uses: tauri-apps/tauri-action@v0 From e722ee7e9945fddff62e36ccb8e5c3807fbf1027 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 3 Nov 2023 17:30:50 +0530 Subject: [PATCH 156/864] fix: remove extra qoutes --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 64d49d0c..1a03c9b1 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -134,7 +134,7 @@ jobs: rm $CERT_FILE security set-keychain-settings -t 3600 -u "$KEYCHAIN_ID" security set-key-partition-list -S "apple-tool:,apple:,codesign:" -s -k "$KEYCHAIN_PWD" "$KEYCHAIN_ID" - cat ./src-build/mac/filesToSign | xargs codesign --force" -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime + cat ./src-build/mac/filesToSign | xargs codesign --force -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime shell: bash - uses: tauri-apps/tauri-action@v0 From caac48f851cf5407fedc051fac912d94794121db Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 3 Nov 2023 17:39:36 +0530 Subject: [PATCH 157/864] chore:add debug logs --- .github/workflows/tauri-build-dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 1a03c9b1..9f4eeb9a 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -134,6 +134,7 @@ jobs: rm $CERT_FILE security set-keychain-settings -t 3600 -u "$KEYCHAIN_ID" security set-key-partition-list -S "apple-tool:,apple:,codesign:" -s -k "$KEYCHAIN_PWD" "$KEYCHAIN_ID" + security find-identity -vp codesigning "$KEYCHAIN_ID" cat ./src-build/mac/filesToSign | xargs codesign --force -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime shell: bash From e9ee935f8b566bf1490cb6e3556850b38ced1e5f Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 3 Nov 2023 18:03:27 +0530 Subject: [PATCH 158/864] chore: code to test code sign in mac --- .github/workflows/tauri-build-dev.yml | 29 +++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 9f4eeb9a..531e759b 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -125,16 +125,33 @@ jobs: KEYCHAIN_PWD: ${{ secrets.KEYCHAIN_PWD }} KEYCHAIN_ID: ${{ secrets.KEYCHAIN_ID }} run: | + local certificate_encoded="$APPLE_CERTIFICATE" + local certificate_password="$APPLE_CERTIFICATE_PASSWORD" + + # Delete any previous version of our keychain if present + delete_keychain + echo "Setting up keychain from environment variables..." + + # List the keychains + security list-keychain -d user + + # Creating a temporary directory + tmp_dir=$(mktemp -d) + cert_path="$tmp_dir/cert.p12" + # Check if base64 decoding is necessary or just a simple echo would suffice + # Assuming base64 decoding is needed + echo "$certificate_encoded" | base64 --decode > "$cert_path" + + # Importing the certificate to the keychain security create-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_ID" security unlock-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_ID" - cat ./src-build/mac/filesToSign - CERT_FILE="Certificate.p12" - echo "$APPLE_CERTIFICATE" | base64 --decode > $CERT_FILE - security import $CERT_FILE -k "$KEYCHAIN_ID" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign - rm $CERT_FILE + security import "$cert_path" -k "$KEYCHAIN_ID" -P "$certificate_password" -T /usr/bin/codesign -T /usr/bin/pkgbuild -T /usr/bin/productbuild security set-keychain-settings -t 3600 -u "$KEYCHAIN_ID" security set-key-partition-list -S "apple-tool:,apple:,codesign:" -s -k "$KEYCHAIN_PWD" "$KEYCHAIN_ID" - security find-identity -vp codesigning "$KEYCHAIN_ID" + + # Listing current keychains, appending new keychain to the list + current_keychains=$(security list-keychain -d user | tr -d '"\n') + security list-keychain -d user -s $current_keychains "$KEYCHAIN_ID" cat ./src-build/mac/filesToSign | xargs codesign --force -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime shell: bash From a8c98254b55b39f66961dc9a40e883c94f97d1fc Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 3 Nov 2023 18:20:54 +0530 Subject: [PATCH 159/864] chore: code to test mac binary sign --- .github/workflows/tauri-build-dev.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 531e759b..3ceee5c2 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -119,7 +119,7 @@ jobs: - name: Sign embedded executables for Mac if: matrix.platform == 'macos-latest' env : - CERTIFICATE_NAME: ${{ secrets.APPLE_EXTERNAL_BINARY_SIGN_CERTIFICATE }} + MAC_IDENTITY: ${{ secrets.APPLE_EXTERNAL_BINARY_SIGN_CERTIFICATE }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} KEYCHAIN_PWD: ${{ secrets.KEYCHAIN_PWD }} @@ -149,10 +149,8 @@ jobs: security set-keychain-settings -t 3600 -u "$KEYCHAIN_ID" security set-key-partition-list -S "apple-tool:,apple:,codesign:" -s -k "$KEYCHAIN_PWD" "$KEYCHAIN_ID" - # Listing current keychains, appending new keychain to the list - current_keychains=$(security list-keychain -d user | tr -d '"\n') - security list-keychain -d user -s $current_keychains "$KEYCHAIN_ID" - cat ./src-build/mac/filesToSign | xargs codesign --force -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime + codesign --force --sign "$MAC_IDENTITY" --keychain "$KEYCHAIN_ID" --timestamp --options runtime ./src-tauri/src-node/node_modules/fsevents/fsevents.node + # cat ./src-build/mac/filesToSign | xargs codesign --force -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime shell: bash - uses: tauri-apps/tauri-action@v0 From 6da16a77b2fcbaa408e835be3e8787d3a0d71064 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 3 Nov 2023 18:25:12 +0530 Subject: [PATCH 160/864] fix: workflow error --- .github/workflows/tauri-build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 3ceee5c2..de200e32 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -125,8 +125,8 @@ jobs: KEYCHAIN_PWD: ${{ secrets.KEYCHAIN_PWD }} KEYCHAIN_ID: ${{ secrets.KEYCHAIN_ID }} run: | - local certificate_encoded="$APPLE_CERTIFICATE" - local certificate_password="$APPLE_CERTIFICATE_PASSWORD" + certificate_encoded="$APPLE_CERTIFICATE" + certificate_password="$APPLE_CERTIFICATE_PASSWORD" # Delete any previous version of our keychain if present delete_keychain From b5404a1860469026768fb1515beb0d1dad501e1c Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 3 Nov 2023 18:32:18 +0530 Subject: [PATCH 161/864] fix: workflow faliure --- .github/workflows/tauri-build-dev.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index de200e32..97fa1ee7 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -128,10 +128,7 @@ jobs: certificate_encoded="$APPLE_CERTIFICATE" certificate_password="$APPLE_CERTIFICATE_PASSWORD" - # Delete any previous version of our keychain if present - delete_keychain echo "Setting up keychain from environment variables..." - # List the keychains security list-keychain -d user From 4559ad4c6895c669acb451cf5a2e8a4f8b4b12a9 Mon Sep 17 00:00:00 2001 From: test Date: Fri, 3 Nov 2023 23:05:59 +0530 Subject: [PATCH 162/864] fix: mac sign not working --- .github/workflows/tauri-build-dev.yml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 97fa1ee7..34e2ef61 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -122,8 +122,6 @@ jobs: MAC_IDENTITY: ${{ secrets.APPLE_EXTERNAL_BINARY_SIGN_CERTIFICATE }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - KEYCHAIN_PWD: ${{ secrets.KEYCHAIN_PWD }} - KEYCHAIN_ID: ${{ secrets.KEYCHAIN_ID }} run: | certificate_encoded="$APPLE_CERTIFICATE" certificate_password="$APPLE_CERTIFICATE_PASSWORD" @@ -138,16 +136,14 @@ jobs: # Check if base64 decoding is necessary or just a simple echo would suffice # Assuming base64 decoding is needed echo "$certificate_encoded" | base64 --decode > "$cert_path" - - # Importing the certificate to the keychain - security create-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_ID" - security unlock-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_ID" - security import "$cert_path" -k "$KEYCHAIN_ID" -P "$certificate_password" -T /usr/bin/codesign -T /usr/bin/pkgbuild -T /usr/bin/productbuild - security set-keychain-settings -t 3600 -u "$KEYCHAIN_ID" - security set-key-partition-list -S "apple-tool:,apple:,codesign:" -s -k "$KEYCHAIN_PWD" "$KEYCHAIN_ID" - - codesign --force --sign "$MAC_IDENTITY" --keychain "$KEYCHAIN_ID" --timestamp --options runtime ./src-tauri/src-node/node_modules/fsevents/fsevents.node - # cat ./src-build/mac/filesToSign | xargs codesign --force -s "$CERTIFICATE_NAME" --keychain "$KEYCHAIN_ID" --timestamp --options runtime + + security create-keychain -p tmp-password build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p tmp-password build.keychain + security import $cert_path -k build.keychain -P $certificate_password -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain + codesign --sign $MAC_IDENTITY --keychain build.keychain --timestamp --options runtime ./src-tauri/src-node/node_modules/fsevents/fsevents.node + rm $cert_path shell: bash - uses: tauri-apps/tauri-action@v0 From 8fc7e5f2075aa187f435092aecb56b1139894b99 Mon Sep 17 00:00:00 2001 From: test Date: Fri, 3 Nov 2023 23:23:57 +0530 Subject: [PATCH 163/864] chore: debug working dir --- .github/workflows/tauri-build-dev.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 34e2ef61..73b90404 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -142,7 +142,9 @@ jobs: security unlock-keychain -p tmp-password build.keychain security import $cert_path -k build.keychain -P $certificate_password -T /usr/bin/codesign security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain - codesign --sign $MAC_IDENTITY --keychain build.keychain --timestamp --options runtime ./src-tauri/src-node/node_modules/fsevents/fsevents.node + ls src-tauri + pwd + codesign --sign $MAC_IDENTITY --keychain build.keychain --timestamp --options runtime src-tauri/src-node/node_modules/fsevents/fsevents.node rm $cert_path shell: bash From e51ccaa6c2cd57e43eca446120d4138b6d106e40 Mon Sep 17 00:00:00 2001 From: test Date: Fri, 3 Nov 2023 23:31:05 +0530 Subject: [PATCH 164/864] chore: adding more logs --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 73b90404..5547d5c9 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -142,7 +142,7 @@ jobs: security unlock-keychain -p tmp-password build.keychain security import $cert_path -k build.keychain -P $certificate_password -T /usr/bin/codesign security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain - ls src-tauri + ls src-tauri/src-node/node_modules/fsevents/ pwd codesign --sign $MAC_IDENTITY --keychain build.keychain --timestamp --options runtime src-tauri/src-node/node_modules/fsevents/fsevents.node rm $cert_path From a3552fc015368503dc57340141debbed33c213e3 Mon Sep 17 00:00:00 2001 From: test Date: Fri, 3 Nov 2023 23:46:52 +0530 Subject: [PATCH 165/864] chore: code clean up --- .github/workflows/tauri-build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 5547d5c9..a0efd391 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -119,7 +119,7 @@ jobs: - name: Sign embedded executables for Mac if: matrix.platform == 'macos-latest' env : - MAC_IDENTITY: ${{ secrets.APPLE_EXTERNAL_BINARY_SIGN_CERTIFICATE }} + APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} run: | @@ -144,7 +144,7 @@ jobs: security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain ls src-tauri/src-node/node_modules/fsevents/ pwd - codesign --sign $MAC_IDENTITY --keychain build.keychain --timestamp --options runtime src-tauri/src-node/node_modules/fsevents/fsevents.node + cat src-build/mac/filesToSign | xargs codesign --sign APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime rm $cert_path shell: bash From e24e6795f221d6871571d1e0cb1445f9d7fee29f Mon Sep 17 00:00:00 2001 From: test Date: Fri, 3 Nov 2023 23:50:49 +0530 Subject: [PATCH 166/864] fix: bug fix --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index a0efd391..fa81d99f 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -144,7 +144,7 @@ jobs: security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain ls src-tauri/src-node/node_modules/fsevents/ pwd - cat src-build/mac/filesToSign | xargs codesign --sign APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime + cat src-build/mac/filesToSign | xargs codesign --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime rm $cert_path shell: bash From 75dc0258e624f7ef10a5df13160c1556c7082a27 Mon Sep 17 00:00:00 2001 From: test Date: Sat, 4 Nov 2023 00:04:34 +0530 Subject: [PATCH 167/864] fix: rm --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index fa81d99f..88dee381 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -145,7 +145,7 @@ jobs: ls src-tauri/src-node/node_modules/fsevents/ pwd cat src-build/mac/filesToSign | xargs codesign --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime - rm $cert_path + shell: bash - uses: tauri-apps/tauri-action@v0 From 783d7b7ce1589241b61ae2ad9de813355d5fe237 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 4 Nov 2023 00:17:29 +0530 Subject: [PATCH 168/864] chore: add --force option --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 88dee381..375dcd0b 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -144,7 +144,7 @@ jobs: security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain ls src-tauri/src-node/node_modules/fsevents/ pwd - cat src-build/mac/filesToSign | xargs codesign --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime + cat src-build/mac/filesToSign | xargs codesign --force --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime shell: bash From 3c388b409972353e7a7864120f20e0fabb53e051 Mon Sep 17 00:00:00 2001 From: test Date: Sat, 4 Nov 2023 02:24:16 +0530 Subject: [PATCH 169/864] chore: addding verbose --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 375dcd0b..33cdbd83 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -144,7 +144,7 @@ jobs: security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain ls src-tauri/src-node/node_modules/fsevents/ pwd - cat src-build/mac/filesToSign | xargs codesign --force --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime + cat src-build/mac/filesToSign | xargs codesign --force --verbose=20 --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime shell: bash From c85e95d1f26f7a2f350492604ad1e1e6655f0748 Mon Sep 17 00:00:00 2001 From: test Date: Sat, 4 Nov 2023 02:38:50 +0530 Subject: [PATCH 170/864] chore: exp --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 33cdbd83..a17f617a 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -144,7 +144,7 @@ jobs: security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain ls src-tauri/src-node/node_modules/fsevents/ pwd - cat src-build/mac/filesToSign | xargs codesign --force --verbose=20 --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime + codesign --force --verbose --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime "src-tauri/src-node/node_modules/fsevents/fsevents.node" shell: bash From 01e310d00bab09bc19811f6b6a51e32295a39527 Mon Sep 17 00:00:00 2001 From: test Date: Sat, 4 Nov 2023 02:46:15 +0530 Subject: [PATCH 171/864] chore: exp1 --- .github/workflows/tauri-build-dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index a17f617a..3b448622 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -142,6 +142,7 @@ jobs: security unlock-keychain -p tmp-password build.keychain security import $cert_path -k build.keychain -P $certificate_password -T /usr/bin/codesign security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain + set -x ls src-tauri/src-node/node_modules/fsevents/ pwd codesign --force --verbose --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime "src-tauri/src-node/node_modules/fsevents/fsevents.node" From d0fda89691a4da12a6a8300f17d92e34a74dd370 Mon Sep 17 00:00:00 2001 From: test Date: Sat, 4 Nov 2023 02:54:01 +0530 Subject: [PATCH 172/864] chore: exp2 --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 3b448622..f10723df 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -145,7 +145,7 @@ jobs: set -x ls src-tauri/src-node/node_modules/fsevents/ pwd - codesign --force --verbose --sign $APPLE_KEY_IDENTITY_NAME --keychain build.keychain --timestamp --options runtime "src-tauri/src-node/node_modules/fsevents/fsevents.node" + codesign --force --verbose --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "src-tauri/src-node/node_modules/fsevents/fsevents.node" shell: bash From 08b68d1c4751355cd0b3bcad35fda1fac01d3e95 Mon Sep 17 00:00:00 2001 From: test Date: Sat, 4 Nov 2023 03:03:23 +0530 Subject: [PATCH 173/864] fix: sign script --- .github/workflows/tauri-build-dev.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index f10723df..c9a51e29 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -140,12 +140,9 @@ jobs: security create-keychain -p tmp-password build.keychain security default-keychain -s build.keychain security unlock-keychain -p tmp-password build.keychain - security import $cert_path -k build.keychain -P $certificate_password -T /usr/bin/codesign + security import "$cert_path" -k build.keychain -P "$certificate_password" -T /usr/bin/codesign security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain - set -x - ls src-tauri/src-node/node_modules/fsevents/ - pwd - codesign --force --verbose --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "src-tauri/src-node/node_modules/fsevents/fsevents.node" + cat src-build/mac/filesToSign | xargs codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime shell: bash From c94812b8de8ec36d56db8b8540ab3d05df2692ab Mon Sep 17 00:00:00 2001 From: test Date: Sat, 4 Nov 2023 03:28:44 +0530 Subject: [PATCH 174/864] fix: keychain clean up --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index c9a51e29..a2bbdb3f 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -143,7 +143,7 @@ jobs: security import "$cert_path" -k build.keychain -P "$certificate_password" -T /usr/bin/codesign security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain cat src-build/mac/filesToSign | xargs codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime - + security delete-keychain build.keychain shell: bash - uses: tauri-apps/tauri-action@v0 From 025e8277cad247bc346ca14076eec8e076584d23 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 4 Nov 2023 10:04:54 +0530 Subject: [PATCH 175/864] feat: Added support for code sign MAC --- .github/workflows/tauri-build-dev.yml | 31 +++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index a2bbdb3f..8a386f8a 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -125,25 +125,34 @@ jobs: run: | certificate_encoded="$APPLE_CERTIFICATE" certificate_password="$APPLE_CERTIFICATE_PASSWORD" - + echo "Setting up keychain from environment variables..." - # List the keychains - security list-keychain -d user - + # Creating a temporary directory tmp_dir=$(mktemp -d) cert_path="$tmp_dir/cert.p12" - # Check if base64 decoding is necessary or just a simple echo would suffice - # Assuming base64 decoding is needed + # Decode the encoded certificate and write it to the cert_path echo "$certificate_encoded" | base64 --decode > "$cert_path" - - security create-keychain -p tmp-password build.keychain + + # Generate a random password for the keychain + KEYCHAIN_PASSWORD=$(openssl rand -base64 16) + + # Create a new keychain with the random password + security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain security default-keychain -s build.keychain - security unlock-keychain -p tmp-password build.keychain + security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain security import "$cert_path" -k build.keychain -P "$certificate_password" -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple: -s -k tmp-password build.keychain - cat src-build/mac/filesToSign | xargs codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime + security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" build.keychain + + # Sign the files specified in src-build/mac/filesToSign + while IFS= read -r file; do + codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" + done < src-build/mac/filesToSign + + # Clean up security delete-keychain build.keychain + rm -rf "$tmp_dir" # removes the temporary directory and the certificate file within it + shell: bash - uses: tauri-apps/tauri-action@v0 From 2e77f176e8a9877a2216422cd1357bfa41209905 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 4 Nov 2023 10:24:51 +0530 Subject: [PATCH 176/864] chore: update task name to convention --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 8a386f8a..dff5b086 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -116,7 +116,7 @@ jobs: # Write the content back to the file Set-Content -Path "./secrets.json" -Value $content shell: powershell - - name: Sign embedded executables for Mac + - name: Sign embedded executables for (Mac Only) if: matrix.platform == 'macos-latest' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} From e1b90b1ba6ebf07f017511098bcfabe4ed8c6197 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 4 Nov 2023 17:59:00 +0530 Subject: [PATCH 177/864] chore: upgrade node to 20LTS from 18LTS --- .github/workflows/desktop-linux-test-pull.yml | 2 +- .github/workflows/desktop-mac-test-pull.yml | 2 +- .github/workflows/desktop-windows-test-pull.yml | 2 +- .github/workflows/prod-desktop-tests-on-push.yml | 6 +++--- .github/workflows/staging-desktop-tests-on-push.yml | 6 +++--- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- .github/workflows/update-phcode-build.yml | 2 +- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index ff4422f7..5c331173 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -14,7 +14,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 1b354ee6..7501a0b6 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -14,7 +14,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index 8083965a..cc4d16a2 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -14,7 +14,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/prod-desktop-tests-on-push.yml b/.github/workflows/prod-desktop-tests-on-push.yml index b8910ee3..5ad4247b 100644 --- a/.github/workflows/prod-desktop-tests-on-push.yml +++ b/.github/workflows/prod-desktop-tests-on-push.yml @@ -18,7 +18,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable @@ -82,7 +82,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable @@ -139,7 +139,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/staging-desktop-tests-on-push.yml b/.github/workflows/staging-desktop-tests-on-push.yml index 4922550f..9bd9a2bc 100644 --- a/.github/workflows/staging-desktop-tests-on-push.yml +++ b/.github/workflows/staging-desktop-tests-on-push.yml @@ -18,7 +18,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable @@ -82,7 +82,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable @@ -139,7 +139,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index dff5b086..9536bbb6 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -17,7 +17,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: lts/* + node-version: 20 - name: get version run: | echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 582e08f3..22f58605 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -17,7 +17,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: lts/* + node-version: 20 - name: get version run: | echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 1022edec..7a3381c8 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -17,7 +17,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: lts/* + node-version: 20 - name: get version run: | echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 3c68ca76..fb081895 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -20,7 +20,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: lts/* + node-version: 20 - name: Update phcode and version run: | From e64249b2cdede3fe4e872cd15ecdeb2842b680e9 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 4 Nov 2023 18:33:57 +0530 Subject: [PATCH 178/864] ci: staging and prod test runs on pull request instead of push --- .../workflows/prod-desktop-tests-on-push.yml | 44 +------------------ .../staging-desktop-tests-on-push.yml | 44 +------------------ 2 files changed, 4 insertions(+), 84 deletions(-) diff --git a/.github/workflows/prod-desktop-tests-on-push.yml b/.github/workflows/prod-desktop-tests-on-push.yml index 5ad4247b..3a87be2d 100644 --- a/.github/workflows/prod-desktop-tests-on-push.yml +++ b/.github/workflows/prod-desktop-tests-on-push.yml @@ -1,13 +1,9 @@ -name: On-Push prod Win/Mac/Linux run full tests suite +name: On pull request on prod Win/Mac/Linux run full tests suite on: - push: + pull_request: branches: [ prod ] -permissions: - contents: read - issues: write - jobs: testDesktopLinux: @@ -223,39 +219,3 @@ jobs: echo "Windows tests failed, marking step as failed" exit 1 shell: cmd - - raiseIssue: - needs: [ testDesktopLinux, testDesktopMac, testDesktopWindows] - runs-on: ubuntu-latest - if: | - always() && ( # This ensures that this job runs even if the previous jobs failed - needs.testDesktopLinux.result == 'failure' || - needs.testDesktopMac.result == 'failure' || - needs.testDesktopWindows.result == 'failure' - ) - steps: - - name: Check for failures and raise an issue - uses: actions/github-script@v6 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - const issueTitle = "Test failure on push to prod branch: commit ${{github.sha}}"; - const runURL = `https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}`; - let issueBody = `There was a test failure. Please investigate.\n\n[Check the failed run here](${runURL})\n\n`; - - if (needs.testDesktopLinux.result == 'failure') { - issueBody += " - Desktop Linux tests failed.\n"; - } - if (needs.testDesktopMac.result == 'failure') { - issueBody += " - Desktop MacOS tests failed.\n"; - } - if (needs.testDesktopWindows.result == 'failure') { - issueBody += " - Desktop Windows tests failed.\n"; - } - - github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: issueTitle, - body: issueBody - }); diff --git a/.github/workflows/staging-desktop-tests-on-push.yml b/.github/workflows/staging-desktop-tests-on-push.yml index 9bd9a2bc..854aa3d0 100644 --- a/.github/workflows/staging-desktop-tests-on-push.yml +++ b/.github/workflows/staging-desktop-tests-on-push.yml @@ -1,13 +1,9 @@ -name: On-Push staging Win/Mac/Linux run full tests suite +name: On pull request on staging Win/Mac/Linux run full tests suite on: - push: + pull_request: branches: [ staging ] -permissions: - contents: read - issues: write - jobs: testDesktopLinux: @@ -223,39 +219,3 @@ jobs: echo "Windows tests failed, marking step as failed" exit 1 shell: cmd - - raiseIssue: - needs: [ testDesktopLinux, testDesktopMac, testDesktopWindows] - runs-on: ubuntu-latest - if: | - always() && ( # This ensures that this job runs even if the previous jobs failed - needs.testDesktopLinux.result == 'failure' || - needs.testDesktopMac.result == 'failure' || - needs.testDesktopWindows.result == 'failure' - ) - steps: - - name: Check for failures and raise an issue - uses: actions/github-script@v6 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - const issueTitle = "Test failure on push to staging branch: commit ${{github.sha}}"; - const runURL = `https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}`; - let issueBody = `There was a test failure. Please investigate.\n\n[Check the failed run here](${runURL})\n\n`; - - if (needs.testDesktopLinux.result == 'failure') { - issueBody += " - Desktop Linux tests failed.\n"; - } - if (needs.testDesktopMac.result == 'failure') { - issueBody += " - Desktop MacOS tests failed.\n"; - } - if (needs.testDesktopWindows.result == 'failure') { - issueBody += " - Desktop Windows tests failed.\n"; - } - - github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: issueTitle, - body: issueBody - }); From a7486a5a6bb676469f549e02aa57f96f5475a0be Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 4 Nov 2023 19:24:17 +0530 Subject: [PATCH 179/864] ci: only run desktop test on pull on main branch --- .github/workflows/desktop-linux-test-pull.yml | 4 +++- .github/workflows/desktop-mac-test-pull.yml | 4 +++- .github/workflows/desktop-windows-test-pull.yml | 4 +++- ...sktop-tests-on-push.yml => prod-desktop-tests-on-pull.yml} | 0 ...op-tests-on-push.yml => staging-desktop-tests-on-pull.yml} | 0 5 files changed, 9 insertions(+), 3 deletions(-) rename .github/workflows/{prod-desktop-tests-on-push.yml => prod-desktop-tests-on-pull.yml} (100%) rename .github/workflows/{staging-desktop-tests-on-push.yml => staging-desktop-tests-on-pull.yml} (100%) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index 5c331173..dc4d9816 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -1,5 +1,7 @@ name: 'Desktop-Linux full test suite run on pull request' -on: [pull_request] +on: + pull_request: + branches: [ main ] concurrency: group: pr-desktop-linux-${{ github.event.pull_request.number }} diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 7501a0b6..94d04600 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -1,5 +1,7 @@ name: 'Desktop-mac full test suite run on pull request' -on: [pull_request] +on: + pull_request: + branches: [ main ] concurrency: group: pr-desktop-mac-${{ github.event.pull_request.number }} diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index cc4d16a2..748b0bde 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -1,5 +1,7 @@ name: 'Desktop-Windows full test suite run on pull request' -on: [pull_request] +on: + pull_request: + branches: [ main ] concurrency: group: pr-desktop-windows-${{ github.event.pull_request.number }} diff --git a/.github/workflows/prod-desktop-tests-on-push.yml b/.github/workflows/prod-desktop-tests-on-pull.yml similarity index 100% rename from .github/workflows/prod-desktop-tests-on-push.yml rename to .github/workflows/prod-desktop-tests-on-pull.yml diff --git a/.github/workflows/staging-desktop-tests-on-push.yml b/.github/workflows/staging-desktop-tests-on-pull.yml similarity index 100% rename from .github/workflows/staging-desktop-tests-on-push.yml rename to .github/workflows/staging-desktop-tests-on-pull.yml From d6b754b6eb73b120cd73399ec16b4119306f6367 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 6 Nov 2023 22:41:50 +0530 Subject: [PATCH 180/864] ci: mac m1 test runner --- .../workflows/desktop-mac-M1-test-pull.yml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/desktop-mac-M1-test-pull.yml diff --git a/.github/workflows/desktop-mac-M1-test-pull.yml b/.github/workflows/desktop-mac-M1-test-pull.yml new file mode 100644 index 00000000..6c57b2d2 --- /dev/null +++ b/.github/workflows/desktop-mac-M1-test-pull.yml @@ -0,0 +1,66 @@ +name: 'Desktop-mac M1 full test suite run on pull request' +on: + pull_request: + branches: [ main ] + +concurrency: + group: pr-desktop-mac-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + test-desktop-mac: + runs-on: macos-latest-large + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + + - name: npm install ci deps + run: npm ci + + - name: Download phoenix and build build phoenix dist-test + run: | + npm run _ci-clonePhoenixForTests + cd .. + cd phoenix + npm ci + npm run build + npm run release:dev + + - name: build test runner + run: | + npm ci + npm run releaseDistTestDebug + + - name: Run tauri unit tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q + + - name: Run tauri integration tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q + + - name: Run tauri mainview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + + - name: Run tauri LegacyInteg tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 30 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q From 946b98c30c51bb53eb88297c00b007f81e9f9ebc Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 6 Nov 2023 22:43:24 +0530 Subject: [PATCH 181/864] ci: mac m1 test runner --- .github/workflows/desktop-mac-M1-test-pull.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/desktop-mac-M1-test-pull.yml b/.github/workflows/desktop-mac-M1-test-pull.yml index 6c57b2d2..43b2ddc3 100644 --- a/.github/workflows/desktop-mac-M1-test-pull.yml +++ b/.github/workflows/desktop-mac-M1-test-pull.yml @@ -4,7 +4,7 @@ on: branches: [ main ] concurrency: - group: pr-desktop-mac-${{ github.event.pull_request.number }} + group: pr-desktop-mac-m1-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: From 01e20d215f675d2a8d5c4701be3aac5da3e78e28 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 6 Nov 2023 22:54:30 +0530 Subject: [PATCH 182/864] ci: mac m1 test runner --- .../workflows/desktop-mac-M1-test-pull.yml | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/desktop-mac-M1-test-pull.yml b/.github/workflows/desktop-mac-M1-test-pull.yml index 43b2ddc3..347b0eeb 100644 --- a/.github/workflows/desktop-mac-M1-test-pull.yml +++ b/.github/workflows/desktop-mac-M1-test-pull.yml @@ -8,11 +8,13 @@ concurrency: cancel-in-progress: true jobs: - test-desktop-mac: + test-desktop-mac-m1: runs-on: macos-latest-large - timeout-minutes: 5 + timeout-minutes: 1 steps: - uses: actions/checkout@v4 + - name: macos hardware info + run: system_profiler SPSoftwareDataType SPHardwareDataType - name: setup node uses: actions/setup-node@v4 with: @@ -40,27 +42,27 @@ jobs: - name: Run tauri unit tests uses: nick-fields/retry@v2 with: - timeout_minutes: 12 - max_attempts: 3 + timeout_minutes: 10 + max_attempts: 2 command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - name: Run tauri integration tests uses: nick-fields/retry@v2 with: - timeout_minutes: 12 - max_attempts: 3 + timeout_minutes: 10 + max_attempts: 2 command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - name: Run tauri mainview tests uses: nick-fields/retry@v2 with: - timeout_minutes: 12 - max_attempts: 3 + timeout_minutes: 10 + max_attempts: 2 command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v2 with: timeout_minutes: 30 - max_attempts: 3 + max_attempts: 1 command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q From 9ea33213ad352e4e5343b78af4f72bbda9ceca9a Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 6 Nov 2023 23:29:50 +0530 Subject: [PATCH 183/864] ci: mac m1 test runner --- ...-test-pull.yml => prod-desktop-mac-m1-tests-on-pull.yml} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename .github/workflows/{desktop-mac-M1-test-pull.yml => prod-desktop-mac-m1-tests-on-pull.yml} (93%) diff --git a/.github/workflows/desktop-mac-M1-test-pull.yml b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml similarity index 93% rename from .github/workflows/desktop-mac-M1-test-pull.yml rename to .github/workflows/prod-desktop-mac-m1-tests-on-pull.yml index 347b0eeb..a9cbc134 100644 --- a/.github/workflows/desktop-mac-M1-test-pull.yml +++ b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml @@ -1,7 +1,7 @@ -name: 'Desktop-mac M1 full test suite run on pull request' +name: 'Expensive Desktop-mac M1 prod only full test suite run on pull request' on: pull_request: - branches: [ main ] + branches: [ prod ] concurrency: group: pr-desktop-mac-m1-${{ github.event.pull_request.number }} @@ -10,7 +10,7 @@ concurrency: jobs: test-desktop-mac-m1: runs-on: macos-latest-large - timeout-minutes: 1 + timeout-minutes: 45 steps: - uses: actions/checkout@v4 - name: macos hardware info From 1dc1fca82dc41b2dd36b548935776445258214a0 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 6 Nov 2023 23:49:57 +0530 Subject: [PATCH 184/864] ci: mac code sign fix in staging and prod --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 44 +++++++++++++++++++-- .github/workflows/tauri-build-staging.yml | 48 ++++++++++++++++++++--- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 9536bbb6..8c87d382 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -57,7 +57,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: lts/* + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 22f58605..677c5625 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -57,7 +57,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: lts/* + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) @@ -116,6 +116,45 @@ jobs: # Write the content back to the file Set-Content -Path "./secrets.json" -Value $content shell: powershell + - name: Sign embedded executables for (Mac Only) + if: matrix.platform == 'macos-latest' + env : + APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + run: | + certificate_encoded="$APPLE_CERTIFICATE" + certificate_password="$APPLE_CERTIFICATE_PASSWORD" + + echo "Setting up keychain from environment variables..." + + # Creating a temporary directory + tmp_dir=$(mktemp -d) + cert_path="$tmp_dir/cert.p12" + # Decode the encoded certificate and write it to the cert_path + echo "$certificate_encoded" | base64 --decode > "$cert_path" + + # Generate a random password for the keychain + KEYCHAIN_PASSWORD=$(openssl rand -base64 16) + + # Create a new keychain with the random password + security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security import "$cert_path" -k build.keychain -P "$certificate_password" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" build.keychain + + # Sign the files specified in src-build/mac/filesToSign + while IFS= read -r file; do + codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" + done < src-build/mac/filesToSign + + # Clean up + security delete-keychain build.keychain + rm -rf "$tmp_dir" # removes the temporary directory and the certificate file within it + + shell: bash + - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -157,7 +196,6 @@ jobs: args: --target aarch64-apple-darwin tagName: ${{ env.GIT_TAG_NAME }} - publish-release: permissions: contents: write @@ -179,7 +217,7 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, tag_name: `${process.env.GIT_TAG_NAME}`, - target_commitish: 'dev', + target_commitish: 'prod', release_id: process.env.release_id, draft: true, prerelease: false diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 7a3381c8..401d9063 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -57,7 +57,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: lts/* + node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) @@ -116,6 +116,45 @@ jobs: # Write the content back to the file Set-Content -Path "./secrets.json" -Value $content shell: powershell + - name: Sign embedded executables for (Mac Only) + if: matrix.platform == 'macos-latest' + env : + APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + run: | + certificate_encoded="$APPLE_CERTIFICATE" + certificate_password="$APPLE_CERTIFICATE_PASSWORD" + + echo "Setting up keychain from environment variables..." + + # Creating a temporary directory + tmp_dir=$(mktemp -d) + cert_path="$tmp_dir/cert.p12" + # Decode the encoded certificate and write it to the cert_path + echo "$certificate_encoded" | base64 --decode > "$cert_path" + + # Generate a random password for the keychain + KEYCHAIN_PASSWORD=$(openssl rand -base64 16) + + # Create a new keychain with the random password + security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain + security import "$cert_path" -k build.keychain -P "$certificate_password" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" build.keychain + + # Sign the files specified in src-build/mac/filesToSign + while IFS= read -r file; do + codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" + done < src-build/mac/filesToSign + + # Clean up + security delete-keychain build.keychain + rm -rf "$tmp_dir" # removes the temporary directory and the certificate file within it + + shell: bash + - uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -125,9 +164,9 @@ jobs: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true @@ -149,15 +188,14 @@ jobs: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin tagName: ${{ env.GIT_TAG_NAME }} - publish-release: permissions: contents: write @@ -179,7 +217,7 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, tag_name: `${process.env.GIT_TAG_NAME}`, - target_commitish: 'dev', + target_commitish: 'staging', release_id: process.env.release_id, draft: true, prerelease: true From 050ba33d97d6e0a72be16404fe36303dccdb70be Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 7 Nov 2023 11:23:28 +0530 Subject: [PATCH 185/864] chore: mac m1 prod releases with m1 macs --- .github/workflows/tauri-build-prod.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 677c5625..88ab1d2d 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -2,7 +2,7 @@ name: 'generate production draft GitHub release' on: push: - branches: [ prod ] + branches: [ xx ] jobs: create-release: @@ -43,10 +43,11 @@ jobs: needs: create-release permissions: contents: write + timeout-minutes: 45 strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-latest, windows-latest ] + platform: [ macos-latest, macos-latest-large, ubuntu-latest, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -72,6 +73,7 @@ jobs: run: | npm ci npm run _ci-release:prod + - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' run: | @@ -116,8 +118,9 @@ jobs: # Write the content back to the file Set-Content -Path "./secrets.json" -Value $content shell: powershell + - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-latest' || matrix.platform == 'macos-latest-large' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -173,12 +176,12 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: setup env for mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-latest-large' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-latest-large' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From cb42e843ab7fffa824b9c15984b43fbef0d66cc7 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 7 Nov 2023 11:45:15 +0530 Subject: [PATCH 186/864] fix: mac m1 release build fail --- .github/workflows/tauri-build-prod.yml | 3 +++ src-tauri/src/main.rs | 2 ++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 88ab1d2d..770696b6 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -14,6 +14,8 @@ jobs: steps: - uses: actions/checkout@v4 + - name: macos hardware info + run: system_profiler SPSoftwareDataType SPHardwareDataType - name: setup node uses: actions/setup-node@v4 with: @@ -159,6 +161,7 @@ jobs: shell: bash - uses: tauri-apps/tauri-action@v0 + if: matrix.platform != 'macos-latest-large' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 5eb3710a..0dc0cf65 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -5,7 +5,9 @@ windows_subsystem = "windows" #[cfg(target_os = "linux")] use std::fs::metadata; +#[cfg(target_os = "linux")] use std::path::PathBuf; + use std::process::Command; use regex::Regex; From 305a95c965ce4218ff699f30ebc148f66cb2becc Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 7 Nov 2023 11:54:09 +0530 Subject: [PATCH 187/864] fix: mac m1 release build fail --- .github/workflows/tauri-build-prod.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 770696b6..2c8aa125 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -15,6 +15,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: macos hardware info + if: matrix.platform == 'macos-latest-large' run: system_profiler SPSoftwareDataType SPHardwareDataType - name: setup node uses: actions/setup-node@v4 From b5d8aa5328f1109142b69d4a81c5551011a12768 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 7 Nov 2023 11:59:34 +0530 Subject: [PATCH 188/864] fix: mac was using interl runner instead of m1 --- .../prod-desktop-mac-m1-tests-on-pull.yml | 2 +- .github/workflows/tauri-build-prod.yml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml index a9cbc134..da031e83 100644 --- a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml @@ -9,7 +9,7 @@ concurrency: jobs: test-desktop-mac-m1: - runs-on: macos-latest-large + runs-on: macos-latest-xlarge timeout-minutes: 45 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 2c8aa125..87120227 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -14,9 +14,6 @@ jobs: steps: - uses: actions/checkout@v4 - - name: macos hardware info - if: matrix.platform == 'macos-latest-large' - run: system_profiler SPSoftwareDataType SPHardwareDataType - name: setup node uses: actions/setup-node@v4 with: @@ -50,11 +47,14 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, macos-latest-large, ubuntu-latest, windows-latest ] + platform: [ macos-latest, macos-latest-xlarge, ubuntu-latest, windows-latest ] runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v4 + - name: macos hardware info + if: matrix.platform == 'macos-latest-xlarge' + run: system_profiler SPSoftwareDataType SPHardwareDataType - name: get Git Tag shell: bash run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV @@ -123,7 +123,7 @@ jobs: shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-latest' || matrix.platform == 'macos-latest-large' + if: matrix.platform == 'macos-latest' || matrix.platform == 'macos-latest-xlarge' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -162,7 +162,7 @@ jobs: shell: bash - uses: tauri-apps/tauri-action@v0 - if: matrix.platform != 'macos-latest-large' + if: matrix.platform != 'macos-latest-xlarge' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} @@ -180,12 +180,12 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: setup env for mac arm (Mac only) - if: matrix.platform == 'macos-latest-large' + if: matrix.platform == 'macos-latest-xlarge' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-latest-large' + if: matrix.platform == 'macos-latest-xlarge' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From dd3144611cd1a8263e12852290b67b32c3d780a2 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 7 Nov 2023 12:15:04 +0530 Subject: [PATCH 189/864] chore: point to prod branch for prod build yml --- .github/workflows/tauri-build-prod.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 87120227..8f4ebcea 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -2,7 +2,7 @@ name: 'generate production draft GitHub release' on: push: - branches: [ xx ] + branches: [ prod ] jobs: create-release: From 1a98c4b11baf552d618c58e30c01a5b6a329a601 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 7 Nov 2023 18:09:30 +0530 Subject: [PATCH 190/864] feat: adding licence --- src-tauri/license/agpl | 661 ++++++++++++++++++++++++++++++++++++++ src-tauri/tauri.conf.json | 1 + 2 files changed, 662 insertions(+) create mode 100644 src-tauri/license/agpl diff --git a/src-tauri/license/agpl b/src-tauri/license/agpl new file mode 100644 index 00000000..be3f7b28 --- /dev/null +++ b/src-tauri/license/agpl @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 0b6dafb1..9e72434a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -144,6 +144,7 @@ "timestampUrl": "http://timestamp.comodoca.com", "nsis": { "displayLanguageSelector": true, + "license" : "./license/agpl", "languages": [ "English", "Afrikaans", From ba88ffb5146841e32d7e037060458f378e3a5563 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 8 Nov 2023 00:41:50 +0530 Subject: [PATCH 191/864] feat: add licence for mac --- src-tauri/tauri.conf.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 9e72434a..cfc961d2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -125,7 +125,8 @@ "exceptionDomain": "localhost", "frameworks": [], "providerShortName": null, - "signingIdentity": null + "signingIdentity": null, + "license" : "./license/agpl" }, "resources": [ "src-node/*" From e09d3833a9f8dc921de51c63a958a273b122c66b Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 9 Nov 2023 21:04:51 +0530 Subject: [PATCH 192/864] chore: change phcode protocol to phtauri as its interfering with phcode.site and other domains in windows --- src-build/ci-createDistReleaseConfig.js | 4 ++-- src-build/createDistReleaseConfig.js | 4 ++-- src-build/createDistTestReleaseConfig.js | 4 ++-- src-build/createSrcReleaseConfig.js | 4 ++-- src-tauri/src/main.rs | 17 +++++++++++++---- src-tauri/tauri.conf.json | 4 ++-- 6 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index 1e0a4b0a..a81c8b4f 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -74,9 +74,9 @@ async function ciCreateDistReleaseConfig() { console.log("Product name is: ", configJson.package.productName); configJson.tauri.windows[0].title = configJson.package.productName; if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = `https://phcode.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; } else { - configJson.tauri.windows[0].url = `phcode://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); configJson.tauri.updater.endpoints = [ diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index dade900f..57444e3b 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -22,9 +22,9 @@ async function createDistReleaseConfig() { configJson.build.distDir = '../../phoenix/dist/'; const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = `https://phcode.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; } else { - configJson.tauri.windows[0].url = `phcode://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index d754aea3..c26042b6 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -24,9 +24,9 @@ async function createDistTestReleaseConfig() { configJson.build.distDir = '../../phoenix/dist-test/'; const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = `https://phcode.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; } else { - configJson.tauri.windows[0].url = `phcode://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index b2a08928..97f4b12d 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -22,9 +22,9 @@ async function createSrcReleaseConfig() { configJson.build.distDir = '../../phoenix/src/' const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = `https://phcode.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; } else { - configJson.tauri.windows[0].url = `phcode://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 0dc0cf65..ab7495b8 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -120,9 +120,18 @@ fn remove_version_from_url(url: &str) -> String { fn main() { tauri::Builder::default() - .register_uri_scheme_protocol("phcode", move |app, request| { // can't use `tauri` because that's already in use + .register_uri_scheme_protocol("phtauri", move |app, request| { // can't use `tauri` because that's already in use let path = remove_version_from_url(request.uri()); - let path = path.strip_prefix("phcode://localhost").unwrap(); + let path = path.strip_prefix("phtauri://localhost"); + if path.is_none() { + let not_found_response = ResponseBuilder::new() + .status(404) + .mimetype("text/html") + .body("Asset not found".as_bytes().to_vec()) + .unwrap(); + return Ok(not_found_response); + } + let path = path.unwrap(); let path = percent_encoding::percent_decode(path.as_bytes()) .decode_utf8_lossy() .to_string(); @@ -143,9 +152,9 @@ fn main() { let asset = asset_option.unwrap(); #[cfg(windows)] - let window_origin = "https://phcode.localhost"; + let window_origin = "https://phtauri.localhost"; #[cfg(not(windows))] - let window_origin = "phcode://localhost"; + let window_origin = "phtauri://localhost"; let builder = ResponseBuilder::new() .header("Access-Control-Allow-Origin", window_origin) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index cfc961d2..4c0c4c13 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -223,7 +223,7 @@ "dangerousDisableAssetCspModification": true, "dangerousRemoteDomainIpcAccess": [ { - "scheme": "phcode", + "scheme": "phtauri", "domain": "localhost", "enableTauriAPI": true, "plugins": [ @@ -266,7 +266,7 @@ }, { "scheme": "https", - "domain": "phcode.localhost", + "domain": "phtauri.localhost", "enableTauriAPI": true, "plugins": [ "fs-extra" From ae8a5500a3e2543da4ceb9e5494b3e8f62eac136 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 9 Nov 2023 17:29:59 +0000 Subject: [PATCH 193/864] ci: update phcode version to 3.2.13 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 7 +++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 6f15c407..498d61d9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.11", + "version": "3.2.13", "type": "module", "scripts": { "tauri": "tauri", @@ -49,6 +49,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "76237ba61bb1a9b2dccff2afaad751f6bd04f87c" + "commit": "3a7dbcff076501a6733186fef00c8b64023a6117" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4e8e56e6..bf621854 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.11" +version = "3.2.13" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4c0c4c13..5df5b178 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.11" + "version": "3.2.13" }, "tauri": { "allowlist": { @@ -126,7 +126,7 @@ "frameworks": [], "providerShortName": null, "signingIdentity": null, - "license" : "./license/agpl" + "license": "./license/agpl" }, "resources": [ "src-node/*" @@ -145,7 +145,7 @@ "timestampUrl": "http://timestamp.comodoca.com", "nsis": { "displayLanguageSelector": true, - "license" : "./license/agpl", + "license": "./license/agpl", "languages": [ "English", "Afrikaans", @@ -262,7 +262,6 @@ "phcode-29", "phcode-30" ] - }, { "scheme": "https", From e7ca9adf87a4f5eff2a615b106fad1d77340264b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Nov 2023 17:32:48 +0000 Subject: [PATCH 194/864] chore(deps): update dependency axios to v1.6.1 --- package-lock.json | 194 +++------------------------------------------- package.json | 2 +- 2 files changed, 10 insertions(+), 186 deletions(-) diff --git a/package-lock.json b/package-lock.json index f1e0dd06..b69507f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,22 +1,21 @@ { "name": "phoenix-code-ide", - "version": "3.2.11", + "version": "3.2.13", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.11", + "version": "3.2.13", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.2", "adm-zip": "0.5.10", - "axios": "1.6.0", + "axios": "1.6.1", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", "fs-extra": "11.1.1", - "progress-stream": "2.0.0", "shx": "^0.3.4", "tar": "6.2.0" } @@ -259,9 +258,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", + "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -425,12 +424,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -785,12 +778,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1081,43 +1068,12 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-2.0.0.tgz", - "integrity": "sha512-xJwOWR46jcXUq6EH9yYyqp+I52skPySOeHfkxOZ2IY1AiBi/sFJhbhAKHoV3OTw/omQ45KTio9215dRJ2Yxd3Q==", - "dev": true, - "dependencies": { - "speedometer": "~1.0.0", - "through2": "~2.0.3" - } - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1174,12 +1130,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -1252,21 +1202,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/speedometer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-1.0.0.tgz", - "integrity": "sha512-lgxErLl/7A5+vgIIXsh9MbeukOaCb2axgQ+bKCdIE+ibNT4XNYGNCR1qFEGq6F+YDASXK3Fh/c5FgtZchFolxw==", - "dev": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -1334,16 +1269,6 @@ "node": ">=10" } }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1365,12 +1290,6 @@ "node": ">= 10.0.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -1412,15 +1331,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", @@ -1589,9 +1499,9 @@ "dev": true }, "axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", + "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", "dev": true, "requires": { "follow-redirects": "^1.15.0", @@ -1717,12 +1627,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1974,12 +1878,6 @@ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2188,43 +2086,12 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-2.0.0.tgz", - "integrity": "sha512-xJwOWR46jcXUq6EH9yYyqp+I52skPySOeHfkxOZ2IY1AiBi/sFJhbhAKHoV3OTw/omQ45KTio9215dRJ2Yxd3Q==", - "dev": true, - "requires": { - "speedometer": "~1.0.0", - "through2": "~2.0.3" - } - }, "proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2266,12 +2133,6 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -2320,21 +2181,6 @@ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true }, - "speedometer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-1.0.0.tgz", - "integrity": "sha512-lgxErLl/7A5+vgIIXsh9MbeukOaCb2axgQ+bKCdIE+ibNT4XNYGNCR1qFEGq6F+YDASXK3Fh/c5FgtZchFolxw==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -2381,16 +2227,6 @@ "yallist": "^4.0.0" } }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2406,12 +2242,6 @@ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2444,12 +2274,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", diff --git a/package.json b/package.json index 498d61d9..66a1736b 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "fs-extra": "11.1.1", "shx": "^0.3.4", "tar": "6.2.0", - "axios": "1.6.0" + "axios": "1.6.1" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From 8e941dd036d62a7f9d491024f78069c01b7dfa23 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 11 Nov 2023 17:16:03 +0530 Subject: [PATCH 195/864] ci: prod m1 builds were testing on dev builds --- .github/workflows/prod-desktop-mac-m1-tests-on-pull.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml index da031e83..59e8e156 100644 --- a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml @@ -32,7 +32,7 @@ jobs: cd phoenix npm ci npm run build - npm run release:dev + npm run release:prod - name: build test runner run: | From 7b69a746a875a4ddcfc0d39fe8334093c39da32b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Nov 2023 18:39:10 +0000 Subject: [PATCH 196/864] chore(deps): update actions/github-script action to v7 --- .github/workflows/tauri-build-dev.yml | 4 ++-- .github/workflows/tauri-build-prod.yml | 4 ++-- .github/workflows/tauri-build-staging.yml | 4 ++-- .github/workflows/updateNotification.yml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 8c87d382..cad37742 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -24,7 +24,7 @@ jobs: echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: create release id: create-release - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { data } = await github.rest.repos.createRelease({ @@ -208,7 +208,7 @@ jobs: run: echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: publish release id: publish-release - uses: actions/github-script@v6 + uses: actions/github-script@v7 env: release_id: ${{ needs.create-release.outputs.release_id }} with: diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 8f4ebcea..446a4d56 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -24,7 +24,7 @@ jobs: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: create release id: create-release - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { data } = await github.rest.repos.createRelease({ @@ -215,7 +215,7 @@ jobs: run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: publish release id: publish-release - uses: actions/github-script@v6 + uses: actions/github-script@v7 env: release_id: ${{ needs.create-release.outputs.release_id }} with: diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 401d9063..3753af40 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -24,7 +24,7 @@ jobs: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: create release id: create-release - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const { data } = await github.rest.repos.createRelease({ @@ -208,7 +208,7 @@ jobs: run: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: publish release id: publish-release - uses: actions/github-script@v6 + uses: actions/github-script@v7 env: release_id: ${{ needs.create-release.outputs.release_id }} with: diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml index a1ba66e1..31fceb46 100644 --- a/.github/workflows/updateNotification.yml +++ b/.github/workflows/updateNotification.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/checkout@v4 with: ref: main - - uses: actions/github-script@v6 + - uses: actions/github-script@v7 name: Update docs folder with tauri update jsons with: script: | From 4b8c73d68a9f462724612bbe460f4cb019ce0fca Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 14 Nov 2023 13:25:09 +0530 Subject: [PATCH 197/864] build: add beta tag to prod builds --- src-build/ci-createDistReleaseConfig.js | 7 ++----- src-build/constants.js | 2 +- src-tauri/Cargo.lock | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index a81c8b4f..5e410d55 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -27,14 +27,11 @@ function _removeSuffixesFromName(name) { function _getProductName(name, stage) { name = _removeSuffixesFromName(name); - if(stage === 'production') { - return name; // Phoenix Code - } if(!PRODUCT_NAME_SUFFIX_FOR_STAGE[stage]) { throw new Error(`Cannot build Phoenix for unknown environment ${stage}`); } - // return `Phoenix code Pre-release` or `Phoenix code Experimental Build` - return `${name} ${PRODUCT_NAME_SUFFIX_FOR_STAGE[stage]}`; + // return `Phoenix code Pre-release` or `Phoenix code Experimental Build` or `Phoenix code ` + return `${name} ${PRODUCT_NAME_SUFFIX_FOR_STAGE[stage]}`.trim(); } async function ciCreateDistReleaseConfig() { diff --git a/src-build/constants.js b/src-build/constants.js index ddbd426e..46dc67f1 100644 --- a/src-build/constants.js +++ b/src-build/constants.js @@ -3,7 +3,7 @@ export const PRODUCT_NAME_SUFFIX_FOR_STAGE = { // and brackets.config.staging.json. The product name suffix corresponding to each stage are values. dev : "Experimental Build", stage: "Pre-release", - production: "" // has no suffix + production: "Beta" // Change to empty if we are out of beta/alpha/rc . Prod has no suffix }; export const BUNDLE_IDENTIFIER_FOR_STAGE = { diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d763d265..bcb4b21b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2424,7 +2424,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.11" +version = "3.2.13" dependencies = [ "once_cell", "percent-encoding", From 04fcd2e8b39218940b7a1fd0258f5b17bd943d9b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Nov 2023 21:55:42 +0000 Subject: [PATCH 198/864] chore(deps): update dependency axios to v1.6.2 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index b69507f8..acfb5ab0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.5.2", "adm-zip": "0.5.10", - "axios": "1.6.1", + "axios": "1.6.2", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", @@ -258,9 +258,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", - "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -1499,9 +1499,9 @@ "dev": true }, "axios": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", - "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", + "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", "dev": true, "requires": { "follow-redirects": "^1.15.0", diff --git a/package.json b/package.json index 66a1736b..d5ef6f57 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "fs-extra": "11.1.1", "shx": "^0.3.4", "tar": "6.2.0", - "axios": "1.6.1" + "axios": "1.6.2" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From f00705db1ce7e52b0af79d6ef3d4447be79239e3 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 16 Nov 2023 21:04:44 +0530 Subject: [PATCH 199/864] feat: in app notifications scaffolding --- docs/appNotifications/dev/root/banner.json | 8 ++++ docs/appNotifications/dev/root/toast.json | 2 + docs/appNotifications/readme.md | 47 ++++++++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 docs/appNotifications/dev/root/banner.json create mode 100644 docs/appNotifications/dev/root/toast.json create mode 100644 docs/appNotifications/readme.md diff --git a/docs/appNotifications/dev/root/banner.json b/docs/appNotifications/dev/root/banner.json new file mode 100644 index 00000000..45f2b5f0 --- /dev/null +++ b/docs/appNotifications/dev/root/banner.json @@ -0,0 +1,8 @@ +{ + "WELCOME_DEVELOPER": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "

", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM" : "all" + } +} \ No newline at end of file diff --git a/docs/appNotifications/dev/root/toast.json b/docs/appNotifications/dev/root/toast.json new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/docs/appNotifications/dev/root/toast.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/docs/appNotifications/readme.md b/docs/appNotifications/readme.md new file mode 100644 index 00000000..66318fc0 --- /dev/null +++ b/docs/appNotifications/readme.md @@ -0,0 +1,47 @@ +## overview +This is used by in app banner or toast notification in phcode. It is automatically translated +by Google Translate. You just need to update `/root/banner.json` and +`/root/toast.json` folder in english language +and a pull request will be raised by GitHub actions translating it into all supported languages. + +You should merge the pull request if release is valid update, and then merge the `main` branch into +`update-notifications branch` to trigger the updates across the installation base. + +## banner notifications - `banner.json` +Banner notifications are shown at the bottom of brackets as seen in picture. Only use this in case of +emergencies to push security updates or other critical updates that needs user attention. Atmost one +banner notification will be shown at a time on screen. If there are multiple, the next notification will only be shown +once the current notification is closed. + +### Format of `/root/banner.json` + +`` can be `dev`, `staging` or `prod`. + +A sample json is as follows: +```json +{ + "SAMPLE_NOTIFICATION_NAME": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "", + "FOR_VERSIONS": "1.x || >=2.5.0 || 5.0.0 - 7.2.3", + "PLATFORM" : "allDesktop" + }, + "ANOTHER_SAMPLE_NOTIFICATION_NAME": {...} +} +``` + + By default, a notification is shown only once except if `DANGER_SHOW_ON_EVERY_BOOT` is set + or there is an html element with class `notification_ack`. + +1. `SAMPLE_NOTIFICATION_NAME` : This is a unique ID. It is used to check if the notification was shown to user. +2. `DANGER_SHOW_ON_EVERY_BOOT` : (Default false) Setting this to true will cause the + notification to be shown on every boot. This is bad ux and only be used if there is a critical security issue + that we want the version not to be used. +3. `HTML_CONTENT`: The actual html content to show to the user. It can have an optional `notification_ack` class. + Setting this class in any child html node will cause the notification to be shown once a day until the user explicitly clicks + on any html element with class `notification_ack` or explicitly click the close button. + If such a class is not present, then the notification is shown only once ever. +4. `FOR_VERSIONS` : [Semver compatible version filter](https://www.npmjs.com/package/semver). + The notification will be shown to all versions satisfying this. +5. `PLATFORM`: A comma seperated list of all platforms in which the message will be shown. + allowed values are: `mac,win,linux,allDesktop,firefox,chrome,safari,allBrowser,all` \ No newline at end of file From afc62f6d2177658431253e11bc138e7c2e89c377 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 18 Nov 2023 11:18:54 +0530 Subject: [PATCH 200/864] refactor: move dev notifications inside phcode --- docs/appNotifications/readme.md | 2 +- docs/appNotifications/{dev => staging}/root/banner.json | 0 docs/appNotifications/{dev => staging}/root/toast.json | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename docs/appNotifications/{dev => staging}/root/banner.json (100%) rename docs/appNotifications/{dev => staging}/root/toast.json (100%) diff --git a/docs/appNotifications/readme.md b/docs/appNotifications/readme.md index 66318fc0..9d03ba9b 100644 --- a/docs/appNotifications/readme.md +++ b/docs/appNotifications/readme.md @@ -15,7 +15,7 @@ once the current notification is closed. ### Format of `/root/banner.json` -`` can be `dev`, `staging` or `prod`. +`` can be `staging` or `prod`. (`dev` stage is directly in phoenix codebase for ease of development.) A sample json is as follows: ```json diff --git a/docs/appNotifications/dev/root/banner.json b/docs/appNotifications/staging/root/banner.json similarity index 100% rename from docs/appNotifications/dev/root/banner.json rename to docs/appNotifications/staging/root/banner.json diff --git a/docs/appNotifications/dev/root/toast.json b/docs/appNotifications/staging/root/toast.json similarity index 100% rename from docs/appNotifications/dev/root/toast.json rename to docs/appNotifications/staging/root/toast.json From 85e5dec9703881e0938929a37fb8f3810ba7ebf1 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 21 Nov 2023 11:33:22 +0530 Subject: [PATCH 201/864] docs: toast notification spec, not yet implemented tho --- docs/appNotifications/readme.md | 55 +++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/docs/appNotifications/readme.md b/docs/appNotifications/readme.md index 9d03ba9b..0778f3c1 100644 --- a/docs/appNotifications/readme.md +++ b/docs/appNotifications/readme.md @@ -8,6 +8,9 @@ You should merge the pull request if release is valid update, and then merge the `update-notifications branch` to trigger the updates across the installation base. ## banner notifications - `banner.json` + +![image](https://github.com/phcode-dev/phoenix/assets/5336369/0094d4fa-fb63-4884-90dc-13b025b2de5e) + Banner notifications are shown at the bottom of brackets as seen in picture. Only use this in case of emergencies to push security updates or other critical updates that needs user attention. Atmost one banner notification will be shown at a time on screen. If there are multiple, the next notification will only be shown @@ -43,5 +46,53 @@ A sample json is as follows: If such a class is not present, then the notification is shown only once ever. 4. `FOR_VERSIONS` : [Semver compatible version filter](https://www.npmjs.com/package/semver). The notification will be shown to all versions satisfying this. -5. `PLATFORM`: A comma seperated list of all platforms in which the message will be shown. - allowed values are: `mac,win,linux,allDesktop,firefox,chrome,safari,allBrowser,all` \ No newline at end of file +5. `PLATFORM`: A comma seperated list(no spaces) of all platforms in which the message will be shown. + allowed values are: `mac,win,linux,allDesktop,firefox,chrome,safari,allBrowser,all` + + +## toast notifications - `toast.json` + +Toast notifications are shown at the side on the general notification area. Multiple toast notifications +can be shown at the same time. Format is similar to banner notification. + +By default, a notification is shown only once and auto close after 25 seconds. +If there is an html element with class `notification_ack` it must be clicked to be dismissed, +else it will come up after every boot till it is acknowledged or the close button clicked. + +### Format of `/root/toast.json` + +> + +`` can be `staging` or `prod`. (`dev` stage is directly in phoenix codebase for ease of development.) + +A sample json is as follows: +```json +{ + "SAMPLE_NOTIFICATION_NAME": { + "TRIGGER" : "MENU_CLICK:file.newFolder,HTML_ELEMENT:#project-files-container", + "TYPE": "ERROR/WARN/INFO/SUCCESS", + "HTML_CONTENT": "", + "FOR_VERSIONS": "1.x || >=2.5.0 || 5.0.0 - 7.2.3", + "PLATFORM" : "allDesktop", + "autoCloseTimeS": 25 + }, + "ANOTHER_SAMPLE_NOTIFICATION_NAME": {...} +} +``` + +1. `SAMPLE_NOTIFICATION_NAME` : This is a unique ID. It is used to check if the notification was shown to user. +2. `TRIGGER` : The trigger to show the notification. Can be a comma seperated list of one of the following + `APP_START/MENU_CLICK:/KEYBOARD_SHORTCUT:/OTHER:/HTML_ELEMENT:<.class/#id>` + 1. `APP_START` : notification will be shown on app start. + 2. `MENU_CLICK:` : When a command is executed by clicking on a ui menu item. + 3. `KEYBOARD_SHORTCUT:` : When a command is executed by keyboard shortcut. + 4. `HTML_ELEMENT:` : On click on the given html element with jquery selector. +3. `HTML_CONTENT`: The actual html content to show to the user. It can have an optional `notification_ack` class. + Setting this class in any child html node will cause the notification to be shown once a day until the user explicitly clicks + on any html element with class `notification_ack` or explicitly click the close button. + If such a class is not present, then the notification is shown only once ever. +4. `FOR_VERSIONS` : [Semver compatible version filter](https://www.npmjs.com/package/semver). + The notification will be shown to all versions satisfying this. +5. `PLATFORM`: A comma seperated list(no spaces) of all platforms in which the message will be shown. + allowed values are: `mac,win,linux,allDesktop,firefox,chrome,safari,allBrowser,all` +6. `autoCloseTimeS`: Time to auto close the popup in seconds \ No newline at end of file From e4b12ccb2d8e29b7f6f5d16616da3d30e4c484b5 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 21 Nov 2023 11:34:12 +0530 Subject: [PATCH 202/864] docs: toast notification spec, not yet implemented tho --- docs/appNotifications/readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/appNotifications/readme.md b/docs/appNotifications/readme.md index 0778f3c1..99feb09e 100644 --- a/docs/appNotifications/readme.md +++ b/docs/appNotifications/readme.md @@ -87,7 +87,8 @@ A sample json is as follows: 2. `MENU_CLICK:` : When a command is executed by clicking on a ui menu item. 3. `KEYBOARD_SHORTCUT:` : When a command is executed by keyboard shortcut. 4. `HTML_ELEMENT:` : On click on the given html element with jquery selector. -3. `HTML_CONTENT`: The actual html content to show to the user. It can have an optional `notification_ack` class. +3. `TYPE` : Can be one of `ERROR/WARN/INFO/SUCCESS`. +4. `HTML_CONTENT`: The actual html content to show to the user. It can have an optional `notification_ack` class. Setting this class in any child html node will cause the notification to be shown once a day until the user explicitly clicks on any html element with class `notification_ack` or explicitly click the close button. If such a class is not present, then the notification is shown only once ever. From 7370e12137425118979e77e0f4a133d5532e7c85 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 29 Nov 2023 15:45:44 +0530 Subject: [PATCH 203/864] refactor: use tauri window position restore plugins instead of self impl --- src-tauri/Cargo.lock | 90 ++++++++++++++++++++++++------------ src-tauri/Cargo.toml | 1 + src-tauri/src/boot_config.rs | 18 +++----- src-tauri/src/init.rs | 49 ++------------------ src-tauri/src/main.rs | 5 +- 5 files changed, 74 insertions(+), 89 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index bcb4b21b..28058f80 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -200,7 +200,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c3d816ce6f0e2909a96830d6911c2aff044370b1ef92d7f267b43bae5addedd" dependencies = [ "atk-sys", - "bitflags", + "bitflags 1.3.2", "glib", "libc", ] @@ -267,12 +267,27 @@ version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "block" version = "0.1.6" @@ -367,7 +382,7 @@ version = "0.15.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c76ee391b03d35510d9fa917357c7f1855bd9a6659c95a1b392e33f49b3369bc" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-sys-rs", "glib", "libc", @@ -463,7 +478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "clap_lex", "indexmap 1.9.3", "strsim", @@ -486,7 +501,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "cocoa-foundation", "core-foundation", @@ -502,7 +517,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "core-foundation", "core-graphics-types", @@ -564,7 +579,7 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-graphics-types", "foreign-types", @@ -577,7 +592,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "libc", ] @@ -1057,7 +1072,7 @@ version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6e05c1f572ab0e1f15be94217f0dc29088c248b14f792a5ff0af0d84bcda9e8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-rs", "gdk-pixbuf", "gdk-sys", @@ -1073,7 +1088,7 @@ version = "0.15.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad38dd9cc8b099cceecdf41375bb6d481b1b5a7cd5cd603e10a69a9383f8619a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gdk-pixbuf-sys", "gio", "glib", @@ -1194,7 +1209,7 @@ version = "0.15.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68fdbc90312d462781a395f7a16d96a2b379bb6ef8cd6310a2df272771c4283b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "futures-channel", "futures-core", "futures-io", @@ -1224,7 +1239,7 @@ version = "0.15.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "futures-channel", "futures-core", "futures-executor", @@ -1300,7 +1315,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92e3004a2d5d6d8b5057d2b57b3712c9529b62e82c77f25c1fecde1fd5c23bd0" dependencies = [ "atk", - "bitflags", + "bitflags 1.3.2", "cairo-rs", "field-offset", "futures-channel", @@ -1673,7 +1688,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf053e7843f2812ff03ef5afe34bb9c06ffee120385caad4f6b9967fcd37d41c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "glib", "javascriptcore-rs-sys", ] @@ -1966,7 +1981,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" dependencies = [ - "bitflags", + "bitflags 1.3.2", "jni-sys", "ndk-sys", "num_enum", @@ -2000,7 +2015,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", "memoffset 0.7.1", @@ -2167,7 +2182,7 @@ version = "0.10.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -2254,7 +2269,7 @@ version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e4045548659aee5313bde6c582b0d83a627b7904dd20dc2d9ef0895d414e4f" dependencies = [ - "bitflags", + "bitflags 1.3.2", "glib", "libc", "once_cell", @@ -2434,6 +2449,7 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-fs-extra", + "tauri-plugin-window-state", "winapi", ] @@ -2475,7 +2491,7 @@ version = "0.17.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", @@ -2489,7 +2505,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", - "bitflags", + "bitflags 1.3.2", "cfg-if", "concurrent-queue", "libc", @@ -2679,7 +2695,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2688,7 +2704,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -2830,7 +2846,7 @@ version = "0.37.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -2892,7 +2908,7 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -2915,7 +2931,7 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cssparser", "derive_more", "fxhash", @@ -3164,7 +3180,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2b4d76501d8ba387cf0fefbe055c3e0a59891d09f0f995ae4e4b16f6b60f3c0" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gio", "glib", "libc", @@ -3178,7 +3194,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "009ef427103fcb17f802871647a7fa6c60cbb654b4c4e4c0ac60a31c5f6dc9cf" dependencies = [ - "bitflags", + "bitflags 1.3.2", "gio-sys", "glib-sys", "gobject-sys", @@ -3306,7 +3322,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6d198e01085564cea63e976ad1566c1ba2c2e4cc79578e35d9f05521505e31" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-rs", "cc", "cocoa", @@ -3497,8 +3513,22 @@ dependencies = [ [[package]] name = "tauri-plugin-fs-extra" version = "0.0.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#5b814f56e6368fdec46c4ddb04a07e0923ff995a" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#3db81b4fe30d2ddb9cc109852b90b1e37da9e4cd" +dependencies = [ + "log", + "serde", + "serde_json", + "tauri", + "thiserror", +] + +[[package]] +name = "tauri-plugin-window-state" +version = "0.1.0" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#3db81b4fe30d2ddb9cc109852b90b1e37da9e4cd" dependencies = [ + "bincode", + "bitflags 2.4.1", "log", "serde", "serde_json", @@ -4134,7 +4164,7 @@ version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8f859735e4a452aeb28c6c56a852967a8a76c8eb1cc32dbf931ad28a13d6370" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cairo-rs", "gdk", "gdk-sys", @@ -4159,7 +4189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d76ca6ecc47aeba01ec61e480139dda143796abcae6f83bcddf50d6b5b1dcf3" dependencies = [ "atk-sys", - "bitflags", + "bitflags 1.3.2", "cairo-sys-rs", "gdk-pixbuf-sys", "gdk-sys", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index bf621854..9263ee23 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -22,6 +22,7 @@ serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.2", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } +tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } [features] # by default Tauri runs in production mode diff --git a/src-tauri/src/boot_config.rs b/src-tauri/src/boot_config.rs index 1dfa19dc..19b61742 100644 --- a/src-tauri/src/boot_config.rs +++ b/src-tauri/src/boot_config.rs @@ -15,8 +15,7 @@ pub static APP_CONSTANTS: OnceCell = OnceCell::new(); #[derive(Serialize)] pub struct BootConfig { - pub last_window_width: u32, - pub last_window_height: u32, + pub version: u32 } static BOOT_CONFIG_FILE_NAME: &'static str = "boot_config.json"; @@ -27,11 +26,7 @@ fn get_boot_config_file_path(app_local_data_dir: &PathBuf) -> PathBuf { } fn _set_boot_config(boot_config: &mut BootConfig, value: &Value) { - boot_config.last_window_width = match value["last_window_width"].as_u64() { - Some(value) => value as u32, - None => 0 - }; - boot_config.last_window_height = match value["last_window_height"].as_u64() { + boot_config.version = match value["version"].as_u64() { Some(value) => value as u32, None => 0 }; @@ -39,8 +34,7 @@ fn _set_boot_config(boot_config: &mut BootConfig, value: &Value) { pub fn read_boot_config() -> BootConfig { let mut boot_config = BootConfig { - last_window_width: 0, - last_window_height: 0 + version: 1 }; if let Some(app_constants) = APP_CONSTANTS.get() { let boot_config_file_path = get_boot_config_file_path(&app_constants.app_local_data_dir); @@ -67,9 +61,9 @@ fn _write_boot_config(boot_config: &BootConfig) { } } -pub fn write_boot_config(last_window_width: u32, last_window_height: u32) { +// WARNING: If there are multiple windows, this will be called on each window close. +pub fn write_boot_config(version: u32) { _write_boot_config(&BootConfig { - last_window_width, - last_window_height + version }) } \ No newline at end of file diff --git a/src-tauri/src/init.rs b/src-tauri/src/init.rs index e5be0a02..1532a8c8 100644 --- a/src-tauri/src/init.rs +++ b/src-tauri/src/init.rs @@ -1,51 +1,8 @@ -use tauri::Manager; use crate::utilities::ensure_dir_exists; use crate::boot_config::read_boot_config; -use crate::boot_config::BootConfig; use crate::boot_config::APP_CONSTANTS; use crate::boot_config::AppConstants; -static PREFERRED_WIDTH: u32 = 1366; -static PREFERRED_HEIGHT: u32 = 900; -static MAXIMIZE_SIZE: u32 = 0; - -fn get_window_size(last_saved_size: u32, screen_size: u32, preferred_size: u32) -> u32 { - if last_saved_size != 0 { - // we dont do last_saved_size Date: Tue, 28 Nov 2023 03:47:19 +0000 Subject: [PATCH 204/864] chore(deps): update dependency fs-extra to v11.2.0 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index acfb5ab0..f799ac0e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,7 @@ "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", - "fs-extra": "11.1.1", + "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.0" } @@ -544,9 +544,9 @@ } }, "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -1709,9 +1709,9 @@ } }, "fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "requires": { "graceful-fs": "^4.2.0", diff --git a/package.json b/package.json index d5ef6f57..e08f4e62 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", - "fs-extra": "11.1.1", + "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.0", "axios": "1.6.2" From addab34e5491c1eae4df4af0140eadf9b2e086f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Nov 2023 12:17:05 +0000 Subject: [PATCH 205/864] build(deps): bump openssl from 0.10.55 to 0.10.60 in /src-tauri Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.55 to 0.10.60. - [Release notes](https://github.com/sfackler/rust-openssl/releases) - [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.55...openssl-v0.10.60) --- updated-dependencies: - dependency-name: openssl dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 28058f80..2407f327 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2178,11 +2178,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -2210,9 +2210,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" dependencies = [ "cc", "libc", From b1a440e58b550b071e2cf7fd1552d55f89f6be45 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 2 Dec 2023 17:07:35 +0000 Subject: [PATCH 206/864] ci: update phcode version to 3.2.14 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e08f4e62..1e594159 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.13", + "version": "3.2.14", "type": "module", "scripts": { "tauri": "tauri", @@ -49,6 +49,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "3a7dbcff076501a6733186fef00c8b64023a6117" + "commit": "03de8c9d979f4cec576a72d2e843b3519015c323" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9263ee23..1a7fe40b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.13" +version = "3.2.14" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 5df5b178..ce23638f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.13" + "version": "3.2.14" }, "tauri": { "allowlist": { From 12d54a94658611e0c94d436594e3f4db0a960d6f Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 2 Dec 2023 22:42:32 +0530 Subject: [PATCH 207/864] build: update tauri to 1.5.3 --- src-tauri/Cargo.lock | 1372 ++++++++++++++++++++++++++---------------- src-tauri/Cargo.toml | 2 +- 2 files changed, 860 insertions(+), 514 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2407f327..6310ee02 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -19,18 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -67,9 +58,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "async-broadcast" @@ -77,32 +68,34 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" dependencies = [ - "event-listener", + "event-listener 2.5.3", "futures-core", ] [[package]] name = "async-channel" -version = "1.9.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" dependencies = [ "concurrent-queue", - "event-listener", + "event-listener 4.0.0", + "event-listener-strategy", "futures-core", + "pin-project-lite", ] [[package]] name = "async-executor" -version = "1.5.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" dependencies = [ - "async-lock", + "async-lock 3.1.2", "async-task", "concurrent-queue", - "fastrand", - "futures-lite", + "fastrand 2.0.1", + "futures-lite 2.0.1", "slab", ] @@ -112,10 +105,10 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "blocking", - "futures-lite", + "futures-lite 1.13.0", ] [[package]] @@ -124,73 +117,120 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", - "futures-lite", + "futures-lite 1.13.0", "log", "parking", - "polling", - "rustix", + "polling 2.8.0", + "rustix 0.37.27", "slab", - "socket2", + "socket2 0.4.10", "waker-fn", ] +[[package]] +name = "async-io" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6d3b15875ba253d1110c740755e246537483f152fa334f91abd7fe84c88b3ff" +dependencies = [ + "async-lock 3.1.2", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.0.1", + "parking", + "polling 3.3.1", + "rustix 0.38.26", + "slab", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "async-lock" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" dependencies = [ - "event-listener", + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea8b3453dd7cc96711834b75400d671b73e3656975fa68d9f277163b7f7e316" +dependencies = [ + "event-listener 4.0.0", + "event-listener-strategy", + "pin-project-lite", ] [[package]] name = "async-process" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" dependencies = [ - "async-io", - "async-lock", - "autocfg", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", "blocking", "cfg-if", - "event-listener", - "futures-lite", - "rustix", - "signal-hook", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.26", "windows-sys 0.48.0", ] [[package]] name = "async-recursion" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" +checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", +] + +[[package]] +name = "async-signal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +dependencies = [ + "async-io 2.2.1", + "async-lock 2.8.0", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.26", + "signal-hook-registry", + "slab", + "windows-sys 0.48.0", ] [[package]] name = "async-task" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" [[package]] name = "async-trait" -version = "0.1.69" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b2d0f03b3640e3a630367e40c468cb7f309529c708ed1d88597047b0e7c6ef7" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] @@ -214,14 +254,14 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] name = "atomic-waker" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atty" @@ -242,9 +282,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -263,9 +303,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "bincode" @@ -305,24 +345,25 @@ dependencies = [ [[package]] name = "blocking" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ "async-channel", - "async-lock", + "async-lock 3.1.2", "async-task", - "atomic-waker", - "fastrand", - "futures-lite", - "log", + "fastrand 2.0.1", + "futures-io", + "futures-lite 2.0.1", + "piper", + "tracing", ] [[package]] name = "brotli" -version = "3.3.4" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -331,9 +372,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.3.4" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" +checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -341,9 +382,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.5.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" +checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" dependencies = [ "memchr", "serde", @@ -351,27 +392,27 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde", ] @@ -397,7 +438,7 @@ checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" dependencies = [ "glib-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] @@ -407,14 +448,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "599aa35200ffff8f04c1925aa1acc92fa2e08874379ef42e210a80e527e60838" dependencies = [ "serde", - "toml 0.7.5", + "toml 0.7.8", ] [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cesu8" @@ -444,9 +488,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.3" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "215c0072ecc28f92eeb0eea38ba63ddfcb65c2828c46311d646f1a3ff5f9841c" +checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" dependencies = [ "smallvec", "target-lexicon", @@ -460,15 +504,15 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "winapi", + "windows-targets 0.48.5", ] [[package]] @@ -513,15 +557,14 @@ dependencies = [ [[package]] name = "cocoa-foundation" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", "core-foundation", "core-graphics-types", - "foreign-types", "libc", "objc", ] @@ -544,9 +587,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" dependencies = [ "crossbeam-utils", ] @@ -559,9 +602,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -569,9 +612,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core-graphics" @@ -588,9 +631,9 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -599,9 +642,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] @@ -625,6 +668,30 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset 0.9.0", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.16" @@ -668,24 +735,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] name = "ctor" -version = "0.1.26" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" dependencies = [ "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] name = "darling" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ "darling_core", "darling_macro", @@ -693,27 +760,37 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] name = "darling_macro" -version = "0.20.1" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.22", + "syn 2.0.39", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", + "serde", ] [[package]] @@ -779,9 +856,9 @@ checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" [[package]] name = "dtoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "dtoa-short" @@ -800,15 +877,15 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "embed-resource" -version = "2.1.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80663502655af01a2902dff3f06869330782267924bf1788410b74edcd93770a" +checksum = "f54cc3e827ee1c3812239a9a41dede7b4d7d5d5464faa32d71bd7cba28ce2cb2" dependencies = [ "cc", "rustc_version", - "toml 0.7.5", + "toml 0.8.8", "vswhom", - "winreg 0.11.0", + "winreg 0.51.0", ] [[package]] @@ -819,18 +896,18 @@ checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] [[package]] name = "enumflags2" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2" +checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" dependencies = [ "enumflags2_derive", "serde", @@ -838,47 +915,68 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" +checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "errno-dragonfly", "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "event-listener" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" dependencies = [ - "cc", - "libc", + "concurrent-queue", + "parking", + "pin-project-lite", ] [[package]] name = "event-listener" -version = "2.5.3" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.0", + "pin-project-lite", +] [[package]] name = "fastrand" @@ -889,11 +987,17 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "fdeflate" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10" +checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" dependencies = [ "simd-adler32", ] @@ -910,21 +1014,21 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "windows-sys 0.48.0", ] [[package]] name = "flate2" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -953,9 +1057,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -972,24 +1076,24 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -998,9 +1102,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-lite" @@ -1008,7 +1112,7 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", @@ -1017,34 +1121,48 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +dependencies = [ + "fastrand 2.0.1", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-core", "futures-io", @@ -1105,7 +1223,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] @@ -1122,7 +1240,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] @@ -1136,7 +1254,7 @@ dependencies = [ "gobject-sys", "libc", "pkg-config", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] @@ -1148,7 +1266,7 @@ dependencies = [ "gdk-sys", "glib-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.2.0", "x11", ] @@ -1188,9 +1306,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -1199,9 +1317,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "gio" @@ -1229,7 +1347,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.2.0", "winapi", ] @@ -1275,7 +1393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" dependencies = [ "libc", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] @@ -1286,15 +1404,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.10" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.3", + "regex-syntax 0.8.2", ] [[package]] @@ -1305,7 +1423,7 @@ checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" dependencies = [ "glib-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] @@ -1346,7 +1464,7 @@ dependencies = [ "gobject-sys", "libc", "pango-sys", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] @@ -1365,9 +1483,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -1375,7 +1493,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -1390,9 +1508,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "heck" @@ -1420,9 +1538,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -1460,13 +1578,13 @@ dependencies = [ [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", - "itoa 1.0.6", + "itoa 1.0.9", ] [[package]] @@ -1494,9 +1612,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" @@ -1513,9 +1631,9 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.6", + "itoa 1.0.9", "pin-project-lite", - "socket2", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -1537,16 +1655,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows 0.48.0", + "windows-core", ] [[package]] @@ -1576,9 +1694,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1586,26 +1704,25 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492" +checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060" dependencies = [ + "crossbeam-deque", "globset", - "lazy_static", "log", "memchr", - "regex", + "regex-automata 0.4.3", "same-file", - "thread_local", "walkdir", "winapi-util", ] [[package]] name = "image" -version = "0.24.6" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" dependencies = [ "bytemuck", "byteorder", @@ -1627,19 +1744,20 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.3", + "serde", ] [[package]] name = "infer" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a898e4b7951673fce96614ce5751d13c40fc5674bc2d759288e46c3ab62598b3" +checksum = "f551f8c3a39f68f986517db0d1759de85881894fdc7db798bd2a9df9cb04b7fc" dependencies = [ "cfb", ] @@ -1659,16 +1777,16 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi 0.3.3", "libc", "windows-sys 0.48.0", ] [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itoa" @@ -1678,9 +1796,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "javascriptcore-rs" @@ -1727,18 +1845,18 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] [[package]] name = "json-patch" -version = "1.0.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f54898088ccb91df1b492cc80029a6fdf1c48ca0db7c6822a8babad69c94658" +checksum = "55ff1e1486799e3f64129f8ccad108b38290df9cd7015cd31bed17239f0789d6" dependencies = [ "serde", "serde_json", @@ -1779,9 +1897,20 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "libredox" +version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall 0.4.1", +] [[package]] name = "line-wrap" @@ -1798,11 +1927,17 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -1837,9 +1972,9 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "mac-notification-sys" -version = "0.5.8" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abc434554ad0e640d772f7f262aa28e61d485212533d3673abe5f3d1729bd42a" +checksum = "51fca4d74ff9dbaac16a01b924bc3693fa2bba0862c2c633abc73f9a8ea21f64" dependencies = [ "cc", "dirs-next", @@ -1948,9 +2083,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -2011,15 +2146,14 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", "memoffset 0.7.1", - "static_assertions", ] [[package]] @@ -2030,9 +2164,9 @@ checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" [[package]] name = "notify-rust" -version = "4.8.0" +version = "4.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bfa211d18e360f08e36c364308f394b5eb23a6629150690e109a916dc6f610e" +checksum = "827c5edfa80235ded4ab3fe8e9dc619b4f866ef16fe9b1c6b8a7f8692c0f2226" dependencies = [ "log", "mac-notification-sys", @@ -2074,9 +2208,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] @@ -2087,7 +2221,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi 0.3.3", "libc", ] @@ -2153,9 +2287,9 @@ dependencies = [ [[package]] name = "object" -version = "0.31.1" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -2199,7 +2333,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] @@ -2253,9 +2387,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "overload" @@ -2285,14 +2419,14 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] name = "parking" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "parking_lot" @@ -2306,15 +2440,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "smallvec", - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -2325,9 +2459,9 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" @@ -2346,9 +2480,17 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ - "phf_macros 0.10.0", "phf_shared 0.10.0", - "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros 0.11.2", + "phf_shared 0.11.2", ] [[package]] @@ -2391,6 +2533,16 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared 0.11.2", + "rand 0.8.5", +] + [[package]] name = "phf_macros" version = "0.8.0" @@ -2407,16 +2559,15 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.10.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", - "proc-macro-hack", + "phf_generator 0.11.2", + "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] @@ -2437,9 +2588,18 @@ dependencies = [ "siphasher", ] +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + [[package]] name = "phoenix-code-ide" -version = "3.2.13" +version = "3.2.14" dependencies = [ "once_cell", "percent-encoding", @@ -2455,9 +2615,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -2465,6 +2625,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.1", + "futures-io", +] + [[package]] name = "pkg-config" version = "0.3.27" @@ -2473,23 +2644,23 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "plist" -version = "1.4.3" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590" +checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ - "base64 0.21.2", - "indexmap 1.9.3", + "base64 0.21.5", + "indexmap 2.1.0", "line-wrap", - "quick-xml 0.28.2", + "quick-xml 0.31.0", "serde", "time", ] [[package]] name = "png" -version = "0.17.9" +version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59871cc5b6cce7eaccca5a802b4173377a1c2ba90654246789a8fa2334426d11" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -2514,6 +2685,26 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "polling" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e" +dependencies = [ + "cfg-if", + "concurrent-queue", + "pin-project-lite", + "rustix 0.38.26", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -2533,7 +2724,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -2568,36 +2759,36 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] [[package]] name = "quick-xml" -version = "0.23.1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bafc859c6815fbaffbbbf4229ecb767ac913fecb27f9ad4343662e9ef099ea" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" dependencies = [ "memchr", ] [[package]] name = "quick-xml" -version = "0.28.2" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.29" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -2662,7 +2853,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -2691,30 +2882,30 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.10", - "redox_syscall 0.2.16", + "getrandom 0.2.11", + "libredox", "thiserror", ] @@ -2724,7 +2915,7 @@ version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick", "memchr", "regex-automata 0.4.3", "regex-syntax 0.8.2", @@ -2745,7 +2936,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ - "aho-corasick 1.0.2", + "aho-corasick", "memchr", "regex-syntax 0.8.2", ] @@ -2764,11 +2955,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -2789,6 +2980,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tokio-util", @@ -2798,7 +2990,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "winreg 0.10.1", + "winreg 0.50.0", ] [[package]] @@ -2842,29 +3034,42 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.25" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.8", "windows-sys 0.48.0", ] +[[package]] +name = "rustix" +version = "0.38.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys 0.4.12", + "windows-sys 0.52.0", +] + [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "safemem" @@ -2883,11 +3088,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -2898,15 +3103,15 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -2917,9 +3122,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -2947,60 +3152,60 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.164" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ - "itoa 1.0.6", + "itoa 1.0.9", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] name = "serde_spanned" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" dependencies = [ "serde", ] @@ -3012,21 +3217,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.6", + "itoa 1.0.9", "ryu", "serde", ] [[package]] name = "serde_with" -version = "3.0.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02d8aa6e3c385bf084924f660ce2a3a6bd333ba55b35e8590b321f35d88513" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "chrono", "hex", "indexmap 1.9.3", + "indexmap 2.1.0", "serde", "serde_json", "serde_with_macros", @@ -3035,14 +3241,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.0.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc7d5d3932fb12ce722ee5e64dd38c504efba37567f0c402f6ca728c3b8b070" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] @@ -3079,9 +3285,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -3090,9 +3296,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -3101,9 +3307,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -3118,16 +3324,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -3139,41 +3335,51 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "siphasher" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", ] +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "soup2" version = "0.2.1" @@ -3268,9 +3474,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.22" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -3290,6 +3496,27 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "5.0.0" @@ -3305,22 +3532,22 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.1.1" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30c2de8a4d8f4b823d634affc9cd2a74ec98c53a756f317e529a48046cbf71f3" +checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" dependencies = [ - "cfg-expr 0.15.3", + "cfg-expr 0.15.5", "heck 0.4.1", "pkg-config", - "toml 0.7.5", + "toml 0.8.8", "version-compare 0.1.1", ] [[package]] name = "tao" -version = "0.16.2" +version = "0.16.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6d198e01085564cea63e976ad1566c1ba2c2e4cc79578e35d9f05521505e31" +checksum = "75f5aefd6be4cd3ad3f047442242fd9f57cbfb3e565379f66b5e14749364fa4f" dependencies = [ "bitflags 1.3.2", "cairo-rs", @@ -3365,9 +3592,9 @@ dependencies = [ [[package]] name = "tao-macros" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b27a4bcc5eb524658234589bdffc7e7bfb996dbae6ce9393bfd39cb4159b445" +checksum = "ec114582505d158b669b136e6851f85840c109819d77c42bb7c0709f727d18c2" dependencies = [ "proc-macro2", "quote", @@ -3376,9 +3603,9 @@ dependencies = [ [[package]] name = "tar" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b55807c0344e1e6c04d7c965f5289c39a8d94ae23ed5c0b57aabac549f871c6" +checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb" dependencies = [ "filetime", "libc", @@ -3387,18 +3614,18 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.8" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1c7f239eb94671427157bd93b3694320f3668d4e1eff08c7285366fd777fac" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tauri" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bfe673cf125ef364d6f56b15e8ce7537d9ca7e4dae1cf6fbbdeed2e024db3d9" +checksum = "32d563b672acde8d0cc4c1b1f5b855976923f67e8d6fe1eba51df0211e197be2" dependencies = [ "anyhow", - "base64 0.21.2", + "base64 0.21.5", "bytes", "clap", "cocoa", @@ -3476,7 +3703,7 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b3475e55acec0b4a50fb96435f19631fb58cbcd31923e1a213de5c382536bbb" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "brotli", "ico", "json-patch", @@ -3498,9 +3725,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613740228de92d9196b795ac455091d3a5fbdac2654abb8bb07d010b62ab43af" +checksum = "acea6445eececebd72ed7720cfcca46eee3b5bad8eb408be8f7ef2e3f7411500" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -3513,7 +3740,7 @@ dependencies = [ [[package]] name = "tauri-plugin-fs-extra" version = "0.0.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#3db81b4fe30d2ddb9cc109852b90b1e37da9e4cd" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#ad5ec05e2639b33f0475a0eefa8684bfa4b92be8" dependencies = [ "log", "serde", @@ -3525,7 +3752,7 @@ dependencies = [ [[package]] name = "tauri-plugin-window-state" version = "0.1.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#3db81b4fe30d2ddb9cc109852b90b1e37da9e4cd" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#ad5ec05e2639b33f0475a0eefa8684bfa4b92be8" dependencies = [ "bincode", "bitflags 2.4.1", @@ -3559,9 +3786,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8141d72b6b65f2008911e9ef5b98a68d1e3413b7a1464e8f85eb3673bb19a895" +checksum = "803a01101bc611ba03e13329951a1bde44287a54234189b9024b78619c1bc206" dependencies = [ "cocoa", "gtk", @@ -3579,9 +3806,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d55e185904a84a419308d523c2c6891d5e2dbcee740c4997eb42e75a7b0f46" +checksum = "a52165bb340e6f6a75f1f5eeeab1bb49f861c12abe3a176067d53642b5454986" dependencies = [ "brotli", "ctor", @@ -3594,7 +3821,7 @@ dependencies = [ "kuchikiki", "log", "memchr", - "phf 0.10.1", + "phf 0.11.2", "proc-macro2", "quote", "semver", @@ -3604,7 +3831,7 @@ dependencies = [ "thiserror", "url", "walkdir", - "windows 0.39.0", + "windows-version", ] [[package]] @@ -3614,30 +3841,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5993dc129e544393574288923d1ec447c857f3f644187f4fbf7d9a875fbfc4fb" dependencies = [ "embed-resource", - "toml 0.7.5", + "toml 0.7.8", ] [[package]] name = "tauri-winrt-notification" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5bff1d532fead7c43324a0fa33643b8621a47ce2944a633be4cb6c0240898f" +checksum = "006851c9ccefa3c38a7646b8cec804bb429def3da10497bfa977179869c3e8e2" dependencies = [ - "quick-xml 0.23.1", - "windows 0.39.0", + "quick-xml 0.30.0", + "windows 0.51.1", ] [[package]] name = "tempfile" -version = "3.6.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ - "autocfg", "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix", + "fastrand 2.0.1", + "redox_syscall 0.4.1", + "rustix 0.38.26", "windows-sys 0.48.0", ] @@ -3654,9 +3880,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" dependencies = [ "winapi-util", ] @@ -3675,22 +3901,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] @@ -3705,11 +3931,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.22" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ - "itoa 1.0.6", + "deranged", + "itoa 1.0.9", + "powerfmt", "serde", "time-core", "time-macros", @@ -3717,15 +3945,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -3747,18 +3975,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.5", "windows-sys 0.48.0", ] @@ -3774,9 +4001,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -3797,32 +4024,57 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.5" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.21.0", ] [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.1.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.1.0", "serde", "serde_spanned", "toml_datetime", @@ -3837,11 +4089,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -3849,20 +4100,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -3870,20 +4121,20 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -3914,9 +4165,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uds_windows" @@ -3936,9 +4187,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -3957,9 +4208,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "url" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -3975,11 +4226,11 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "uuid" -version = "1.4.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] @@ -4034,15 +4285,15 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -4071,9 +4322,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4081,24 +4332,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" dependencies = [ "cfg-if", "js-sys", @@ -4108,9 +4359,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4118,28 +4369,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "wasm-streams" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" +checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" dependencies = [ "futures-util", "js-sys", @@ -4150,9 +4401,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" dependencies = [ "js-sys", "wasm-bindgen", @@ -4202,7 +4453,7 @@ dependencies = [ "pango-sys", "pkg-config", "soup2-sys", - "system-deps 6.1.1", + "system-deps 6.2.0", ] [[package]] @@ -4261,9 +4512,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -4307,7 +4558,17 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets 0.48.5", ] [[package]] @@ -4320,6 +4581,15 @@ dependencies = [ "windows-tokens", ] +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-implement" version = "0.39.0" @@ -4366,7 +4636,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -4386,17 +4665,32 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -4405,6 +4699,15 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f838de2fe15fe6bac988e74b798f26499a8b21a9d97edec321e79b28d1d7f597" +[[package]] +name = "windows-version" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75aa004c988e080ad34aff5739c39d0312f4684699d6d71fc8a198d057b8b9b4" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -4413,9 +4716,15 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" @@ -4437,9 +4746,15 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" @@ -4461,9 +4776,15 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" @@ -4485,9 +4806,15 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" @@ -4509,9 +4836,15 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" @@ -4521,9 +4854,15 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" @@ -4545,43 +4884,50 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.4.7" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] name = "winreg" -version = "0.11.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a1a57ff50e9b408431e8f97d5456f2807f8eb2a2cd79b06068fc87f8ecf189" +checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "wry" -version = "0.24.4" +version = "0.24.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ef04bdad49eba2e01f06e53688c8413bd6a87b0bc14b72284465cf96e3578e" +checksum = "64a70547e8f9d85da0f5af609143f7bde3ac7457a6e1073104d9b73d6c5ac744" dependencies = [ "base64 0.13.1", "block", @@ -4638,9 +4984,9 @@ dependencies = [ [[package]] name = "xattr" -version = "0.2.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc" +checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" dependencies = [ "libc", ] @@ -4664,8 +5010,8 @@ dependencies = [ "async-broadcast", "async-executor", "async-fs", - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "async-process", "async-recursion", "async-task", @@ -4674,7 +5020,7 @@ dependencies = [ "byteorder", "derivative", "enumflags2", - "event-listener", + "event-listener 2.5.3", "futures-core", "futures-sink", "futures-util", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1a7fe40b..43943d1c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,7 +19,7 @@ once_cell = "1.18.0" percent-encoding = "2.3" regex = "1.10.2" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.5.2", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } +tauri = { version = "1.5.3", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From 407ca4568949c2434ed5eb08f53f91766785f9f9 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sun, 3 Dec 2023 16:42:16 +0000 Subject: [PATCH 208/864] ci: update phcode version to 3.2.15 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 1e594159..546f9812 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.14", + "version": "3.2.15", "type": "module", "scripts": { "tauri": "tauri", @@ -49,6 +49,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "03de8c9d979f4cec576a72d2e843b3519015c323" + "commit": "56b0eba5b65d1d73faee3113eae7b368cec911d3" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 43943d1c..4bb283dc 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.14" +version = "3.2.15" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ce23638f..215fbdad 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.14" + "version": "3.2.15" }, "tauri": { "allowlist": { From a441659820ce25f6369011d301079742058b1105 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 5 Dec 2023 09:17:39 +0530 Subject: [PATCH 209/864] deps: upgrade tauri cli to bring in windows install speed fix --- package-lock.json | 178 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/package-lock.json b/package-lock.json index f799ac0e..f37d0992 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "phoenix-code-ide", - "version": "3.2.13", + "version": "3.2.15", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.13", + "version": "3.2.15", "hasInstallScript": true, "devDependencies": { - "@tauri-apps/cli": "1.5.2", + "@tauri-apps/cli": "1.5.7", "adm-zip": "0.5.10", "axios": "1.6.2", "chalk": "^5.3.0", @@ -21,9 +21,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.2.tgz", - "integrity": "sha512-x4rPinrdyWLdTU5TbV7wrXudOyMilv0nmi1rngm/jwN3MmZdAj5J2xaS2rYtA8BU3oM/SE34qQwYxv1a2sM9ug==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.7.tgz", + "integrity": "sha512-z7nXLpDAYfQqR5pYhQlWOr88DgPq1AfQyxHhGiakiVgWlaG0ikEfQxop2txrd52H0TRADG0JHR9vFrVFPv4hVQ==", "dev": true, "bin": { "tauri": "tauri.js" @@ -36,22 +36,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.5.2", - "@tauri-apps/cli-darwin-x64": "1.5.2", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.2", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.2", - "@tauri-apps/cli-linux-arm64-musl": "1.5.2", - "@tauri-apps/cli-linux-x64-gnu": "1.5.2", - "@tauri-apps/cli-linux-x64-musl": "1.5.2", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.2", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.2", - "@tauri-apps/cli-win32-x64-msvc": "1.5.2" + "@tauri-apps/cli-darwin-arm64": "1.5.7", + "@tauri-apps/cli-darwin-x64": "1.5.7", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.7", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.7", + "@tauri-apps/cli-linux-arm64-musl": "1.5.7", + "@tauri-apps/cli-linux-x64-gnu": "1.5.7", + "@tauri-apps/cli-linux-x64-musl": "1.5.7", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.7", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.7", + "@tauri-apps/cli-win32-x64-msvc": "1.5.7" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.2.tgz", - "integrity": "sha512-3mYN15jpYjuuHRWii5Xk6JvB3ZLEgAZkeVgc5Hg7k3Yw1ZBrEGiUNe3Ku4DjbkYWL/QDd7oteIJnQk3j0mXwEg==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.7.tgz", + "integrity": "sha512-eUpOUhs2IOpKaLa6RyGupP2owDLfd0q2FR/AILzryjtBtKJJRDQQvuotf+LcbEce2Nc2AHeYJIqYAsB4sw9K+g==", "cpu": [ "arm64" ], @@ -65,9 +65,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.2.tgz", - "integrity": "sha512-8Jsl+EKBGdBoRUIR5ohjiTV6uG+pFpkNwHB4WaOzzR//v6p0lGULk2ohPIjJxhoQIFIN9oBd8bsSSNbZO/57/g==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.7.tgz", + "integrity": "sha512-zfumTv1xUuR+RB1pzhRy+51tB6cm8I76g0xUBaXOfEdOJ9FqW5GW2jdnEUbpNuU65qJ1lB8LVWHKGrSWWKazew==", "cpu": [ "x64" ], @@ -81,9 +81,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.2.tgz", - "integrity": "sha512-oWzcQtZogchdCSdQ+eEbDJHjJO9BGPO9EZNfvI2u3JzS/hJj4wCwnGHvZGI4jJ/6cnmcNvtt9ZftYYN4rpQW7A==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.7.tgz", + "integrity": "sha512-JngWNqS06bMND9PhiPWp0e+yknJJuSozsSbo+iMzHoJNRauBZCUx+HnUcygUR66Cy6qM4eJvLXtsRG7ApxvWmg==", "cpu": [ "arm" ], @@ -97,9 +97,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.2.tgz", - "integrity": "sha512-hfIUtys+SrrGEpLhQJwmL16g1FDhfObR4AGahCMqvMwA25uQKhtzRhxieO4X3k03vBeboTyJla5a2rX4TQ4lXA==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.7.tgz", + "integrity": "sha512-WyIYP9BskgBGq+kf4cLAyru8ArrxGH2eMYGBJvuNEuSaqBhbV0i1uUxvyWdazllZLAEz1WvSocUmSwLknr1+sQ==", "cpu": [ "arm64" ], @@ -113,9 +113,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.2.tgz", - "integrity": "sha512-ZpFX4HyjkJHfF0geVVpq5fNjEXG8766LRg/BL4/wKy8MNbqcc/aW3sLEpVj0GvdulxOnd2trDb1FJdZ206Kp8g==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.7.tgz", + "integrity": "sha512-OrDpihQP2MB0JY1a/wP9wsl9dDjFDpVEZOQxt4hU+UVGRCZQok7ghPBg4+Xpd1CkNkcCCuIeY8VxRvwLXpnIzg==", "cpu": [ "arm64" ], @@ -129,9 +129,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.2.tgz", - "integrity": "sha512-/kEZrDVZv1+qYpZigtLntX4s+gx7WQqp8cmxKZL5GrzAjUNSTnfWK5VL7o0lYm09QBJAdTvjcJu2aPzNHLDS+Q==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.7.tgz", + "integrity": "sha512-4T7FAYVk76rZi8VkuLpiKUAqaSxlva86C1fHm/RtmoTKwZEV+MI3vIMoVg+AwhyWIy9PS55C75nF7+OwbnFnvQ==", "cpu": [ "x64" ], @@ -145,9 +145,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.2.tgz", - "integrity": "sha512-vOrTqfW7NZLYmB1ZXjEq9JC8Z5knIHVGltN3jfyq9UY+tu7d6jNaSHuDdsVHLaKIRQajTHz+5cphDMoL+6/MUQ==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.7.tgz", + "integrity": "sha512-LL9aMK601BmQjAUDcKWtt5KvAM0xXi0iJpOjoUD3LPfr5dLvBMTflVHQDAEtuZexLQyqpU09+60781PrI/FCTw==", "cpu": [ "x64" ], @@ -161,9 +161,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.2.tgz", - "integrity": "sha512-PCAIxH8TvIy1PlJK2qrdwpRCa7pZV648whRhmoLwj9lvn9PR4+vwuUWhSTXmp1ISHWZm/mEJpYuVq0ZxJDQKZQ==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.7.tgz", + "integrity": "sha512-TmAdM6GVkfir3AUFsDV2gyc25kIbJeAnwT72OnmJGAECHs/t/GLP9IkFLLVcFKsiosRf8BXhVyQ84NYkSWo14w==", "cpu": [ "arm64" ], @@ -177,9 +177,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.2.tgz", - "integrity": "sha512-0rCXZC/9qyWZI2cgVnsT4JEjcxjQcZlrZjaSwhGynPUMkIUUBsWDimzkQeOP8abw5j/kLS2QPQRHAHqd0IF6Rg==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.7.tgz", + "integrity": "sha512-bqWfxwCfLmrfZy69sEU19KHm5TFEaMb8KIekd4aRq/kyOlrjKLdZxN1PyNRP8zpJA1lTiRHzfUDfhpmnZH/skg==", "cpu": [ "ia32" ], @@ -193,9 +193,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.2.tgz", - "integrity": "sha512-HrOwIujKTql8yUOvR+IEGW/SXwMwPrGWrcM35cDfCxpkLH6h3F5i4JtRqYTAiFdSfTk1J2rcFVQXfFJYIDntnA==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.7.tgz", + "integrity": "sha512-OxLHVBNdzyQ//xT3kwjQFnJTn/N5zta/9fofAkXfnL7vqmVn6s/RY1LDa3sxCHlRaKw0n3ShpygRbM9M8+sO9w==", "cpu": [ "x64" ], @@ -1374,90 +1374,90 @@ }, "dependencies": { "@tauri-apps/cli": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.2.tgz", - "integrity": "sha512-x4rPinrdyWLdTU5TbV7wrXudOyMilv0nmi1rngm/jwN3MmZdAj5J2xaS2rYtA8BU3oM/SE34qQwYxv1a2sM9ug==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.7.tgz", + "integrity": "sha512-z7nXLpDAYfQqR5pYhQlWOr88DgPq1AfQyxHhGiakiVgWlaG0ikEfQxop2txrd52H0TRADG0JHR9vFrVFPv4hVQ==", "dev": true, "requires": { - "@tauri-apps/cli-darwin-arm64": "1.5.2", - "@tauri-apps/cli-darwin-x64": "1.5.2", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.2", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.2", - "@tauri-apps/cli-linux-arm64-musl": "1.5.2", - "@tauri-apps/cli-linux-x64-gnu": "1.5.2", - "@tauri-apps/cli-linux-x64-musl": "1.5.2", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.2", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.2", - "@tauri-apps/cli-win32-x64-msvc": "1.5.2" + "@tauri-apps/cli-darwin-arm64": "1.5.7", + "@tauri-apps/cli-darwin-x64": "1.5.7", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.7", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.7", + "@tauri-apps/cli-linux-arm64-musl": "1.5.7", + "@tauri-apps/cli-linux-x64-gnu": "1.5.7", + "@tauri-apps/cli-linux-x64-musl": "1.5.7", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.7", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.7", + "@tauri-apps/cli-win32-x64-msvc": "1.5.7" } }, "@tauri-apps/cli-darwin-arm64": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.2.tgz", - "integrity": "sha512-3mYN15jpYjuuHRWii5Xk6JvB3ZLEgAZkeVgc5Hg7k3Yw1ZBrEGiUNe3Ku4DjbkYWL/QDd7oteIJnQk3j0mXwEg==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.7.tgz", + "integrity": "sha512-eUpOUhs2IOpKaLa6RyGupP2owDLfd0q2FR/AILzryjtBtKJJRDQQvuotf+LcbEce2Nc2AHeYJIqYAsB4sw9K+g==", "dev": true, "optional": true }, "@tauri-apps/cli-darwin-x64": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.2.tgz", - "integrity": "sha512-8Jsl+EKBGdBoRUIR5ohjiTV6uG+pFpkNwHB4WaOzzR//v6p0lGULk2ohPIjJxhoQIFIN9oBd8bsSSNbZO/57/g==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.7.tgz", + "integrity": "sha512-zfumTv1xUuR+RB1pzhRy+51tB6cm8I76g0xUBaXOfEdOJ9FqW5GW2jdnEUbpNuU65qJ1lB8LVWHKGrSWWKazew==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.2.tgz", - "integrity": "sha512-oWzcQtZogchdCSdQ+eEbDJHjJO9BGPO9EZNfvI2u3JzS/hJj4wCwnGHvZGI4jJ/6cnmcNvtt9ZftYYN4rpQW7A==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.7.tgz", + "integrity": "sha512-JngWNqS06bMND9PhiPWp0e+yknJJuSozsSbo+iMzHoJNRauBZCUx+HnUcygUR66Cy6qM4eJvLXtsRG7ApxvWmg==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.2.tgz", - "integrity": "sha512-hfIUtys+SrrGEpLhQJwmL16g1FDhfObR4AGahCMqvMwA25uQKhtzRhxieO4X3k03vBeboTyJla5a2rX4TQ4lXA==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.7.tgz", + "integrity": "sha512-WyIYP9BskgBGq+kf4cLAyru8ArrxGH2eMYGBJvuNEuSaqBhbV0i1uUxvyWdazllZLAEz1WvSocUmSwLknr1+sQ==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.2.tgz", - "integrity": "sha512-ZpFX4HyjkJHfF0geVVpq5fNjEXG8766LRg/BL4/wKy8MNbqcc/aW3sLEpVj0GvdulxOnd2trDb1FJdZ206Kp8g==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.7.tgz", + "integrity": "sha512-OrDpihQP2MB0JY1a/wP9wsl9dDjFDpVEZOQxt4hU+UVGRCZQok7ghPBg4+Xpd1CkNkcCCuIeY8VxRvwLXpnIzg==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.2.tgz", - "integrity": "sha512-/kEZrDVZv1+qYpZigtLntX4s+gx7WQqp8cmxKZL5GrzAjUNSTnfWK5VL7o0lYm09QBJAdTvjcJu2aPzNHLDS+Q==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.7.tgz", + "integrity": "sha512-4T7FAYVk76rZi8VkuLpiKUAqaSxlva86C1fHm/RtmoTKwZEV+MI3vIMoVg+AwhyWIy9PS55C75nF7+OwbnFnvQ==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.2.tgz", - "integrity": "sha512-vOrTqfW7NZLYmB1ZXjEq9JC8Z5knIHVGltN3jfyq9UY+tu7d6jNaSHuDdsVHLaKIRQajTHz+5cphDMoL+6/MUQ==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.7.tgz", + "integrity": "sha512-LL9aMK601BmQjAUDcKWtt5KvAM0xXi0iJpOjoUD3LPfr5dLvBMTflVHQDAEtuZexLQyqpU09+60781PrI/FCTw==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.2.tgz", - "integrity": "sha512-PCAIxH8TvIy1PlJK2qrdwpRCa7pZV648whRhmoLwj9lvn9PR4+vwuUWhSTXmp1ISHWZm/mEJpYuVq0ZxJDQKZQ==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.7.tgz", + "integrity": "sha512-TmAdM6GVkfir3AUFsDV2gyc25kIbJeAnwT72OnmJGAECHs/t/GLP9IkFLLVcFKsiosRf8BXhVyQ84NYkSWo14w==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.2.tgz", - "integrity": "sha512-0rCXZC/9qyWZI2cgVnsT4JEjcxjQcZlrZjaSwhGynPUMkIUUBsWDimzkQeOP8abw5j/kLS2QPQRHAHqd0IF6Rg==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.7.tgz", + "integrity": "sha512-bqWfxwCfLmrfZy69sEU19KHm5TFEaMb8KIekd4aRq/kyOlrjKLdZxN1PyNRP8zpJA1lTiRHzfUDfhpmnZH/skg==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.2.tgz", - "integrity": "sha512-HrOwIujKTql8yUOvR+IEGW/SXwMwPrGWrcM35cDfCxpkLH6h3F5i4JtRqYTAiFdSfTk1J2rcFVQXfFJYIDntnA==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.7.tgz", + "integrity": "sha512-OxLHVBNdzyQ//xT3kwjQFnJTn/N5zta/9fofAkXfnL7vqmVn6s/RY1LDa3sxCHlRaKw0n3ShpygRbM9M8+sO9w==", "dev": true, "optional": true }, diff --git a/package.json b/package.json index 546f9812..9d21dce9 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { - "@tauri-apps/cli": "1.5.2", + "@tauri-apps/cli": "1.5.7", "adm-zip": "0.5.10", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", From 7d65c834e8c70934c731dae875d83a060c34ab44 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 13:19:18 +0000 Subject: [PATCH 210/864] fix(deps): update rust crate once_cell to 1.19.0 --- src-tauri/Cargo.lock | 6 +++--- src-tauri/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 6310ee02..ad7c58f7 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2296,9 +2296,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "open" @@ -2599,7 +2599,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.14" +version = "3.2.15" dependencies = [ "once_cell", "percent-encoding", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4bb283dc..2bdb23bd 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -15,7 +15,7 @@ tauri-build = { version = "1.5.0", features = [] } [dependencies] serde_json = "1.0" -once_cell = "1.18.0" +once_cell = "1.19.0" percent-encoding = "2.3" regex = "1.10.2" serde = { version = "1.0", features = ["derive"] } From 1af653949435571c38050718f6229aec608124e5 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 16 Dec 2023 17:46:09 +0530 Subject: [PATCH 211/864] feat: google analytics feeder in updates.phcode.io --- docs/googleAnalytics/feeder.html | 59 ++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/googleAnalytics/feeder.html diff --git a/docs/googleAnalytics/feeder.html b/docs/googleAnalytics/feeder.html new file mode 100644 index 00000000..38f3af55 --- /dev/null +++ b/docs/googleAnalytics/feeder.html @@ -0,0 +1,59 @@ + + + + + Google Analytics feeder + + + +This page will be loaded in an iframe in tauri desktop builds to enable google analytics integration. +This is because its almost impossible to run google analytics without an http or https url +For more details. + + \ No newline at end of file From 419f22a12611edf39d71bdd2ca30c43766f7440e Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 16 Dec 2023 18:03:51 +0530 Subject: [PATCH 212/864] fix: remove test dev ga tag. this is public info so no secret loss --- docs/googleAnalytics/feeder.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/googleAnalytics/feeder.html b/docs/googleAnalytics/feeder.html index 38f3af55..d0f7290a 100644 --- a/docs/googleAnalytics/feeder.html +++ b/docs/googleAnalytics/feeder.html @@ -13,7 +13,7 @@ // Get the gtag ID from the query string parameter named 'gtagID' const urlParams = new URLSearchParams(window.location.search); - const analyticsID = urlParams.get('analyticsID') || "G-VE5BXWJ0HF"; + const analyticsID = urlParams.get('analyticsID'); if(analyticsID && isAllowedOrigin(location.origin)){ // for google analytics window.dataLayer = window.dataLayer || []; From e4f076878e2aeeb315249a197ffb1d495c182de9 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 16 Dec 2023 18:20:25 +0530 Subject: [PATCH 213/864] fix: google analytics feeder not working --- docs/googleAnalytics/feeder.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/googleAnalytics/feeder.html b/docs/googleAnalytics/feeder.html index d0f7290a..0a528e9a 100644 --- a/docs/googleAnalytics/feeder.html +++ b/docs/googleAnalytics/feeder.html @@ -14,7 +14,7 @@ // Get the gtag ID from the query string parameter named 'gtagID' const urlParams = new URLSearchParams(window.location.search); const analyticsID = urlParams.get('analyticsID'); - if(analyticsID && isAllowedOrigin(location.origin)){ + if(analyticsID){ // for google analytics window.dataLayer = window.dataLayer || []; window.gtag = function(){window.dataLayer.push(arguments);}; From 92aa727a2ebcc275b8635f5f5b5c0676ca0c8527 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 16 Dec 2023 19:14:09 +0530 Subject: [PATCH 214/864] fix: ga not workinf from updates.phcode.io --- docs/googleAnalytics/feeder.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/googleAnalytics/feeder.html b/docs/googleAnalytics/feeder.html index 0a528e9a..fea24f10 100644 --- a/docs/googleAnalytics/feeder.html +++ b/docs/googleAnalytics/feeder.html @@ -27,7 +27,8 @@ gtag('config', analyticsID, { 'page_title': 'Phoenix Analytics Feeder', 'page_path': '/feeder.html', - 'page_location': window.location.origin + 'page_location': window.location.origin, + 'cookie_flags': 'SameSite=None;Secure' }); }; script.src = 'https://www.googletagmanager.com/gtag/js?' + analyticsID; From 2435f5b4b42b225e504af2b9ce984c2d1d60f5ab Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 17 Dec 2023 11:59:08 +0530 Subject: [PATCH 215/864] refacotr: remove analyrtics feeder as it wont work due to third party cookie restrictions --- docs/googleAnalytics/feeder.html | 60 -------------------------------- 1 file changed, 60 deletions(-) delete mode 100644 docs/googleAnalytics/feeder.html diff --git a/docs/googleAnalytics/feeder.html b/docs/googleAnalytics/feeder.html deleted file mode 100644 index fea24f10..00000000 --- a/docs/googleAnalytics/feeder.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - - Google Analytics feeder - - - -This page will be loaded in an iframe in tauri desktop builds to enable google analytics integration. -This is because its almost impossible to run google analytics without an http or https url -For more details. - - \ No newline at end of file From fff4be32e0a62ba5a881d7920652519a55168a67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Dec 2023 18:49:52 +0000 Subject: [PATCH 216/864] fix(deps): update tauri monorepo --- src-tauri/Cargo.lock | 141 ++++++++++++++++++++++++++++++++++++++----- src-tauri/Cargo.toml | 4 +- 2 files changed, 129 insertions(+), 16 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ad7c58f7..7142f926 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -62,6 +62,25 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +[[package]] +name = "arboard" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafb29b107435aa276664c1db8954ac27a6e105cdad3c88287a199eb0e313c08" +dependencies = [ + "clipboard-win", + "core-graphics", + "image", + "log", + "objc", + "objc-foundation", + "objc_id", + "parking_lot", + "thiserror", + "winapi", + "x11rb", +] + [[package]] name = "async-broadcast" version = "0.5.1" @@ -539,6 +558,17 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clipboard-win" +version = "4.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" +dependencies = [ + "error-code", + "str-buf", + "winapi", +] + [[package]] name = "cocoa" version = "0.24.1" @@ -940,6 +970,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "error-code" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" +dependencies = [ + "libc", + "str-buf", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -1293,6 +1333,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "gethostname" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -1729,6 +1779,8 @@ dependencies = [ "color_quant", "num-rational", "num-traits", + "png", + "tiff", ] [[package]] @@ -1843,6 +1895,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jpeg-decoder" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" + [[package]] name = "js-sys" version = "0.3.66" @@ -3429,6 +3487,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "str-buf" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" + [[package]] name = "string_cache" version = "0.8.7" @@ -3620,9 +3684,9 @@ checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" [[package]] name = "tauri" -version = "1.5.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d563b672acde8d0cc4c1b1f5b855976923f67e8d6fe1eba51df0211e197be2" +checksum = "fd27c04b9543776a972c86ccf70660b517ecabbeced9fb58d8b961a13ad129af" dependencies = [ "anyhow", "base64 0.21.5", @@ -3680,9 +3744,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defbfc551bd38ab997e5f8e458f87396d2559d05ce32095076ad6c30f7fc5f9c" +checksum = "e9914a4715e0b75d9f387a285c7e26b5bbfeb1249ad9f842675a82481565c532" dependencies = [ "anyhow", "cargo_toml", @@ -3699,9 +3763,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3475e55acec0b4a50fb96435f19631fb58cbcd31923e1a213de5c382536bbb" +checksum = "a1554c5857f65dbc377cefb6b97c8ac77b1cb2a90d30d3448114d5d6b48a77fc" dependencies = [ "base64 0.21.5", "brotli", @@ -3725,9 +3789,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acea6445eececebd72ed7720cfcca46eee3b5bad8eb408be8f7ef2e3f7411500" +checksum = "277abf361a3a6993ec16bcbb179de0d6518009b851090a01adfea12ac89fa875" dependencies = [ "heck 0.4.1", "proc-macro2", @@ -3765,9 +3829,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07f8e9e53e00e9f41212c115749e87d5cd2a9eebccafca77a19722eeecd56d43" +checksum = "cf2d0652aa2891ff3e9caa2401405257ea29ab8372cce01f186a5825f1bd0e76" dependencies = [ "gtk", "http", @@ -3786,10 +3850,11 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "803a01101bc611ba03e13329951a1bde44287a54234189b9024b78619c1bc206" +checksum = "6cae61fbc731f690a4899681c9052dde6d05b159b44563ace8186fc1bfb7d158" dependencies = [ + "arboard", "cocoa", "gtk", "percent-encoding", @@ -3806,9 +3871,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a52165bb340e6f6a75f1f5eeeab1bb49f861c12abe3a176067d53642b5454986" +checksum = "ece74810b1d3d44f29f732a7ae09a63183d63949bbdd59c61f8ed2a1b70150db" dependencies = [ "brotli", "ctor", @@ -3929,6 +3994,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiff" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "time" version = "0.3.30" @@ -4494,6 +4570,12 @@ dependencies = [ "windows-metadata", ] +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + [[package]] name = "winapi" version = "0.3.9" @@ -4519,6 +4601,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "winapi-wsapoll" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -4982,6 +5073,28 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "x11rb" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" +dependencies = [ + "gethostname", + "nix", + "winapi", + "winapi-wsapoll", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" +dependencies = [ + "nix", +] + [[package]] name = "xattr" version = "1.0.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 2bdb23bd..9f41dfc7 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -11,7 +11,7 @@ rust-version = "1.70" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [build-dependencies] -tauri-build = { version = "1.5.0", features = [] } +tauri-build = { version = "1.5.1", features = [] } [dependencies] serde_json = "1.0" @@ -19,7 +19,7 @@ once_cell = "1.19.0" percent-encoding = "2.3" regex = "1.10.2" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.5.3", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } +tauri = { version = "1.5.4", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From eaa8b29c3177785f9593d266f61141f3a4b45be5 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 Dec 2023 17:33:28 +0530 Subject: [PATCH 217/864] feat: native window webview zoom rust-JS API --- src-tauri/Cargo.lock | 1 + src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 28 +++++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7142f926..7ee9c165 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2668,6 +2668,7 @@ dependencies = [ "tauri-build", "tauri-plugin-fs-extra", "tauri-plugin-window-state", + "webkit2gtk", "winapi", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9f41dfc7..14cd9cb3 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -18,6 +18,7 @@ serde_json = "1.0" once_cell = "1.19.0" percent-encoding = "2.3" regex = "1.10.2" +webkit2gtk = "0.18" # if tauri build fails, make sure to match this version to what we have in tauri serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.4", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index dfbc7ea8..e3dbe4bd 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -9,6 +9,8 @@ use std::fs::metadata; use std::path::PathBuf; use std::process::Command; +#[cfg(target_os = "linux")] +extern crate webkit2gtk; use regex::Regex; extern crate percent_encoding; @@ -105,6 +107,30 @@ fn show_in_folder(path: String) { } } +#[tauri::command] +fn zoom_window(window: tauri::Window, scale_factor: f64) { + let _ = window.with_webview(move |webview| { + #[cfg(target_os = "linux")] + { + // see https://docs.rs/webkit2gtk/0.18.2/webkit2gtk/struct.WebView.html + // and https://docs.rs/webkit2gtk/0.18.2/webkit2gtk/trait.WebViewExt.html + use webkit2gtk::traits::WebViewExt; + webview.inner().set_zoom_level(scale_factor); + } + + #[cfg(windows)] + unsafe { + // see https://docs.rs/webview2-com/0.19.1/webview2_com/Microsoft/Web/WebView2/Win32/struct.ICoreWebView2Controller.html + webview.controller().SetZoomFactor(scale_factor).unwrap(); + } + + #[cfg(target_os = "macos")] + unsafe { + let () = msg_send![webview.inner(), setPageZoom: scale_factor]; + } + }); +} + fn process_window_event(event: &GlobalWindowEvent) { if let tauri::WindowEvent::CloseRequested { .. } = event.event() { // this does nothing and is here if in future you need to persist something on window close. @@ -170,7 +196,7 @@ fn main() { .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ toggle_devtools, console_log, console_error, - _get_windows_drives, _rename_path, show_in_folder]) + _get_windows_drives, _rename_path, show_in_folder, zoom_window]) .setup(|app| { init::init_app(app); Ok(()) From b0d206f8bc4b870aeee8fcbf0b361acf05ea9a1f Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 Dec 2023 17:42:18 +0530 Subject: [PATCH 218/864] fix: webkit2gtk only import in linux cargo.toml --- src-tauri/Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 14cd9cb3..d7edd20b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -18,13 +18,15 @@ serde_json = "1.0" once_cell = "1.19.0" percent-encoding = "2.3" regex = "1.10.2" -webkit2gtk = "0.18" # if tauri build fails, make sure to match this version to what we have in tauri serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.4", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } +[target.'cfg(target_os = "linux")'.dependencies] +webkit2gtk = "0.18" # if tauri build fails, make sure to match this version to what we have in tauri + [features] # by default Tauri runs in production mode # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL From a596666d2fa858b448831d3cd93a850b934ac26d Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 Dec 2023 17:58:32 +0530 Subject: [PATCH 219/864] fix: mac build break due to objc crate not added for webview zoom --- src-tauri/Cargo.lock | 1 + src-tauri/Cargo.toml | 3 +++ src-tauri/src/main.rs | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7ee9c165..f32a42fb 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2659,6 +2659,7 @@ dependencies = [ name = "phoenix-code-ide" version = "3.2.15" dependencies = [ + "objc", "once_cell", "percent-encoding", "regex", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d7edd20b..9be18eff 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -27,6 +27,9 @@ tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-works [target.'cfg(target_os = "linux")'.dependencies] webkit2gtk = "0.18" # if tauri build fails, make sure to match this version to what we have in tauri +[target.'cfg(target_os = "macos")'.dependencies] +objc = "0.2" + [features] # by default Tauri runs in production mode # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index e3dbe4bd..be26d345 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -12,6 +12,10 @@ use std::process::Command; #[cfg(target_os = "linux")] extern crate webkit2gtk; +#[cfg(target_os = "macos")] +#[macro_use] +extern crate objc; + use regex::Regex; extern crate percent_encoding; use tauri::http::ResponseBuilder; From 4bd9bf1d703d1f45afab60073dc7e6b146b6baf4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 27 Dec 2023 01:48:13 +0000 Subject: [PATCH 220/864] chore(deps): update dependency axios to v1.6.3 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index f37d0992..cfa3f185 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.5.7", "adm-zip": "0.5.10", - "axios": "1.6.2", + "axios": "1.6.3", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", @@ -258,9 +258,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", + "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -1499,9 +1499,9 @@ "dev": true }, "axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", + "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", "dev": true, "requires": { "follow-redirects": "^1.15.0", diff --git a/package.json b/package.json index 9d21dce9..6c4c81fc 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.0", - "axios": "1.6.2" + "axios": "1.6.3" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From 0b67f1cf23671ea3d01f85a66fc54fb84a063692 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 28 Dec 2023 07:20:47 +0000 Subject: [PATCH 221/864] chore(deps): update dependency @tauri-apps/cli to v1.5.9 --- package-lock.json | 174 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 88 insertions(+), 88 deletions(-) diff --git a/package-lock.json b/package-lock.json index cfa3f185..8afe8b5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.2.15", "hasInstallScript": true, "devDependencies": { - "@tauri-apps/cli": "1.5.7", + "@tauri-apps/cli": "1.5.9", "adm-zip": "0.5.10", "axios": "1.6.3", "chalk": "^5.3.0", @@ -21,9 +21,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.7.tgz", - "integrity": "sha512-z7nXLpDAYfQqR5pYhQlWOr88DgPq1AfQyxHhGiakiVgWlaG0ikEfQxop2txrd52H0TRADG0JHR9vFrVFPv4hVQ==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.9.tgz", + "integrity": "sha512-knSt/9AvCTeyfC6wkyeouF9hBW/0Mzuw+5vBKEvzaGPQsfFJo1ZCp5FkdiZpGBBfnm09BhugasGRTGofzatfqQ==", "dev": true, "bin": { "tauri": "tauri.js" @@ -36,22 +36,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.5.7", - "@tauri-apps/cli-darwin-x64": "1.5.7", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.7", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.7", - "@tauri-apps/cli-linux-arm64-musl": "1.5.7", - "@tauri-apps/cli-linux-x64-gnu": "1.5.7", - "@tauri-apps/cli-linux-x64-musl": "1.5.7", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.7", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.7", - "@tauri-apps/cli-win32-x64-msvc": "1.5.7" + "@tauri-apps/cli-darwin-arm64": "1.5.9", + "@tauri-apps/cli-darwin-x64": "1.5.9", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.9", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.9", + "@tauri-apps/cli-linux-arm64-musl": "1.5.9", + "@tauri-apps/cli-linux-x64-gnu": "1.5.9", + "@tauri-apps/cli-linux-x64-musl": "1.5.9", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.9", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.9", + "@tauri-apps/cli-win32-x64-msvc": "1.5.9" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.7.tgz", - "integrity": "sha512-eUpOUhs2IOpKaLa6RyGupP2owDLfd0q2FR/AILzryjtBtKJJRDQQvuotf+LcbEce2Nc2AHeYJIqYAsB4sw9K+g==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.9.tgz", + "integrity": "sha512-7C2Jf8f0gzv778mLYb7Eszqqv1bm9Wzews81MRTqKrUIcC+eZEtDXLex+JaEkEzFEUrgIafdOvMBVEavF030IA==", "cpu": [ "arm64" ], @@ -65,9 +65,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.7.tgz", - "integrity": "sha512-zfumTv1xUuR+RB1pzhRy+51tB6cm8I76g0xUBaXOfEdOJ9FqW5GW2jdnEUbpNuU65qJ1lB8LVWHKGrSWWKazew==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.9.tgz", + "integrity": "sha512-LHKytpkofPYgH8RShWvwDa3hD1ws131x7g7zNasJPfOiCWLqYVQFUuQVmjEUt8+dpHe/P/err5h4z+YZru2d0A==", "cpu": [ "x64" ], @@ -81,9 +81,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.7.tgz", - "integrity": "sha512-JngWNqS06bMND9PhiPWp0e+yknJJuSozsSbo+iMzHoJNRauBZCUx+HnUcygUR66Cy6qM4eJvLXtsRG7ApxvWmg==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.9.tgz", + "integrity": "sha512-teGK20IYKx+dVn8wFq/Lg57Q9ce7foq1KHSfyHi464LVt1T0V1rsmULSgZpQPPj/NYPF5BG78PcWYv64yH86jw==", "cpu": [ "arm" ], @@ -97,9 +97,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.7.tgz", - "integrity": "sha512-WyIYP9BskgBGq+kf4cLAyru8ArrxGH2eMYGBJvuNEuSaqBhbV0i1uUxvyWdazllZLAEz1WvSocUmSwLknr1+sQ==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.9.tgz", + "integrity": "sha512-onJ/DW5Crw38qVx+wquY4uBbfCxVhzhdJmlCYqnYyXsZZmSiPUfSyhV58y+5TYB0q1hG8eYdB5x8VAwzByhGzw==", "cpu": [ "arm64" ], @@ -113,9 +113,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.7.tgz", - "integrity": "sha512-OrDpihQP2MB0JY1a/wP9wsl9dDjFDpVEZOQxt4hU+UVGRCZQok7ghPBg4+Xpd1CkNkcCCuIeY8VxRvwLXpnIzg==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.9.tgz", + "integrity": "sha512-23AYoLD3acakLp9NtheKQDJl8F66eTOflxoPzdJNRy13hUSxb+W9qpz4rRA+CIzkjICFvO2i3UWjeV9QwDVpsQ==", "cpu": [ "arm64" ], @@ -129,9 +129,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.7.tgz", - "integrity": "sha512-4T7FAYVk76rZi8VkuLpiKUAqaSxlva86C1fHm/RtmoTKwZEV+MI3vIMoVg+AwhyWIy9PS55C75nF7+OwbnFnvQ==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.9.tgz", + "integrity": "sha512-9PQA1rE7gh41W2ylyKd5qOGOds55ymaYPml9KOpM0g+cxmCXa+8Wf9K5NKvACnJldJJ6cekWzIyB4eN6o5T+yQ==", "cpu": [ "x64" ], @@ -145,9 +145,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.7.tgz", - "integrity": "sha512-LL9aMK601BmQjAUDcKWtt5KvAM0xXi0iJpOjoUD3LPfr5dLvBMTflVHQDAEtuZexLQyqpU09+60781PrI/FCTw==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.9.tgz", + "integrity": "sha512-5hdbNFeDsrJ/pXZ4cSQV4bJwUXPPxXxN3/pAtNUqIph7q+vLcBXOXIMoS64iuyaluJC59lhEwlWZFz+EPv0Hqg==", "cpu": [ "x64" ], @@ -161,9 +161,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.7.tgz", - "integrity": "sha512-TmAdM6GVkfir3AUFsDV2gyc25kIbJeAnwT72OnmJGAECHs/t/GLP9IkFLLVcFKsiosRf8BXhVyQ84NYkSWo14w==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.9.tgz", + "integrity": "sha512-O18JufjSB3hSJYu5WWByONouGeX7DraLAtXLErsG1r/VS3zHd/zyuzycrVUaObNXk5bfGlIP0Ypt+RvZJILN2w==", "cpu": [ "arm64" ], @@ -177,9 +177,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.7.tgz", - "integrity": "sha512-bqWfxwCfLmrfZy69sEU19KHm5TFEaMb8KIekd4aRq/kyOlrjKLdZxN1PyNRP8zpJA1lTiRHzfUDfhpmnZH/skg==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.9.tgz", + "integrity": "sha512-FQxtxTZu0JVBihfd/lmpxo7jyMOesjWQehfyVUqtgMfm5+Pvvw0Y+ZioeDi1TZkFVrT3QDYy8R4LqDLSZVMQRA==", "cpu": [ "ia32" ], @@ -193,9 +193,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.7.tgz", - "integrity": "sha512-OxLHVBNdzyQ//xT3kwjQFnJTn/N5zta/9fofAkXfnL7vqmVn6s/RY1LDa3sxCHlRaKw0n3ShpygRbM9M8+sO9w==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.9.tgz", + "integrity": "sha512-EeI1+L518cIBLKw0qUFwnLIySBeSmPQjPLIlNwSukHSro4tAQPHycEVGgKrdToiCWgaZJBA0e5aRSds0Du2TWg==", "cpu": [ "x64" ], @@ -1374,90 +1374,90 @@ }, "dependencies": { "@tauri-apps/cli": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.7.tgz", - "integrity": "sha512-z7nXLpDAYfQqR5pYhQlWOr88DgPq1AfQyxHhGiakiVgWlaG0ikEfQxop2txrd52H0TRADG0JHR9vFrVFPv4hVQ==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.9.tgz", + "integrity": "sha512-knSt/9AvCTeyfC6wkyeouF9hBW/0Mzuw+5vBKEvzaGPQsfFJo1ZCp5FkdiZpGBBfnm09BhugasGRTGofzatfqQ==", "dev": true, "requires": { - "@tauri-apps/cli-darwin-arm64": "1.5.7", - "@tauri-apps/cli-darwin-x64": "1.5.7", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.7", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.7", - "@tauri-apps/cli-linux-arm64-musl": "1.5.7", - "@tauri-apps/cli-linux-x64-gnu": "1.5.7", - "@tauri-apps/cli-linux-x64-musl": "1.5.7", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.7", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.7", - "@tauri-apps/cli-win32-x64-msvc": "1.5.7" + "@tauri-apps/cli-darwin-arm64": "1.5.9", + "@tauri-apps/cli-darwin-x64": "1.5.9", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.9", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.9", + "@tauri-apps/cli-linux-arm64-musl": "1.5.9", + "@tauri-apps/cli-linux-x64-gnu": "1.5.9", + "@tauri-apps/cli-linux-x64-musl": "1.5.9", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.9", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.9", + "@tauri-apps/cli-win32-x64-msvc": "1.5.9" } }, "@tauri-apps/cli-darwin-arm64": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.7.tgz", - "integrity": "sha512-eUpOUhs2IOpKaLa6RyGupP2owDLfd0q2FR/AILzryjtBtKJJRDQQvuotf+LcbEce2Nc2AHeYJIqYAsB4sw9K+g==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.9.tgz", + "integrity": "sha512-7C2Jf8f0gzv778mLYb7Eszqqv1bm9Wzews81MRTqKrUIcC+eZEtDXLex+JaEkEzFEUrgIafdOvMBVEavF030IA==", "dev": true, "optional": true }, "@tauri-apps/cli-darwin-x64": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.7.tgz", - "integrity": "sha512-zfumTv1xUuR+RB1pzhRy+51tB6cm8I76g0xUBaXOfEdOJ9FqW5GW2jdnEUbpNuU65qJ1lB8LVWHKGrSWWKazew==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.9.tgz", + "integrity": "sha512-LHKytpkofPYgH8RShWvwDa3hD1ws131x7g7zNasJPfOiCWLqYVQFUuQVmjEUt8+dpHe/P/err5h4z+YZru2d0A==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.7.tgz", - "integrity": "sha512-JngWNqS06bMND9PhiPWp0e+yknJJuSozsSbo+iMzHoJNRauBZCUx+HnUcygUR66Cy6qM4eJvLXtsRG7ApxvWmg==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.9.tgz", + "integrity": "sha512-teGK20IYKx+dVn8wFq/Lg57Q9ce7foq1KHSfyHi464LVt1T0V1rsmULSgZpQPPj/NYPF5BG78PcWYv64yH86jw==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.7.tgz", - "integrity": "sha512-WyIYP9BskgBGq+kf4cLAyru8ArrxGH2eMYGBJvuNEuSaqBhbV0i1uUxvyWdazllZLAEz1WvSocUmSwLknr1+sQ==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.9.tgz", + "integrity": "sha512-onJ/DW5Crw38qVx+wquY4uBbfCxVhzhdJmlCYqnYyXsZZmSiPUfSyhV58y+5TYB0q1hG8eYdB5x8VAwzByhGzw==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.7.tgz", - "integrity": "sha512-OrDpihQP2MB0JY1a/wP9wsl9dDjFDpVEZOQxt4hU+UVGRCZQok7ghPBg4+Xpd1CkNkcCCuIeY8VxRvwLXpnIzg==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.9.tgz", + "integrity": "sha512-23AYoLD3acakLp9NtheKQDJl8F66eTOflxoPzdJNRy13hUSxb+W9qpz4rRA+CIzkjICFvO2i3UWjeV9QwDVpsQ==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.7.tgz", - "integrity": "sha512-4T7FAYVk76rZi8VkuLpiKUAqaSxlva86C1fHm/RtmoTKwZEV+MI3vIMoVg+AwhyWIy9PS55C75nF7+OwbnFnvQ==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.9.tgz", + "integrity": "sha512-9PQA1rE7gh41W2ylyKd5qOGOds55ymaYPml9KOpM0g+cxmCXa+8Wf9K5NKvACnJldJJ6cekWzIyB4eN6o5T+yQ==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.7.tgz", - "integrity": "sha512-LL9aMK601BmQjAUDcKWtt5KvAM0xXi0iJpOjoUD3LPfr5dLvBMTflVHQDAEtuZexLQyqpU09+60781PrI/FCTw==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.9.tgz", + "integrity": "sha512-5hdbNFeDsrJ/pXZ4cSQV4bJwUXPPxXxN3/pAtNUqIph7q+vLcBXOXIMoS64iuyaluJC59lhEwlWZFz+EPv0Hqg==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.7.tgz", - "integrity": "sha512-TmAdM6GVkfir3AUFsDV2gyc25kIbJeAnwT72OnmJGAECHs/t/GLP9IkFLLVcFKsiosRf8BXhVyQ84NYkSWo14w==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.9.tgz", + "integrity": "sha512-O18JufjSB3hSJYu5WWByONouGeX7DraLAtXLErsG1r/VS3zHd/zyuzycrVUaObNXk5bfGlIP0Ypt+RvZJILN2w==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.7.tgz", - "integrity": "sha512-bqWfxwCfLmrfZy69sEU19KHm5TFEaMb8KIekd4aRq/kyOlrjKLdZxN1PyNRP8zpJA1lTiRHzfUDfhpmnZH/skg==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.9.tgz", + "integrity": "sha512-FQxtxTZu0JVBihfd/lmpxo7jyMOesjWQehfyVUqtgMfm5+Pvvw0Y+ZioeDi1TZkFVrT3QDYy8R4LqDLSZVMQRA==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.7", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.7.tgz", - "integrity": "sha512-OxLHVBNdzyQ//xT3kwjQFnJTn/N5zta/9fofAkXfnL7vqmVn6s/RY1LDa3sxCHlRaKw0n3ShpygRbM9M8+sO9w==", + "version": "1.5.9", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.9.tgz", + "integrity": "sha512-EeI1+L518cIBLKw0qUFwnLIySBeSmPQjPLIlNwSukHSro4tAQPHycEVGgKrdToiCWgaZJBA0e5aRSds0Du2TWg==", "dev": true, "optional": true }, diff --git a/package.json b/package.json index 6c4c81fc..8067af1b 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { - "@tauri-apps/cli": "1.5.7", + "@tauri-apps/cli": "1.5.9", "adm-zip": "0.5.10", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", From e6cab28c42c02af5f379de08c1cbfb06c3ae1c69 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 5 Jan 2024 22:31:02 +0000 Subject: [PATCH 222/864] chore(deps): update dependency axios to v1.6.5 --- package-lock.json | 30 +++++++++++++++--------------- package.json | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8afe8b5f..615cfefa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.5.9", "adm-zip": "0.5.10", - "axios": "1.6.3", + "axios": "1.6.5", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", @@ -258,12 +258,12 @@ "dev": true }, "node_modules/axios": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", - "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -510,9 +510,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", "dev": true, "funding": [ { @@ -1499,12 +1499,12 @@ "dev": true }, "axios": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.3.tgz", - "integrity": "sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", "dev": true, "requires": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -1692,9 +1692,9 @@ } }, "follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.4", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", + "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", "dev": true }, "form-data": { diff --git a/package.json b/package.json index 8067af1b..63648df6 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.0", - "axios": "1.6.3" + "axios": "1.6.5" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From a9b54aaddce759dd6f4ede3a9a82edda689c7021 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 7 Jan 2024 09:37:19 +0530 Subject: [PATCH 223/864] fix: f10 keydown events not working in linux --- src-tauri/Cargo.lock | 1 + src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 13 +++++++++++++ 3 files changed, 15 insertions(+) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f32a42fb..ed2512b2 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2659,6 +2659,7 @@ dependencies = [ name = "phoenix-code-ide" version = "3.2.15" dependencies = [ + "gtk", "objc", "once_cell", "percent-encoding", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9be18eff..adaef063 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -25,6 +25,7 @@ tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } [target.'cfg(target_os = "linux")'.dependencies] +gtk = "0.15" webkit2gtk = "0.18" # if tauri build fails, make sure to match this version to what we have in tauri [target.'cfg(target_os = "macos")'.dependencies] diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index be26d345..92160deb 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -7,6 +7,8 @@ windows_subsystem = "windows" use std::fs::metadata; #[cfg(target_os = "linux")] use std::path::PathBuf; +#[cfg(target_os = "linux")] +use gtk::{glib::ObjectExt, prelude::WidgetExt}; use std::process::Command; #[cfg(target_os = "linux")] @@ -16,6 +18,7 @@ extern crate webkit2gtk; #[macro_use] extern crate objc; +use tauri::Manager; use regex::Regex; extern crate percent_encoding; use tauri::http::ResponseBuilder; @@ -203,6 +206,16 @@ fn main() { _get_windows_drives, _rename_path, show_in_folder, zoom_window]) .setup(|app| { init::init_app(app); + #[cfg(target_os = "linux")] + { + // In linux, f10 key press events are reserved for gtk-menu-bar-accel and not passed. + // So we assing f25 key to it to free f10 and make it available to app + // https://discord.com/channels/616186924390023171/1192844593557950474 + let win = app.get_window("main").unwrap(); + let gtk_win = win.gtk_window().unwrap(); + let gtk_settings = gtk_win.settings().unwrap(); + gtk_settings.set_property("gtk-menu-bar-accel", "F25"); + } Ok(()) }) .run(tauri::generate_context!()) From 84cbbf1a51d6783a47f0ccd6fb014f08c055f16f Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 7 Jan 2024 09:44:38 +0530 Subject: [PATCH 224/864] fix: unused import warning in mac and win --- src-tauri/src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 92160deb..5ad0bd76 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,6 +3,9 @@ all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows" )] +#[cfg(target_os = "linux")] +use tauri::Manager; // needed for the f10 key fix for now in linux only + #[cfg(target_os = "linux")] use std::fs::metadata; #[cfg(target_os = "linux")] @@ -18,7 +21,6 @@ extern crate webkit2gtk; #[macro_use] extern crate objc; -use tauri::Manager; use regex::Regex; extern crate percent_encoding; use tauri::http::ResponseBuilder; From bce464d972cb49c87335f634225fe59655979de5 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 11 Jan 2024 16:44:45 +0000 Subject: [PATCH 225/864] ci: update phcode version to 3.2.17 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 63648df6..13b17ebc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.15", + "version": "3.2.17", "type": "module", "scripts": { "tauri": "tauri", @@ -49,6 +49,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "56b0eba5b65d1d73faee3113eae7b368cec911d3" + "commit": "ac800eefead572f1a745bdf3b67162d68a71506f" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index adaef063..ba09efe5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.15" +version = "3.2.17" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 215fbdad..5c0b3fc0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.15" + "version": "3.2.17" }, "tauri": { "allowlist": { From 3b257a44f0aabd9cdff4b67412c8a351294c09e5 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 11 Jan 2024 22:27:27 +0530 Subject: [PATCH 226/864] ci: enable live preview integration tests in pipeline --- .github/workflows/desktop-linux-test-pull.yml | 7 +++++ .github/workflows/desktop-mac-test-pull.yml | 7 +++++ .../workflows/desktop-windows-test-pull.yml | 16 +++++++++- .../prod-desktop-mac-m1-tests-on-pull.yml | 7 +++++ .../workflows/prod-desktop-tests-on-pull.yml | 30 ++++++++++++++++++- .../staging-desktop-tests-on-pull.yml | 16 +++++++++- 6 files changed, 80 insertions(+), 3 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index dc4d9816..bf05e28f 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -65,6 +65,13 @@ jobs: max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + - name: Run tauri livepreview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q + - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v2 with: diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 94d04600..8034c01c 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -58,6 +58,13 @@ jobs: max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + - name: Run tauri livepreview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q + - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v2 with: diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index 748b0bde..614c724d 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -80,6 +80,20 @@ jobs: run: type output-mainview.txt shell: cmd + - name: Run tauri livepreview tests in windows + uses: nick-fields/retry@v2 + id: windowsRunLivepreview + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=livepreview -q > output-livepreview.txt 2>&1 + shell: cmd + + - name: Print windows livepreview test output to console + run: type output-livepreview.txt + shell: cmd + - name: Run tauri LegacyInteg tests in windows uses: nick-fields/retry@v2 id: windowsRunLegacyInteg @@ -95,7 +109,7 @@ jobs: shell: cmd - name: Fail on test runs failed in windows - if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' + if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLivepreview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' run: | echo "Windows tests failed, marking step as failed" exit 1 diff --git a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml index 59e8e156..d94e890f 100644 --- a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml @@ -60,6 +60,13 @@ jobs: max_attempts: 2 command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + - name: Run tauri livepreview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 10 + max_attempts: 2 + command: ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q + - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v2 with: diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index 3a87be2d..3bf21e38 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -63,6 +63,13 @@ jobs: max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + - name: Run tauri livepreview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q + - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v2 with: @@ -120,6 +127,13 @@ jobs: max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + - name: Run tauri livepreview tests + uses: nick-fields/retry@v2 + with: + timeout_minutes: 12 + max_attempts: 3 + command: ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q + - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v2 with: @@ -199,6 +213,20 @@ jobs: run: type output-mainview.txt shell: cmd + - name: Run tauri livepreview tests in windows + uses: nick-fields/retry@v2 + id: windowsRunLivepreview + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=livepreview -q > output-livepreview.txt 2>&1 + shell: cmd + + - name: Print windows livepreview test output to console + run: type output-livepreview.txt + shell: cmd + - name: Run tauri LegacyInteg tests in windows uses: nick-fields/retry@v2 id: windowsRunLegacyInteg @@ -214,7 +242,7 @@ jobs: shell: cmd - name: Fail on test runs failed in windows - if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' + if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLivepreview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' run: | echo "Windows tests failed, marking step as failed" exit 1 diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index 854aa3d0..7c52431c 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -199,6 +199,20 @@ jobs: run: type output-mainview.txt shell: cmd + - name: Run tauri livepreview tests in windows + uses: nick-fields/retry@v2 + id: windowsRunLivepreview + continue-on-error: true + with: + timeout_minutes: 12 + max_attempts: 3 + command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=livepreview -q > output-livepreview.txt 2>&1 + shell: cmd + + - name: Print windows livepreview test output to console + run: type output-livepreview.txt + shell: cmd + - name: Run tauri LegacyInteg tests in windows uses: nick-fields/retry@v2 id: windowsRunLegacyInteg @@ -214,7 +228,7 @@ jobs: shell: cmd - name: Fail on test runs failed in windows - if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' + if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLivepreview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' run: | echo "Windows tests failed, marking step as failed" exit 1 From a6dead4f9489afa0d1a622e67ddd704b7b635517 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 12 Jan 2024 12:05:25 +0530 Subject: [PATCH 227/864] chore: update deps --- package-lock.json | 4 ++-- src-tauri/Cargo.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 615cfefa..dec2a090 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.2.15", + "version": "3.2.17", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.15", + "version": "3.2.17", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.9", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ed2512b2..9c9531f6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2657,7 +2657,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.15" +version = "3.2.17" dependencies = [ "gtk", "objc", From 0d819277b354dd9f9606bdaed56ef09723489fb3 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 12 Jan 2024 16:24:24 +0530 Subject: [PATCH 228/864] fix: mac notarization fail --- src-build/mac/filesToSign | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src-build/mac/filesToSign b/src-build/mac/filesToSign index 7b2190ff..d14718ee 100644 --- a/src-build/mac/filesToSign +++ b/src-build/mac/filesToSign @@ -1 +1,6 @@ src-tauri/src-node/node_modules/fsevents/fsevents.node +src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.napi.node +src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.abi108.node +src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.abi115.node +src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/node.abi108.glibc.node +src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/node.napi.glibc.node From b594e564468edc79f90e713574fee263bd755cd5 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 12 Jan 2024 16:40:07 +0530 Subject: [PATCH 229/864] fix: GUI apps on macOS and Linux do not inherit the PATH from your shell dotfiles --- src-tauri/Cargo.lock | 45 +++++++++++++++++++++++++++++++++++++++++++ src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 4 ++++ 3 files changed, 50 insertions(+) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9c9531f6..f0156e91 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1064,6 +1064,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "fix-path-env" +version = "0.0.0" +source = "git+https://github.com/tauri-apps/fix-path-env-rs#8481725b7ebfc56cdb052d522517421242eac36b" +dependencies = [ + "strip-ansi-escapes", + "thiserror", +] + [[package]] name = "flate2" version = "1.0.28" @@ -2659,6 +2668,7 @@ dependencies = [ name = "phoenix-code-ide" version = "3.2.17" dependencies = [ + "fix-path-env", "gtk", "objc", "once_cell", @@ -3522,6 +3532,15 @@ dependencies = [ "quote", ] +[[package]] +name = "strip-ansi-escapes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.10.0" @@ -4303,6 +4322,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "uuid" version = "1.6.1" @@ -4362,6 +4387,26 @@ dependencies = [ "libc", ] +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "waker-fn" version = "1.1.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ba09efe5..4c72aa25 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -23,6 +23,7 @@ tauri = { version = "1.5.4", features = [ "cli", "api-all", "updater", "devtools winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } +fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } [target.'cfg(target_os = "linux")'.dependencies] gtk = "0.15" diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 5ad0bd76..f624e991 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -154,6 +154,10 @@ fn remove_version_from_url(url: &str) -> String { } fn main() { + // GUI apps on macOS and Linux do not inherit the $PATH from your shell dotfiles (.bashrc, .bash_profile, .zshrc, etc). + // fix that https://github.com/tauri-apps/fix-path-env-rs + let _ = fix_path_env::fix(); + tauri::Builder::default() .register_uri_scheme_protocol("phtauri", move |app, request| { // can't use `tauri` because that's already in use let path = remove_version_from_url(request.uri()); From 9f4dfcd45168229eea84f7f58166a5a972b79aa5 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 15 Jan 2024 11:45:32 +0530 Subject: [PATCH 230/864] fix: appimage bundle fails due to incompatible binaries in linux --- .github/workflows/tauri-build-dev.yml | 6 +++++- .github/workflows/tauri-build-prod.yml | 4 ++++ .github/workflows/tauri-build-staging.yml | 4 ++++ package.json | 3 ++- src-build/mac/filesToSign | 5 +++++ 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index cad37742..98b0d930 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -146,10 +146,14 @@ jobs: # Sign the files specified in src-build/mac/filesToSign while IFS= read -r file; do + if [ -f "$file" ]; then codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" + else + echo "File to sign not found, ignoring: $file" + fi done < src-build/mac/filesToSign - # Clean up + # Clean up security delete-keychain build.keychain rm -rf "$tmp_dir" # removes the temporary directory and the certificate file within it diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 446a4d56..632b1590 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -152,7 +152,11 @@ jobs: # Sign the files specified in src-build/mac/filesToSign while IFS= read -r file; do + if [ -f "$file" ]; then codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" + else + echo "File to sign not found, ignoring: $file" + fi done < src-build/mac/filesToSign # Clean up diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 3753af40..cf39de05 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -146,7 +146,11 @@ jobs: # Sign the files specified in src-build/mac/filesToSign while IFS= read -r file; do + if [ -f "$file" ]; then codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" + else + echo "File to sign not found, ignoring: $file" + fi done < src-build/mac/filesToSign # Clean up diff --git a/package.json b/package.json index 13b17ebc..c6392c52 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "releaseDistDebug": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", - "_src-node_npm_install": "cd src-tauri/src-node && npm ci --production && cd ../../", + "_src-node_npm_install": "cd src-tauri/src-node && npm ci --production && cd ../../ && npm run _src-node_remove_unsupported_bin", + "_src-node_remove_unsupported_bin": "shx rm -f src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-linux-*/*.musl.node src-tauri/src-node/node_modules/@lmdb/lmdb-linux-*/*.musl.node", "_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r ../phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", "_make_src-node_debug_dev": "npm run _make_src-node && shx rm -rf src-tauri/target/debug/src-node && shx cp -r src-tauri/src-node src-tauri/target/debug/src-node", "_ci_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", diff --git a/src-build/mac/filesToSign b/src-build/mac/filesToSign index d14718ee..88eeaf46 100644 --- a/src-build/mac/filesToSign +++ b/src-build/mac/filesToSign @@ -1,6 +1,11 @@ src-tauri/src-node/node_modules/fsevents/fsevents.node src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.napi.node +src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.napi.node src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.abi108.node +src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.abi108.node src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.abi115.node +src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.abi115.node src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/node.abi108.glibc.node +src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.abi108.glibc.node src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/node.napi.glibc.node +src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.napi.glibc.node From 575ff37b995ecc83756099629138d23226e69e1b Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 15 Jan 2024 12:01:34 +0530 Subject: [PATCH 231/864] refactor: indentaion --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 98b0d930..a8b4fa22 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -153,7 +153,7 @@ jobs: fi done < src-build/mac/filesToSign - # Clean up + # Clean up security delete-keychain build.keychain rm -rf "$tmp_dir" # removes the temporary directory and the certificate file within it From f66626104cb9d61e084dd8137bcd1cdf4dc6eed3 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 15 Jan 2024 17:55:48 +0530 Subject: [PATCH 232/864] build: add media codecs in linux --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 5c0b3fc0..4a33644e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -106,7 +106,7 @@ "depends": [] }, "appimage": { - "bundleMediaFramework": false + "bundleMediaFramework": true }, "externalBin": [ "phnode" From 3d222294a221fe6bb21dc2c19fd5b9c0bef52798 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 15 Jan 2024 20:23:32 +0530 Subject: [PATCH 233/864] fix: adding entitlements.plist to fix side car not working in mac Ventura --- entitlements.plist | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/entitlements.plist b/entitlements.plist index 5516ebf3..045df8ea 100644 --- a/entitlements.plist +++ b/entitlements.plist @@ -2,5 +2,17 @@ + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.disable-executable-page-protection + + com.apple.security.cs.allow-dyld-environment-variables + + com.apple.security.cs.disable-library-validation + + com.apple.security.get-task-allow + - \ No newline at end of file + From 834ead09c00fe0634e9ff3c0c6217122ae73d8f6 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Tue, 16 Jan 2024 09:37:20 +0000 Subject: [PATCH 234/864] ci: update phcode version to 3.2.18 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index c6392c52..4955d5f4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.17", + "version": "3.2.18", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "ac800eefead572f1a745bdf3b67162d68a71506f" + "commit": "b4e9306238b73cbb142dbbe08d7c23c4536af8cb" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4c72aa25..ccb50122 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.17" +version = "3.2.18" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4a33644e..368deab8 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.17" + "version": "3.2.18" }, "tauri": { "allowlist": { From 28d37802ac335239d201fc1fa20b87081a096952 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 16 Jan 2024 16:44:36 +0530 Subject: [PATCH 235/864] fix: prod release name is always phoenix code --- src-build/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-build/constants.js b/src-build/constants.js index 46dc67f1..d352f0eb 100644 --- a/src-build/constants.js +++ b/src-build/constants.js @@ -3,7 +3,7 @@ export const PRODUCT_NAME_SUFFIX_FOR_STAGE = { // and brackets.config.staging.json. The product name suffix corresponding to each stage are values. dev : "Experimental Build", stage: "Pre-release", - production: "Beta" // Change to empty if we are out of beta/alpha/rc . Prod has no suffix + production: "" // Prod has no suffix. !!!DO NOT use any beta/alpha/rc etc here in name as it will nuke update!!! }; export const BUNDLE_IDENTIFIER_FOR_STAGE = { From 292af46f23891c7b5060872e774965fa4905671b Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 17 Jan 2024 17:40:40 +0530 Subject: [PATCH 236/864] feat: add support for getting copied files from clipboard --- src-tauri/Cargo.lock | 23 ++++++++++++++++++++++- src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 16 +++++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f0156e91..9f886035 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -558,6 +558,20 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "clipboard-files" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc2120eaf094b70a9c58bd1f8bb908cb74fbfe0c9793314567f7f8cea0be383" +dependencies = [ + "clipboard-win", + "gtk", + "objc", + "objc-foundation", + "objc_id", + "urlencoding", +] + [[package]] name = "clipboard-win" version = "4.5.0" @@ -2666,8 +2680,9 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.17" +version = "3.2.18" dependencies = [ + "clipboard-files", "fix-path-env", "gtk", "objc", @@ -4316,6 +4331,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf-8" version = "0.7.6" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ccb50122..9e2d0dc0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -18,6 +18,7 @@ serde_json = "1.0" once_cell = "1.19.0" percent-encoding = "2.3" regex = "1.10.2" +clipboard-files = "0.1.1" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.4", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index f624e991..61aa133a 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -21,6 +21,8 @@ extern crate webkit2gtk; #[macro_use] extern crate objc; +use clipboard_files; + use regex::Regex; extern crate percent_encoding; use tauri::http::ResponseBuilder; @@ -52,6 +54,18 @@ fn _rename_path(old_path: &str, new_path: &str) -> Result<(), String> { platform::rename_path(old_path, new_path) } +#[tauri::command] +fn _get_clipboard_files() -> Option> { + match clipboard_files::read() { + Ok(paths) => Some( + paths.into_iter() + .map(|path| path.to_string_lossy().into_owned()) + .collect() + ), + Err(_) => None, + } +} + static mut DEVTOOLS_LOADED:bool = false; #[tauri::command] @@ -209,7 +223,7 @@ fn main() { .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ toggle_devtools, console_log, console_error, - _get_windows_drives, _rename_path, show_in_folder, zoom_window]) + _get_windows_drives, _rename_path, show_in_folder, zoom_window, _get_clipboard_files]) .setup(|app| { init::init_app(app); #[cfg(target_os = "linux")] From 0c7ea1bae256b2dc36466188bacae68a04f3068d Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 17 Jan 2024 22:04:37 +0530 Subject: [PATCH 237/864] fix: disable tauri file drop as it disables browser drag-drop --- src-tauri/tauri.conf.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 368deab8..2c3a592a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -326,7 +326,8 @@ "title": "Phoenix Code Experimental Build", "width": 1366, "minWidth": 800, - "acceptFirstMouse": true + "acceptFirstMouse": true, + "fileDropEnabled": false } ] } From ce9b78c6cca969f342484002dc238c63ae5023a6 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 18 Jan 2024 11:10:57 +0530 Subject: [PATCH 238/864] feat: add _get_commandline_args tauri api --- src-tauri/src/main.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 61aa133a..a729d84f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -2,7 +2,7 @@ all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows" )] - +use std::env; #[cfg(target_os = "linux")] use tauri::Manager; // needed for the f10 key fix for now in linux only @@ -49,6 +49,12 @@ fn _get_windows_drives() -> Option> { platform::get_windows_drives() } +#[tauri::command] +fn _get_commandline_args() -> Option> { + Some(env::args().collect()) +} + + #[tauri::command] fn _rename_path(old_path: &str, new_path: &str) -> Result<(), String> { platform::rename_path(old_path, new_path) @@ -222,7 +228,7 @@ fn main() { .plugin(tauri_plugin_window_state::Builder::default().build()) .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ - toggle_devtools, console_log, console_error, + toggle_devtools, console_log, console_error, _get_commandline_args, _get_windows_drives, _rename_path, show_in_folder, zoom_window, _get_clipboard_files]) .setup(|app| { init::init_app(app); From ef3a69442341999cc6d3d1184a93572ebabcbbb6 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 17 Jan 2024 15:51:17 +0530 Subject: [PATCH 239/864] fix: reg cleanup not working in windows --- .../src/bundle/windows/nsis/installer.nsi | 741 ++++++++++++++++++ src-tauri/tauri.conf.json | 3 +- 2 files changed, 743 insertions(+), 1 deletion(-) create mode 100644 src-tauri/src/bundle/windows/nsis/installer.nsi diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi new file mode 100644 index 00000000..6e910b3b --- /dev/null +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -0,0 +1,741 @@ +Unicode true +; Set the compression algorithm. Default is LZMA. +!if "{{compression}}" == "" + SetCompressor /SOLID lzma +!else + SetCompressor /SOLID "{{compression}}" +!endif + +!include MUI2.nsh +!include FileFunc.nsh +!include x64.nsh +!include WordFunc.nsh +!include "StrFunc.nsh" +${StrCase} +${StrLoc} + +!define MANUFACTURER "{{manufacturer}}" +!define PRODUCTNAME "{{product_name}}" +!define VERSION "{{version}}" +!define VERSIONWITHBUILD "{{version_with_build}}" +!define SHORTDESCRIPTION "{{short_description}}" +!define INSTALLMODE "{{install_mode}}" +!define LICENSE "{{license}}" +!define INSTALLERICON "{{installer_icon}}" +!define SIDEBARIMAGE "{{sidebar_image}}" +!define HEADERIMAGE "{{header_image}}" +!define MAINBINARYNAME "{{main_binary_name}}" +!define MAINBINARYSRCPATH "{{main_binary_path}}" +!define BUNDLEID "{{bundle_id}}" +!define COPYRIGHT "{{copyright}}" +!define OUTFILE "{{out_file}}" +!define ARCH "{{arch}}" +!define PLUGINSPATH "{{additional_plugins_path}}" +!define ALLOWDOWNGRADES "{{allow_downgrades}}" +!define DISPLAYLANGUAGESELECTOR "{{display_language_selector}}" +!define INSTALLWEBVIEW2MODE "{{install_webview2_mode}}" +!define WEBVIEW2INSTALLERARGS "{{webview2_installer_args}}" +!define WEBVIEW2BOOTSTRAPPERPATH "{{webview2_bootstrapper_path}}" +!define WEBVIEW2INSTALLERPATH "{{webview2_installer_path}}" +!define UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}" +!define MANUPRODUCTKEY "Software\${MANUFACTURER}\${PRODUCTNAME}" +!define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}" +!define ESTIMATEDSIZE "{{estimated_size}}" + +Name "${PRODUCTNAME}" +BrandingText "${COPYRIGHT}" +OutFile "${OUTFILE}" + +VIProductVersion "${VERSIONWITHBUILD}" +VIAddVersionKey "ProductName" "${PRODUCTNAME}" +VIAddVersionKey "FileDescription" "${SHORTDESCRIPTION}" +VIAddVersionKey "LegalCopyright" "${COPYRIGHT}" +VIAddVersionKey "FileVersion" "${VERSION}" +VIAddVersionKey "ProductVersion" "${VERSION}" + +; Plugins path, currently exists for linux only +!if "${PLUGINSPATH}" != "" + !addplugindir "${PLUGINSPATH}" +!endif + +!if "${UNINSTALLERSIGNCOMMAND}" != "" + !uninstfinalize '${UNINSTALLERSIGNCOMMAND}' +!endif + +; Handle install mode, `perUser`, `perMachine` or `both` +!if "${INSTALLMODE}" == "perMachine" + RequestExecutionLevel highest +!endif + +!if "${INSTALLMODE}" == "currentUser" + RequestExecutionLevel user +!endif + +!if "${INSTALLMODE}" == "both" + !define MULTIUSER_MUI + !define MULTIUSER_INSTALLMODE_INSTDIR "${PRODUCTNAME}" + !define MULTIUSER_INSTALLMODE_COMMANDLINE + !if "${ARCH}" == "x64" + !define MULTIUSER_USE_PROGRAMFILES64 + !else if "${ARCH}" == "arm64" + !define MULTIUSER_USE_PROGRAMFILES64 + !endif + !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "${UNINSTKEY}" + !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "CurrentUser" + !define MULTIUSER_INSTALLMODEPAGE_SHOWUSERNAME + !define MULTIUSER_INSTALLMODE_FUNCTION RestorePreviousInstallLocation + !define MULTIUSER_EXECUTIONLEVEL Highest + !include MultiUser.nsh +!endif + +; installer icon +!if "${INSTALLERICON}" != "" + !define MUI_ICON "${INSTALLERICON}" +!endif + +; installer sidebar image +!if "${SIDEBARIMAGE}" != "" + !define MUI_WELCOMEFINISHPAGE_BITMAP "${SIDEBARIMAGE}" +!endif + +; installer header image +!if "${HEADERIMAGE}" != "" + !define MUI_HEADERIMAGE + !define MUI_HEADERIMAGE_BITMAP "${HEADERIMAGE}" +!endif + +; Define registry key to store installer language +!define MUI_LANGDLL_REGISTRY_ROOT "HKCU" +!define MUI_LANGDLL_REGISTRY_KEY "${MANUPRODUCTKEY}" +!define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language" + +; Installer pages, must be ordered as they appear +; 1. Welcome Page +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive +!insertmacro MUI_PAGE_WELCOME + +; 2. License Page (if defined) +!if "${LICENSE}" != "" + !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive + !insertmacro MUI_PAGE_LICENSE "${LICENSE}" +!endif + +; 3. Install mode (if it is set to `both`) +!if "${INSTALLMODE}" == "both" + !define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive + !insertmacro MULTIUSER_PAGE_INSTALLMODE +!endif + + +; 4. Custom page to ask user if he wants to reinstall/uninstall +; only if a previous installtion was detected +Var ReinstallPageCheck +Page custom PageReinstall PageLeaveReinstall +Function PageReinstall + ; Uninstall previous WiX installation if exists. + ; + ; A WiX installer stores the isntallation info in registry + ; using a UUID and so we have to loop through all keys under + ; `HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall` + ; and check if `DisplayName` and `Publisher` keys match ${PRODUCTNAME} and ${MANUFACTURER} + ; + ; This has a potentional issue that there maybe another installation that matches + ; our ${PRODUCTNAME} and ${MANUFACTURER} but wasn't installed by our WiX installer, + ; however, this should be fine since the user will have to confirm the uninstallation + ; and they can chose to abort it if doesn't make sense. + StrCpy $0 0 + wix_loop: + EnumRegKey $1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" $0 + StrCmp $1 "" wix_done ; Exit loop if there is no more keys to loop on + IntOp $0 $0 + 1 + ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "DisplayName" + ReadRegStr $R1 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "Publisher" + StrCmp "$R0$R1" "${PRODUCTNAME}${MANUFACTURER}" 0 wix_loop + ReadRegStr $R0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" "UninstallString" + ${StrCase} $R1 $R0 "L" + ${StrLoc} $R0 $R1 "msiexec" ">" + StrCmp $R0 0 0 wix_done + StrCpy $R7 "wix" + StrCpy $R6 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$1" + Goto compare_version + wix_done: + + ; Check if there is an existing installation, if not, abort the reinstall page + ReadRegStr $R0 SHCTX "${UNINSTKEY}" "" + ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString" + ${IfThen} "$R0$R1" == "" ${|} Abort ${|} + + ; Compare this installar version with the existing installation + ; and modify the messages presented to the user accordingly + compare_version: + StrCpy $R4 "$(older)" + ${If} $R7 == "wix" + ReadRegStr $R0 HKLM "$R6" "DisplayVersion" + ${Else} + ReadRegStr $R0 SHCTX "${UNINSTKEY}" "DisplayVersion" + ${EndIf} + ${IfThen} $R0 == "" ${|} StrCpy $R4 "$(unknown)" ${|} + + nsis_tauri_utils::SemverCompare "${VERSION}" $R0 + Pop $R0 + ; Reinstalling the same version + ${If} $R0 == 0 + StrCpy $R1 "$(alreadyInstalledLong)" + StrCpy $R2 "$(addOrReinstall)" + StrCpy $R3 "$(uninstallApp)" + !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(chooseMaintenanceOption)" + StrCpy $R5 "2" + ; Upgrading + ${ElseIf} $R0 == 1 + StrCpy $R1 "$(olderOrUnknownVersionInstalled)" + StrCpy $R2 "$(uninstallBeforeInstalling)" + StrCpy $R3 "$(dontUninstall)" + !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)" + StrCpy $R5 "1" + ; Downgrading + ${ElseIf} $R0 == -1 + StrCpy $R1 "$(newerVersionInstalled)" + StrCpy $R2 "$(uninstallBeforeInstalling)" + !if "${ALLOWDOWNGRADES}" == "true" + StrCpy $R3 "$(dontUninstall)" + !else + StrCpy $R3 "$(dontUninstallDowngrade)" + !endif + !insertmacro MUI_HEADER_TEXT "$(alreadyInstalled)" "$(choowHowToInstall)" + StrCpy $R5 "1" + ${Else} + Abort + ${EndIf} + + Call SkipIfPassive + + nsDialogs::Create 1018 + Pop $R4 + ${IfThen} $(^RTL) == 1 ${|} nsDialogs::SetRTL $(^RTL) ${|} + + ${NSD_CreateLabel} 0 0 100% 24u $R1 + Pop $R1 + + ${NSD_CreateRadioButton} 30u 50u -30u 8u $R2 + Pop $R2 + ${NSD_OnClick} $R2 PageReinstallUpdateSelection + + ${NSD_CreateRadioButton} 30u 70u -30u 8u $R3 + Pop $R3 + ; disable this radio button if downgrading and downgrades are disabled + !if "${ALLOWDOWNGRADES}" == "false" + ${IfThen} $R0 == -1 ${|} EnableWindow $R3 0 ${|} + !endif + ${NSD_OnClick} $R3 PageReinstallUpdateSelection + + ; Check the first radio button if this the first time + ; we enter this page or if the second button wasn't + ; selected the last time we were on this page + ${If} $ReinstallPageCheck != 2 + SendMessage $R2 ${BM_SETCHECK} ${BST_CHECKED} 0 + ${Else} + SendMessage $R3 ${BM_SETCHECK} ${BST_CHECKED} 0 + ${EndIf} + + ${NSD_SetFocus} $R2 + nsDialogs::Show +FunctionEnd +Function PageReinstallUpdateSelection + ${NSD_GetState} $R2 $R1 + ${If} $R1 == ${BST_CHECKED} + StrCpy $ReinstallPageCheck 1 + ${Else} + StrCpy $ReinstallPageCheck 2 + ${EndIf} +FunctionEnd +Function PageLeaveReinstall + ${NSD_GetState} $R2 $R1 + + ; $R5 holds whether we are reinstalling the same version or not + ; $R5 == "1" -> different versions + ; $R5 == "2" -> same version + ; + ; $R1 holds the radio buttons state. its meaning is dependant on the context + StrCmp $R5 "1" 0 +2 ; Existing install is not the same version? + StrCmp $R1 "1" reinst_uninstall reinst_done ; $R1 == "1", then user chose to uninstall existing version, otherwise skip uninstalling + StrCmp $R1 "1" reinst_done ; Same version? skip uninstalling + + reinst_uninstall: + HideWindow + ClearErrors + + ${If} $R7 == "wix" + ReadRegStr $R1 HKLM "$R6" "UninstallString" + ExecWait '$R1' $0 + ${Else} + ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" "" + ReadRegStr $R1 SHCTX "${UNINSTKEY}" "UninstallString" + ExecWait '$R1 /P _?=$4' $0 + ${EndIf} + + BringToFront + + ${IfThen} ${Errors} ${|} StrCpy $0 2 ${|} ; ExecWait failed, set fake exit code + + ${If} $0 <> 0 + ${OrIf} ${FileExists} "$INSTDIR\${MAINBINARYNAME}.exe" + ${If} $0 = 1 ; User aborted uninstaller? + StrCmp $R5 "2" 0 +2 ; Is the existing install the same version? + Quit ; ...yes, already installed, we are done + Abort + ${EndIf} + MessageBox MB_ICONEXCLAMATION "$(unableToUninstall)" + Abort + ${Else} + StrCpy $0 $R1 1 + ${IfThen} $0 == '"' ${|} StrCpy $R1 $R1 -1 1 ${|} ; Strip quotes from UninstallString + Delete $R1 + RMDir $INSTDIR + ${EndIf} + reinst_done: +FunctionEnd + +; 5. Choose install directoy page +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive +!insertmacro MUI_PAGE_DIRECTORY + +; 6. Start menu shortcut page +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive +Var AppStartMenuFolder +!insertmacro MUI_PAGE_STARTMENU Application $AppStartMenuFolder + +; 7. Installation page +!insertmacro MUI_PAGE_INSTFILES + +; 8. Finish page +; +; Don't auto jump to finish page after installation page, +; because the installation page has useful info that can be used debug any issues with the installer. +!define MUI_FINISHPAGE_NOAUTOCLOSE +; Use show readme button in the finish page as a button create a desktop shortcut +!define MUI_FINISHPAGE_SHOWREADME +!define MUI_FINISHPAGE_SHOWREADME_TEXT "$(createDesktop)" +!define MUI_FINISHPAGE_SHOWREADME_FUNCTION CreateDesktopShortcut +; Show run app after installation. +!define MUI_FINISHPAGE_RUN "$INSTDIR\${MAINBINARYNAME}.exe" +!define MUI_PAGE_CUSTOMFUNCTION_PRE SkipIfPassive +!insertmacro MUI_PAGE_FINISH + +; Uninstaller Pages +; 1. Confirm uninstall page +Var DeleteAppDataCheckbox +Var DeleteAppDataCheckboxState +!define /ifndef WS_EX_LAYOUTRTL 0x00400000 +!define MUI_PAGE_CUSTOMFUNCTION_SHOW un.ConfirmShow +Function un.ConfirmShow + FindWindow $1 "#32770" "" $HWNDPARENT ; Find inner dialog + ${If} $(^RTL) == 1 + System::Call 'USER32::CreateWindowEx(i${__NSD_CheckBox_EXSTYLE}|${WS_EX_LAYOUTRTL},t"${__NSD_CheckBox_CLASS}",t "$(deleteAppData)",i${__NSD_CheckBox_STYLE},i 50,i 100,i 400, i 25,i$1,i0,i0,i0)i.s' + ${Else} + System::Call 'USER32::CreateWindowEx(i${__NSD_CheckBox_EXSTYLE},t"${__NSD_CheckBox_CLASS}",t "$(deleteAppData)",i${__NSD_CheckBox_STYLE},i 0,i 100,i 400, i 25,i$1,i0,i0,i0)i.s' + ${EndIf} + Pop $DeleteAppDataCheckbox + SendMessage $HWNDPARENT ${WM_GETFONT} 0 0 $1 + SendMessage $DeleteAppDataCheckbox ${WM_SETFONT} $1 1 +FunctionEnd +!define MUI_PAGE_CUSTOMFUNCTION_LEAVE un.ConfirmLeave +Function un.ConfirmLeave + SendMessage $DeleteAppDataCheckbox ${BM_GETCHECK} 0 0 $DeleteAppDataCheckboxState +FunctionEnd +!insertmacro MUI_UNPAGE_CONFIRM + +; 2. Uninstalling Page +!insertmacro MUI_UNPAGE_INSTFILES + +;Languages +{{#each languages}} +!insertmacro MUI_LANGUAGE "{{this}}" +{{/each}} +!insertmacro MUI_RESERVEFILE_LANGDLL +{{#each language_files}} + !include "{{this}}" +{{/each}} + +!macro SetContext + !if "${INSTALLMODE}" == "currentUser" + SetShellVarContext current + !else if "${INSTALLMODE}" == "perMachine" + SetShellVarContext all + !endif + + ${If} ${RunningX64} + !if "${ARCH}" == "x64" + SetRegView 64 + !else if "${ARCH}" == "arm64" + SetRegView 64 + !else + SetRegView 32 + !endif + ${EndIf} +!macroend + +Var PassiveMode +Function .onInit + ${GetOptions} $CMDLINE "/P" $PassiveMode + IfErrors +2 0 + StrCpy $PassiveMode 1 + + !if "${DISPLAYLANGUAGESELECTOR}" == "true" + !insertmacro MUI_LANGDLL_DISPLAY + !endif + + !insertmacro SetContext + + ${If} $INSTDIR == "" + ; Set default install location + !if "${INSTALLMODE}" == "perMachine" + ${If} ${RunningX64} + !if "${ARCH}" == "x64" + StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCTNAME}" + !else if "${ARCH}" == "arm64" + StrCpy $INSTDIR "$PROGRAMFILES64\${PRODUCTNAME}" + !else + StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCTNAME}" + !endif + ${Else} + StrCpy $INSTDIR "$PROGRAMFILES\${PRODUCTNAME}" + ${EndIf} + !else if "${INSTALLMODE}" == "currentUser" + StrCpy $INSTDIR "$LOCALAPPDATA\${PRODUCTNAME}" + !endif + + Call RestorePreviousInstallLocation + ${EndIf} + + + !if "${INSTALLMODE}" == "both" + !insertmacro MULTIUSER_INIT + !endif +FunctionEnd + + +Section EarlyChecks + ; Abort silent installer if downgrades is disabled + !if "${ALLOWDOWNGRADES}" == "false" + IfSilent 0 silent_downgrades_done + ; If downgrading + ${If} $R0 == -1 + System::Call 'kernel32::AttachConsole(i -1)i.r0' + ${If} $0 != 0 + System::Call 'kernel32::GetStdHandle(i -11)i.r0' + System::call 'kernel32::SetConsoleTextAttribute(i r0, i 0x0004)' ; set red color + FileWrite $0 "$(silentDowngrades)" + ${EndIf} + Abort + ${EndIf} + silent_downgrades_done: + !endif + +SectionEnd + +Section WebView2 + ; Check if Webview2 is already installed and skip this section + ${If} ${RunningX64} + ReadRegStr $4 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + ${Else} + ReadRegStr $4 HKLM "SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + ${EndIf} + ReadRegStr $5 HKCU "SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + + StrCmp $4 "" 0 webview2_done + StrCmp $5 "" 0 webview2_done + + ; Webview2 install modes + !if "${INSTALLWEBVIEW2MODE}" == "downloadBootstrapper" + Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe" + DetailPrint "$(webview2Downloading)" + nsis_tauri_utils::download "https://go.microsoft.com/fwlink/p/?LinkId=2124703" "$TEMP\MicrosoftEdgeWebview2Setup.exe" + Pop $0 + ${If} $0 == 0 + DetailPrint "$(webview2DownloadSuccess)" + ${Else} + DetailPrint "$(webview2DownloadError)" + Abort "$(webview2AbortError)" + ${EndIf} + StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe" + Goto install_webview2 + !endif + + !if "${INSTALLWEBVIEW2MODE}" == "embedBootstrapper" + Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe" + File "/oname=$TEMP\MicrosoftEdgeWebview2Setup.exe" "${WEBVIEW2BOOTSTRAPPERPATH}" + DetailPrint "$(installingWebview2)" + StrCpy $6 "$TEMP\MicrosoftEdgeWebview2Setup.exe" + Goto install_webview2 + !endif + + !if "${INSTALLWEBVIEW2MODE}" == "offlineInstaller" + Delete "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe" + File "/oname=$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe" "${WEBVIEW2INSTALLERPATH}" + DetailPrint "$(installingWebview2)" + StrCpy $6 "$TEMP\MicrosoftEdgeWebView2RuntimeInstaller.exe" + Goto install_webview2 + !endif + + Goto webview2_done + + install_webview2: + DetailPrint "$(installingWebview2)" + ; $6 holds the path to the webview2 installer + ExecWait "$6 ${WEBVIEW2INSTALLERARGS} /install" $1 + ${If} $1 == 0 + DetailPrint "$(webview2InstallSuccess)" + ${Else} + DetailPrint "$(webview2InstallError)" + Abort "$(webview2AbortError)" + ${EndIf} + webview2_done: +SectionEnd + +!macro CheckIfAppIsRunning + !if "${INSTALLMODE}" == "currentUser" + nsis_tauri_utils::FindProcessCurrentUser "${MAINBINARYNAME}.exe" + !else + nsis_tauri_utils::FindProcess "${MAINBINARYNAME}.exe" + !endif + Pop $R0 + ${If} $R0 = 0 + IfSilent kill 0 + ${IfThen} $PassiveMode != 1 ${|} MessageBox MB_OKCANCEL "$(appRunningOkKill)" IDOK kill IDCANCEL cancel ${|} + kill: + !if "${INSTALLMODE}" == "currentUser" + nsis_tauri_utils::KillProcessCurrentUser "${MAINBINARYNAME}.exe" + !else + nsis_tauri_utils::KillProcess "${MAINBINARYNAME}.exe" + !endif + Pop $R0 + Sleep 500 + ${If} $R0 = 0 + Goto app_check_done + ${Else} + IfSilent silent ui + silent: + System::Call 'kernel32::AttachConsole(i -1)i.r0' + ${If} $0 != 0 + System::Call 'kernel32::GetStdHandle(i -11)i.r0' + System::call 'kernel32::SetConsoleTextAttribute(i r0, i 0x0004)' ; set red color + FileWrite $0 "$(appRunning)$\n" + ${EndIf} + Abort + ui: + Abort "$(failedToKillApp)" + ${EndIf} + cancel: + Abort "$(appRunning)" + ${EndIf} + app_check_done: +!macroend + +Section Install + SetOutPath $INSTDIR + + !insertmacro CheckIfAppIsRunning + + ; Copy main executable + File "${MAINBINARYSRCPATH}" + + ; Copy resources + {{#each resources_dirs}} + CreateDirectory "$INSTDIR\\{{this}}" + {{/each}} + {{#each resources}} + File /a "/oname={{this.[1]}}" "{{@key}}" + {{/each}} + + ; Copy external binaries + {{#each binaries}} + File /a "/oname={{this}}" "{{@key}}" + {{/each}} + + ; Create uninstaller + WriteUninstaller "$INSTDIR\uninstall.exe" + + ; Save $INSTDIR in registry for future installations + WriteRegStr SHCTX "${MANUPRODUCTKEY}" "" $INSTDIR + + !if "${INSTALLMODE}" == "both" + ; Save install mode to be selected by default for the next installation such as updating + ; or when uninstalling + WriteRegStr SHCTX "${UNINSTKEY}" $MultiUser.InstallMode 1 + !endif + + ; Registry information for add/remove programs + WriteRegStr SHCTX "${UNINSTKEY}" "DisplayName" "${PRODUCTNAME}" + WriteRegStr SHCTX "${UNINSTKEY}" "DisplayIcon" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\"" + WriteRegStr SHCTX "${UNINSTKEY}" "DisplayVersion" "${VERSION}" + WriteRegStr SHCTX "${UNINSTKEY}" "Publisher" "${MANUFACTURER}" + WriteRegStr SHCTX "${UNINSTKEY}" "InstallLocation" "$\"$INSTDIR$\"" + WriteRegStr SHCTX "${UNINSTKEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1" + WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1" + WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "${ESTIMATEDSIZE}" + + ; Set file association and context menu for .html files + WriteRegStr HKCU "Software\Classes\.html" "" "phcodeHTML" + WriteRegStr HKCU "Software\Classes\phcodeHTML" "" "HTML file" + WriteRegStr HKCU "Software\Classes\phcodeHTML\DefaultIcon" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\",0" + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + + + ; Set file association and context menu for .js files + WriteRegStr HKCU "Software\Classes\.js" "" "phcodeJS" + WriteRegStr HKCU "Software\Classes\phcodeJS" "" "JavaScript file" + WriteRegStr HKCU "Software\Classes\phcodeJS\DefaultIcon" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\",0" + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + + ; Set file association and context menu for .css files + WriteRegStr HKCU "Software\Classes\.css" "" "phcodeCSS" + WriteRegStr HKCU "Software\Classes\phcodeCSS" "" "CSS file" + WriteRegStr HKCU "Software\Classes\phcodeCSS\DefaultIcon" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\",0" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + + ; Create start menu shortcut (GUI) + !insertmacro MUI_STARTMENU_WRITE_BEGIN Application + Call CreateStartMenuShortcut + !insertmacro MUI_STARTMENU_WRITE_END + + ; Create shortcuts for silent and passive installers, which + ; can be disabled by passing `/NS` flag + ; GUI installer has buttons for users to control creating them + IfSilent check_ns_flag 0 + ${IfThen} $PassiveMode == 1 ${|} Goto check_ns_flag ${|} + Goto shortcuts_done + check_ns_flag: + ${GetOptions} $CMDLINE "/NS" $R0 + IfErrors 0 shortcuts_done + Call CreateDesktopShortcut + Call CreateStartMenuShortcut + shortcuts_done: + + ; Auto close this page for passive mode + ${IfThen} $PassiveMode == 1 ${|} SetAutoClose true ${|} +SectionEnd + +Function .onInstSuccess + ; Check for `/R` flag only in silent and passive installers because + ; GUI installer has a toggle for the user to (re)start the app + IfSilent check_r_flag 0 + ${IfThen} $PassiveMode == 1 ${|} Goto check_r_flag ${|} + Goto run_done + check_r_flag: + ${GetOptions} $CMDLINE "/R" $R0 + IfErrors run_done 0 + Exec '"$INSTDIR\${MAINBINARYNAME}.exe"' + run_done: +FunctionEnd + +Function un.onInit + !insertmacro SetContext + + !if "${INSTALLMODE}" == "both" + !insertmacro MULTIUSER_UNINIT + !endif + + !insertmacro MUI_UNGETLANGUAGE +FunctionEnd + +Section Uninstall + !insertmacro CheckIfAppIsRunning + + ; Delete the app directory and its content from disk + ; Copy main executable + Delete "$INSTDIR\${MAINBINARYNAME}.exe" + + ; Delete resources + {{#each resources}} + Delete "$INSTDIR\\{{this.[1]}}" + {{/each}} + + ; Delete external binaries + {{#each binaries}} + Delete "$INSTDIR\\{{this}}" + {{/each}} + + ; Delete uninstaller + Delete "$INSTDIR\uninstall.exe" + + ${If} $DeleteAppDataCheckboxState == 1 + RMDir /R /REBOOTOK "$INSTDIR" + ${Else} + {{#each resources_ancestors}} + RMDir /REBOOTOK "$INSTDIR\\{{this}}" + {{/each}} + RMDir "$INSTDIR" + ${EndIf} + ; Remove registry entries for .html file associations and context menu + DeleteRegKey HKCU "Software\Classes\.html" + DeleteRegKey HKCU "Software\Classes\phcodeHTML" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode" + + ; Remove registry entries for .js file associations and context menu + DeleteRegKey HKCU "Software\Classes\.js" + DeleteRegKey HKCU "Software\Classes\phcodeJS" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode" + + ; Remove registry entries for .css file associations and context menu + DeleteRegKey HKCU "Software\Classes\.css" + DeleteRegKey HKCU "Software\Classes\phcodeCSS" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode" + + ; Remove start menu shortcut + !insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder + Delete "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" + RMDir "$SMPROGRAMS\$AppStartMenuFolder" + + ; Remove desktop shortcuts + Delete "$DESKTOP\${MAINBINARYNAME}.lnk" + + ; Remove registry information for add/remove programs + !if "${INSTALLMODE}" == "both" + DeleteRegKey SHCTX "${UNINSTKEY}" + !else if "${INSTALLMODE}" == "perMachine" + DeleteRegKey HKLM "${UNINSTKEY}" + !else + DeleteRegKey HKCU "${UNINSTKEY}" + !endif + + DeleteRegValue HKCU "${MANUPRODUCTKEY}" "Installer Language" + + ; Delete app data + ${If} $DeleteAppDataCheckboxState == 1 + SetShellVarContext current + RmDir /r "$APPDATA\${BUNDLEID}" + RmDir /r "$LOCALAPPDATA\${BUNDLEID}" + ${EndIf} + + ${GetOptions} $CMDLINE "/P" $R0 + IfErrors +2 0 + SetAutoClose true +SectionEnd + +Function RestorePreviousInstallLocation + ReadRegStr $4 SHCTX "${MANUPRODUCTKEY}" "" + StrCmp $4 "" +2 0 + StrCpy $INSTDIR $4 +FunctionEnd + +Function SkipIfPassive + ${IfThen} $PassiveMode == 1 ${|} Abort ${|} +FunctionEnd + +Function CreateDesktopShortcut + CreateShortcut "$DESKTOP\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + ApplicationID::Set "$DESKTOP\${MAINBINARYNAME}.lnk" "${BUNDLEID}" +FunctionEnd + +Function CreateStartMenuShortcut + CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder" + CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" + ApplicationID::Set "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "${BUNDLEID}" +FunctionEnd diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2c3a592a..b228b0e1 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -146,6 +146,7 @@ "nsis": { "displayLanguageSelector": true, "license": "./license/agpl", + "template" : "./src/bundle/windows/nsis/installer.nsi", "languages": [ "English", "Afrikaans", @@ -331,4 +332,4 @@ } ] } -} \ No newline at end of file +} From eebd5abfcecdba9270552df55c816dae3fd58c9a Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 17 Jan 2024 16:52:06 +0530 Subject: [PATCH 240/864] fix: nsi was not escaping correctly --- .../src/bundle/windows/nsis/installer.nsi | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi index 6e910b3b..85e0abae 100644 --- a/src-tauri/src/bundle/windows/nsis/installer.nsi +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -574,31 +574,29 @@ Section Install WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1" WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1" WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "${ESTIMATEDSIZE}" - - ; Set file association and context menu for .html files + ; Set file association and context menu for .html files WriteRegStr HKCU "Software\Classes\.html" "" "phcodeHTML" WriteRegStr HKCU "Software\Classes\phcodeHTML" "" "HTML file" - WriteRegStr HKCU "Software\Classes\phcodeHTML\DefaultIcon" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\",0" - WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + WriteRegStr HKCU "Software\Classes\phcodeHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" - + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .js files WriteRegStr HKCU "Software\Classes\.js" "" "phcodeJS" WriteRegStr HKCU "Software\Classes\phcodeJS" "" "JavaScript file" - WriteRegStr HKCU "Software\Classes\phcodeJS\DefaultIcon" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\",0" - WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + WriteRegStr HKCU "Software\Classes\phcodeJS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .css files WriteRegStr HKCU "Software\Classes\.css" "" "phcodeCSS" WriteRegStr HKCU "Software\Classes\phcodeCSS" "" "CSS file" - WriteRegStr HKCU "Software\Classes\phcodeCSS\DefaultIcon" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\",0" - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + WriteRegStr HKCU "Software\Classes\phcodeCSS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode\command" "" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\" \"%1\"" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Create start menu shortcut (GUI) !insertmacro MUI_STARTMENU_WRITE_BEGIN Application From 415963623cbd5e29f98ba1113aee9751aac5b436 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 17 Jan 2024 23:12:13 +0530 Subject: [PATCH 241/864] feat: added support for adding reg entiries one by one --- .../src/bundle/windows/nsis/installer.nsi | 988 +++++++++++++++++- 1 file changed, 961 insertions(+), 27 deletions(-) diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi index 85e0abae..f65fc83b 100644 --- a/src-tauri/src/bundle/windows/nsis/installer.nsi +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -530,6 +530,148 @@ SectionEnd ${EndIf} app_check_done: !macroend +Function AssociateFiles + ; Push file types and descriptions onto the stack + Push ".asax" + Push "ASP.NET Server Application" + Push ".ashx" + Push "ASP.NET Web Handler" + Push ".aspx" + Push "ASP.NET Server Page" + Push ".atom" + Push "Atom Syndication Format" + Push ".cf" + Push "ColdFusion" + Push ".cfc" + Push "ColdFusion Component" + Push ".cfm" + Push "ColdFusion Markup" + Push ".cfm1" + Push "ColdFusion Markup (Alternate)" + Push ".clj" + Push "Clojure Source File" + Push ".coffee" + Push "CoffeeScript" + Push ".cshtml" + Push "ASP.NET Razor Web Page" + Push ".cson" + Push "CSON Document" + Push ".css" + Push "Cascading Style Sheets" + Push ".ctp" + Push "CakePHP Template" + Push ".dhtml" + Push "Dynamic HTML" + Push ".diff" + Push "Diff Output" + Push ".ejs" + Push "Embedded JavaScript Template" + Push ".handlebars" + Push "Handlebars Template" + Push ".hbs" + Push "Handlebars Template" + Push ".htm" + Push "HTML Document" + Push ".html" + Push "HTML Document" + Push ".hx" + Push "Haxe Source File" + Push ".js" + Push "JavaScript File" + Push ".json" + Push "JSON Document" + Push ".jsp" + Push "Java Server Page" + Push ".jsx" + Push "JSX Script" + Push ".kit" + Push "Kit File" + Push ".less" + Push "LESS Style Sheet" + Push ".markdown" + Push "Markdown Document" + Push ".mathml" + Push "MathML Document" + Push ".md" + Push "Markdown Document" + Push ".patch" + Push "Patch File" + Push ".php" + Push "PHP Script" + Push ".php3" + Push "PHP 3 Script" + Push ".php4" + Push "PHP 4 Script" + Push ".php5" + Push "PHP 5 Script" + Push ".phtm" + Push "PHP-based Web Page" + Push ".phtml" + Push "PHP Web Page" + Push ".rdf" + Push "Resource Description Framework File" + Push ".rss" + Push "RSS Feed" + Push ".sass" + Push "SASS Style Sheet" + Push ".scss" + Push "SCSS Style Sheet" + Push ".shtm" + Push "HTML Document with SSI" + Push ".shtml" + Push "HTML Document with SSI" + Push ".sql" + Push "SQL Database Script" + Push ".svg" + Push "Scalable Vector Graphics" + Push ".tpl" + Push "Template File" + Push ".twig" + Push "Twig Template" + Push ".wsgi" + Push "Python WSGI Script" + Push ".xbl" + Push "XML Binding Language File" + Push ".xht" + Push "XHTML Document" + Push ".xhtml" + Push "XHTML Document" + Push ".xml" + Push "XML Document" + Push ".xslt" + Push "XSL Transformation" + Push ".xul" + Push "XML User Interface Language File" + Push ".yaml" + Push "YAML Document" + Push ".yml" + Push "YAML Document" + + loop: + ; Attempt to Pop the description + Pop $0 + ; Check if $0 is empty (description) + ${If} $0 == "" + ; If $0 is empty, it means the stack is empty, exit the loop + Goto loop_end + ${EndIf} + ; Attempt to Pop the file extension + Pop $1 + + ; Set file association + WriteRegStr HKCU "Software\Classes\$1" "" "phcode$1" + WriteRegStr HKCU "Software\Classes\phcode$1" "" $0 + WriteRegStr HKCU "Software\Classes\phcode$1\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcode$1\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcode$1\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcode$1\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + + ; Continue looping + Goto loop + + loop_end: + +FunctionEnd Section Install SetOutPath $INSTDIR @@ -574,29 +716,479 @@ Section Install WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1" WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1" WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "${ESTIMATEDSIZE}" - ; Set file association and context menu for .html files + + ; Set file association and context menu for .asax files + WriteRegStr HKCU "Software\Classes\.asax" "" "phcodeASAX" + WriteRegStr HKCU "Software\Classes\phcodeASAX" "" "ASAX file" + WriteRegStr HKCU "Software\Classes\phcodeASAX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .ashx files + WriteRegStr HKCU "Software\Classes\.ashx" "" "phcodeASHX" + WriteRegStr HKCU "Software\Classes\phcodeASHX" "" "ASHX file" + WriteRegStr HKCU "Software\Classes\phcodeASHX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .aspx files + WriteRegStr HKCU "Software\Classes\.aspx" "" "phcodeASPX" + WriteRegStr HKCU "Software\Classes\phcodeASPX" "" "ASPX file" + WriteRegStr HKCU "Software\Classes\phcodeASPX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .atom files + WriteRegStr HKCU "Software\Classes\.atom" "" "phcodeATOM" + WriteRegStr HKCU "Software\Classes\phcodeATOM" "" "ATOM file" + WriteRegStr HKCU "Software\Classes\phcodeATOM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .cf files + WriteRegStr HKCU "Software\Classes\.cf" "" "phcodeCF" + WriteRegStr HKCU "Software\Classes\phcodeCF" "" "CF file" + WriteRegStr HKCU "Software\Classes\phcodeCF\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .cfc files + WriteRegStr HKCU "Software\Classes\.cfc" "" "phcodeCFC" + WriteRegStr HKCU "Software\Classes\phcodeCFC" "" "CFC file" + WriteRegStr HKCU "Software\Classes\phcodeCFC\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .cfm files + WriteRegStr HKCU "Software\Classes\.cfm" "" "phcodeCFM" + WriteRegStr HKCU "Software\Classes\phcodeCFM" "" "CFM file" + WriteRegStr HKCU "Software\Classes\phcodeCFM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .cfm1 files + WriteRegStr HKCU "Software\Classes\.cfm1" "" "phcodeCFM1" + WriteRegStr HKCU "Software\Classes\phcodeCFM1" "" "CFM1 file" + WriteRegStr HKCU "Software\Classes\phcodeCFM1\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .clj files + WriteRegStr HKCU "Software\Classes\.clj" "" "phcodeCLJ" + WriteRegStr HKCU "Software\Classes\phcodeCLJ" "" "CLJ file" + WriteRegStr HKCU "Software\Classes\phcodeCLJ\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .coffee files + WriteRegStr HKCU "Software\Classes\.coffee" "" "phcodeCOFFEE" + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE" "" "COFFEE file" + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .cshtml files + WriteRegStr HKCU "Software\Classes\.cshtml" "" "phcodeCSHTML" + WriteRegStr HKCU "Software\Classes\phcodeCSHTML" "" "CSHTML file" + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .cson files + WriteRegStr HKCU "Software\Classes\.cson" "" "phcodeCSON" + WriteRegStr HKCU "Software\Classes\phcodeCSON" "" "CSON file" + WriteRegStr HKCU "Software\Classes\phcodeCSON\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .css files + WriteRegStr HKCU "Software\Classes\.css" "" "phcodeCSS" + WriteRegStr HKCU "Software\Classes\phcodeCSS" "" "CSS file" + WriteRegStr HKCU "Software\Classes\phcodeCSS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .ctp files + WriteRegStr HKCU "Software\Classes\.ctp" "" "phcodeCTP" + WriteRegStr HKCU "Software\Classes\phcodeCTP" "" "CTP file" + WriteRegStr HKCU "Software\Classes\phcodeCTP\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .dhtml files + WriteRegStr HKCU "Software\Classes\.dhtml" "" "phcodeDHTML" + WriteRegStr HKCU "Software\Classes\phcodeDHTML" "" "DHTML file" + WriteRegStr HKCU "Software\Classes\phcodeDHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .diff files + WriteRegStr HKCU "Software\Classes\.diff" "" "phcodeDIFF" + WriteRegStr HKCU "Software\Classes\phcodeDIFF" "" "DIFF file" + WriteRegStr HKCU "Software\Classes\phcodeDIFF\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .ejs files + WriteRegStr HKCU "Software\Classes\.ejs" "" "phcodeEJS" + WriteRegStr HKCU "Software\Classes\phcodeEJS" "" "EJS file" + WriteRegStr HKCU "Software\Classes\phcodeEJS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .handlebars files + WriteRegStr HKCU "Software\Classes\.handlebars" "" "phcodeHANDLEBARS" + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS" "" "HANDLEBARS file" + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .hbs files + WriteRegStr HKCU "Software\Classes\.hbs" "" "phcodeHBS" + WriteRegStr HKCU "Software\Classes\phcodeHBS" "" "HBS file" + WriteRegStr HKCU "Software\Classes\phcodeHBS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .htm files + WriteRegStr HKCU "Software\Classes\.htm" "" "phcodeHTM" + WriteRegStr HKCU "Software\Classes\phcodeHTM" "" "HTM file" + WriteRegStr HKCU "Software\Classes\phcodeHTM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .html files WriteRegStr HKCU "Software\Classes\.html" "" "phcodeHTML" WriteRegStr HKCU "Software\Classes\phcodeHTML" "" "HTML file" WriteRegStr HKCU "Software\Classes\phcodeHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .hx files + WriteRegStr HKCU "Software\Classes\.hx" "" "phcodeHX" + WriteRegStr HKCU "Software\Classes\phcodeHX" "" "HX file" + WriteRegStr HKCU "Software\Classes\phcodeHX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' ; Set file association and context menu for .js files WriteRegStr HKCU "Software\Classes\.js" "" "phcodeJS" - WriteRegStr HKCU "Software\Classes\phcodeJS" "" "JavaScript file" + WriteRegStr HKCU "Software\Classes\phcodeJS" "" "JS file" WriteRegStr HKCU "Software\Classes\phcodeJS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .json files + WriteRegStr HKCU "Software\Classes\.json" "" "phcodeJSON" + WriteRegStr HKCU "Software\Classes\phcodeJSON" "" "JSON file" + WriteRegStr HKCU "Software\Classes\phcodeJSON\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .jsp files + WriteRegStr HKCU "Software\Classes\.jsp" "" "phcodeJSP" + WriteRegStr HKCU "Software\Classes\phcodeJSP" "" "JSP file" + WriteRegStr HKCU "Software\Classes\phcodeJSP\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .jsx files + WriteRegStr HKCU "Software\Classes\.jsx" "" "phcodeJSX" + WriteRegStr HKCU "Software\Classes\phcodeJSX" "" "JSX file" + WriteRegStr HKCU "Software\Classes\phcodeJSX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .kit files + WriteRegStr HKCU "Software\Classes\.kit" "" "phcodeKIT" + WriteRegStr HKCU "Software\Classes\phcodeKIT" "" "KIT file" + WriteRegStr HKCU "Software\Classes\phcodeKIT\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .less files + WriteRegStr HKCU "Software\Classes\.less" "" "phcodeLESS" + WriteRegStr HKCU "Software\Classes\phcodeLESS" "" "LESS file" + WriteRegStr HKCU "Software\Classes\phcodeLESS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .markdown files + WriteRegStr HKCU "Software\Classes\.markdown" "" "phcodeMARKDOWN" + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN" "" "MARKDOWN file" + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .mathml files + WriteRegStr HKCU "Software\Classes\.mathml" "" "phcodeMATHML" + WriteRegStr HKCU "Software\Classes\phcodeMATHML" "" "MATHML file" + WriteRegStr HKCU "Software\Classes\phcodeMATHML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .md files + WriteRegStr HKCU "Software\Classes\.md" "" "phcodeMD" + WriteRegStr HKCU "Software\Classes\phcodeMD" "" "MD file" + WriteRegStr HKCU "Software\Classes\phcodeMD\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .patch files + WriteRegStr HKCU "Software\Classes\.patch" "" "phcodePATCH" + WriteRegStr HKCU "Software\Classes\phcodePATCH" "" "PATCH file" + WriteRegStr HKCU "Software\Classes\phcodePATCH\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .php files + WriteRegStr HKCU "Software\Classes\.php" "" "phcodePHP" + WriteRegStr HKCU "Software\Classes\phcodePHP" "" "PHP file" + WriteRegStr HKCU "Software\Classes\phcodePHP\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .php3 files + WriteRegStr HKCU "Software\Classes\.php3" "" "phcodePHP3" + WriteRegStr HKCU "Software\Classes\phcodePHP3" "" "PHP3 file" + WriteRegStr HKCU "Software\Classes\phcodePHP3\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .php4 files + WriteRegStr HKCU "Software\Classes\.php4" "" "phcodePHP4" + WriteRegStr HKCU "Software\Classes\phcodePHP4" "" "PHP4 file" + WriteRegStr HKCU "Software\Classes\phcodePHP4\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .php5 files + WriteRegStr HKCU "Software\Classes\.php5" "" "phcodePHP5" + WriteRegStr HKCU "Software\Classes\phcodePHP5" "" "PHP5 file" + WriteRegStr HKCU "Software\Classes\phcodePHP5\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .phtm files + WriteRegStr HKCU "Software\Classes\.phtm" "" "phcodePHTM" + WriteRegStr HKCU "Software\Classes\phcodePHTM" "" "PHTM file" + WriteRegStr HKCU "Software\Classes\phcodePHTM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .phtml files + WriteRegStr HKCU "Software\Classes\.phtml" "" "phcodePHTML" + WriteRegStr HKCU "Software\Classes\phcodePHTML" "" "PHTML file" + WriteRegStr HKCU "Software\Classes\phcodePHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .rdf files + WriteRegStr HKCU "Software\Classes\.rdf" "" "phcodeRDF" + WriteRegStr HKCU "Software\Classes\phcodeRDF" "" "RDF file" + WriteRegStr HKCU "Software\Classes\phcodeRDF\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .rss files + WriteRegStr HKCU "Software\Classes\.rss" "" "phcodeRSS" + WriteRegStr HKCU "Software\Classes\phcodeRSS" "" "RSS file" + WriteRegStr HKCU "Software\Classes\phcodeRSS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .sass files + WriteRegStr HKCU "Software\Classes\.sass" "" "phcodeSASS" + WriteRegStr HKCU "Software\Classes\phcodeSASS" "" "SASS file" + WriteRegStr HKCU "Software\Classes\phcodeSASS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .scss files + WriteRegStr HKCU "Software\Classes\.scss" "" "phcodeSCSS" + WriteRegStr HKCU "Software\Classes\phcodeSCSS" "" "SCSS file" + WriteRegStr HKCU "Software\Classes\phcodeSCSS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .shtm files + WriteRegStr HKCU "Software\Classes\.shtm" "" "phcodeSHTM" + WriteRegStr HKCU "Software\Classes\phcodeSHTM" "" "SHTM file" + WriteRegStr HKCU "Software\Classes\phcodeSHTM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .shtml files + WriteRegStr HKCU "Software\Classes\.shtml" "" "phcodeSHTML" + WriteRegStr HKCU "Software\Classes\phcodeSHTML" "" "SHTML file" + WriteRegStr HKCU "Software\Classes\phcodeSHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .sql files + WriteRegStr HKCU "Software\Classes\.sql" "" "phcodeSQL" + WriteRegStr HKCU "Software\Classes\phcodeSQL" "" "SQL file" + WriteRegStr HKCU "Software\Classes\phcodeSQL\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .svg files + WriteRegStr HKCU "Software\Classes\.svg" "" "phcodeSVG" + WriteRegStr HKCU "Software\Classes\phcodeSVG" "" "SVG file" + WriteRegStr HKCU "Software\Classes\phcodeSVG\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .tpl files + WriteRegStr HKCU "Software\Classes\.tpl" "" "phcodeTPL" + WriteRegStr HKCU "Software\Classes\phcodeTPL" "" "TPL file" + WriteRegStr HKCU "Software\Classes\phcodeTPL\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .twig files + WriteRegStr HKCU "Software\Classes\.twig" "" "phcodeTWIG" + WriteRegStr HKCU "Software\Classes\phcodeTWIG" "" "TWIG file" + WriteRegStr HKCU "Software\Classes\phcodeTWIG\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .wsgi files + WriteRegStr HKCU "Software\Classes\.wsgi" "" "phcodeWSGI" + WriteRegStr HKCU "Software\Classes\phcodeWSGI" "" "WSGI file" + WriteRegStr HKCU "Software\Classes\phcodeWSGI\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .xbl files + WriteRegStr HKCU "Software\Classes\.xbl" "" "phcodeXBL" + WriteRegStr HKCU "Software\Classes\phcodeXBL" "" "XBL file" + WriteRegStr HKCU "Software\Classes\phcodeXBL\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .xht files + WriteRegStr HKCU "Software\Classes\.xht" "" "phcodeXHT" + WriteRegStr HKCU "Software\Classes\phcodeXHT" "" "XHT file" + WriteRegStr HKCU "Software\Classes\phcodeXHT\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .xhtml files + WriteRegStr HKCU "Software\Classes\.xhtml" "" "phcodeXHTML" + WriteRegStr HKCU "Software\Classes\phcodeXHTML" "" "XHTML file" + WriteRegStr HKCU "Software\Classes\phcodeXHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .xml files + WriteRegStr HKCU "Software\Classes\.xml" "" "phcodeXML" + WriteRegStr HKCU "Software\Classes\phcodeXML" "" "XML file" + WriteRegStr HKCU "Software\Classes\phcodeXML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .xslt files + WriteRegStr HKCU "Software\Classes\.xslt" "" "phcodeXSLT" + WriteRegStr HKCU "Software\Classes\phcodeXSLT" "" "XSLT file" + WriteRegStr HKCU "Software\Classes\phcodeXSLT\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .xul files + WriteRegStr HKCU "Software\Classes\.xul" "" "phcodeXUL" + WriteRegStr HKCU "Software\Classes\phcodeXUL" "" "XUL file" + WriteRegStr HKCU "Software\Classes\phcodeXUL\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .yaml files + WriteRegStr HKCU "Software\Classes\.yaml" "" "phcodeYAML" + WriteRegStr HKCU "Software\Classes\phcodeYAML" "" "YAML file" + WriteRegStr HKCU "Software\Classes\phcodeYAML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .yml files + WriteRegStr HKCU "Software\Classes\.yml" "" "phcodeYML" + WriteRegStr HKCU "Software\Classes\phcodeYML" "" "YML file" + WriteRegStr HKCU "Software\Classes\phcodeYML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .ts files + WriteRegStr HKCU "Software\Classes\.ts" "" "phcodeTS" + WriteRegStr HKCU "Software\Classes\phcodeTS" "" "TS file" + WriteRegStr HKCU "Software\Classes\phcodeTS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + + ; Set file association and context menu for .tsx files + WriteRegStr HKCU "Software\Classes\.tsx" "" "phcodeTSX" + WriteRegStr HKCU "Software\Classes\phcodeTSX" "" "TSX file" + WriteRegStr HKCU "Software\Classes\phcodeTSX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - ; Set file association and context menu for .css files - WriteRegStr HKCU "Software\Classes\.css" "" "phcodeCSS" - WriteRegStr HKCU "Software\Classes\phcodeCSS" "" "CSS file" - WriteRegStr HKCU "Software\Classes\phcodeCSS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Create start menu shortcut (GUI) !insertmacro MUI_STARTMENU_WRITE_BEGIN Application @@ -671,20 +1263,362 @@ Section Uninstall {{/each}} RMDir "$INSTDIR" ${EndIf} - ; Remove registry entries for .html file associations and context menu - DeleteRegKey HKCU "Software\Classes\.html" - DeleteRegKey HKCU "Software\Classes\phcodeHTML" - DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode" - - ; Remove registry entries for .js file associations and context menu - DeleteRegKey HKCU "Software\Classes\.js" - DeleteRegKey HKCU "Software\Classes\phcodeJS" - DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode" - - ; Remove registry entries for .css file associations and context menu - DeleteRegKey HKCU "Software\Classes\.css" - DeleteRegKey HKCU "Software\Classes\phcodeCSS" - DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode" + ; NSIS Cleanup Script + + DeleteRegKey HKCU "Software\Classes\.asax" + DeleteRegKey HKCU "Software\Classes\phcodeASAX" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.ashx" + DeleteRegKey HKCU "Software\Classes\phcodeASHX" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.aspx" + DeleteRegKey HKCU "Software\Classes\phcodeASPX" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.atom" + DeleteRegKey HKCU "Software\Classes\phcodeATOM" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cf" + DeleteRegKey HKCU "Software\Classes\phcodeCF" + DeleteRegKey HKCU "Software\Classes\phcodeCF\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cfc" + DeleteRegKey HKCU "Software\Classes\phcodeCFC" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cfm" + DeleteRegKey HKCU "Software\Classes\phcodeCFM" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cfm1" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.clj" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.coffee" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cshtml" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cson" + DeleteRegKey HKCU "Software\Classes\phcodeCSON" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.css" + DeleteRegKey HKCU "Software\Classes\phcodeCSS" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.ctp" + DeleteRegKey HKCU "Software\Classes\phcodeCTP" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.dhtml" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.diff" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.ejs" + DeleteRegKey HKCU "Software\Classes\phcodeEJS" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.handlebars" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.hbs" + DeleteRegKey HKCU "Software\Classes\phcodeHBS" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.htm" + DeleteRegKey HKCU "Software\Classes\phcodeHTM" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.html" + DeleteRegKey HKCU "Software\Classes\phcodeHTML" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.hx" + DeleteRegKey HKCU "Software\Classes\phcodeHX" + DeleteRegKey HKCU "Software\Classes\phcodeHX\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.js" + DeleteRegKey HKCU "Software\Classes\phcodeJS" + DeleteRegKey HKCU "Software\Classes\phcodeJS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.json" + DeleteRegKey HKCU "Software\Classes\phcodeJSON" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.jsp" + DeleteRegKey HKCU "Software\Classes\phcodeJSP" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.jsx" + DeleteRegKey HKCU "Software\Classes\phcodeJSX" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.kit" + DeleteRegKey HKCU "Software\Classes\phcodeKIT" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.less" + DeleteRegKey HKCU "Software\Classes\phcodeLESS" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.markdown" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.mathml" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.md" + DeleteRegKey HKCU "Software\Classes\phcodeMD" + DeleteRegKey HKCU "Software\Classes\phcodeMD\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.patch" + DeleteRegKey HKCU "Software\Classes\phcodePATCH" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.php" + DeleteRegKey HKCU "Software\Classes\phcodePHP" + DeleteRegKey HKCU "Software\Classes\phcodePHP\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.php3" + DeleteRegKey HKCU "Software\Classes\phcodePHP3" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.php4" + DeleteRegKey HKCU "Software\Classes\phcodePHP4" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.php5" + DeleteRegKey HKCU "Software\Classes\phcodePHP5" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.phtm" + DeleteRegKey HKCU "Software\Classes\phcodePHTM" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.phtml" + DeleteRegKey HKCU "Software\Classes\phcodePHTML" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.rdf" + DeleteRegKey HKCU "Software\Classes\phcodeRDF" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.rss" + DeleteRegKey HKCU "Software\Classes\phcodeRSS" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.sass" + DeleteRegKey HKCU "Software\Classes\phcodeSASS" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.scss" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.shtm" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.shtml" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.sql" + DeleteRegKey HKCU "Software\Classes\phcodeSQL" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.svg" + DeleteRegKey HKCU "Software\Classes\phcodeSVG" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.tpl" + DeleteRegKey HKCU "Software\Classes\phcodeTPL" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.twig" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.wsgi" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xbl" + DeleteRegKey HKCU "Software\Classes\phcodeXBL" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xht" + DeleteRegKey HKCU "Software\Classes\phcodeXHT" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xhtml" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xml" + DeleteRegKey HKCU "Software\Classes\phcodeXML" + DeleteRegKey HKCU "Software\Classes\phcodeXML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xslt" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xul" + DeleteRegKey HKCU "Software\Classes\phcodeXUL" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.yaml" + DeleteRegKey HKCU "Software\Classes\phcodeYAML" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.yml" + DeleteRegKey HKCU "Software\Classes\phcodeYML" + DeleteRegKey HKCU "Software\Classes\phcodeYML\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.ts" + DeleteRegKey HKCU "Software\Classes\phcodeTS" + DeleteRegKey HKCU "Software\Classes\phcodeTS\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.tsx" + DeleteRegKey HKCU "Software\Classes\phcodeTSX" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\DefaultIcon" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode\command" ; Remove start menu shortcut !insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder From ef6764e8aeffcb96c51ef852be3d32a077b97538 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 18 Jan 2024 18:08:47 +0530 Subject: [PATCH 242/864] chore: added registy entires for all supported files --- .../src/bundle/windows/nsis/installer.nsi | 1069 +++++------------ 1 file changed, 289 insertions(+), 780 deletions(-) diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi index f65fc83b..e20e243a 100644 --- a/src-tauri/src/bundle/windows/nsis/installer.nsi +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -530,665 +530,348 @@ SectionEnd ${EndIf} app_check_done: !macroend -Function AssociateFiles - ; Push file types and descriptions onto the stack - Push ".asax" - Push "ASP.NET Server Application" - Push ".ashx" - Push "ASP.NET Web Handler" - Push ".aspx" - Push "ASP.NET Server Page" - Push ".atom" - Push "Atom Syndication Format" - Push ".cf" - Push "ColdFusion" - Push ".cfc" - Push "ColdFusion Component" - Push ".cfm" - Push "ColdFusion Markup" - Push ".cfm1" - Push "ColdFusion Markup (Alternate)" - Push ".clj" - Push "Clojure Source File" - Push ".coffee" - Push "CoffeeScript" - Push ".cshtml" - Push "ASP.NET Razor Web Page" - Push ".cson" - Push "CSON Document" - Push ".css" - Push "Cascading Style Sheets" - Push ".ctp" - Push "CakePHP Template" - Push ".dhtml" - Push "Dynamic HTML" - Push ".diff" - Push "Diff Output" - Push ".ejs" - Push "Embedded JavaScript Template" - Push ".handlebars" - Push "Handlebars Template" - Push ".hbs" - Push "Handlebars Template" - Push ".htm" - Push "HTML Document" - Push ".html" - Push "HTML Document" - Push ".hx" - Push "Haxe Source File" - Push ".js" - Push "JavaScript File" - Push ".json" - Push "JSON Document" - Push ".jsp" - Push "Java Server Page" - Push ".jsx" - Push "JSX Script" - Push ".kit" - Push "Kit File" - Push ".less" - Push "LESS Style Sheet" - Push ".markdown" - Push "Markdown Document" - Push ".mathml" - Push "MathML Document" - Push ".md" - Push "Markdown Document" - Push ".patch" - Push "Patch File" - Push ".php" - Push "PHP Script" - Push ".php3" - Push "PHP 3 Script" - Push ".php4" - Push "PHP 4 Script" - Push ".php5" - Push "PHP 5 Script" - Push ".phtm" - Push "PHP-based Web Page" - Push ".phtml" - Push "PHP Web Page" - Push ".rdf" - Push "Resource Description Framework File" - Push ".rss" - Push "RSS Feed" - Push ".sass" - Push "SASS Style Sheet" - Push ".scss" - Push "SCSS Style Sheet" - Push ".shtm" - Push "HTML Document with SSI" - Push ".shtml" - Push "HTML Document with SSI" - Push ".sql" - Push "SQL Database Script" - Push ".svg" - Push "Scalable Vector Graphics" - Push ".tpl" - Push "Template File" - Push ".twig" - Push "Twig Template" - Push ".wsgi" - Push "Python WSGI Script" - Push ".xbl" - Push "XML Binding Language File" - Push ".xht" - Push "XHTML Document" - Push ".xhtml" - Push "XHTML Document" - Push ".xml" - Push "XML Document" - Push ".xslt" - Push "XSL Transformation" - Push ".xul" - Push "XML User Interface Language File" - Push ".yaml" - Push "YAML Document" - Push ".yml" - Push "YAML Document" - - loop: - ; Attempt to Pop the description - Pop $0 - ; Check if $0 is empty (description) - ${If} $0 == "" - ; If $0 is empty, it means the stack is empty, exit the loop - Goto loop_end - ${EndIf} - ; Attempt to Pop the file extension - Pop $1 - - ; Set file association - WriteRegStr HKCU "Software\Classes\$1" "" "phcode$1" - WriteRegStr HKCU "Software\Classes\phcode$1" "" $0 - WriteRegStr HKCU "Software\Classes\phcode$1\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcode$1\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' - WriteRegStr HKCU "Software\Classes\phcode$1\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcode$1\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' - - ; Continue looping - Goto loop - - loop_end: -FunctionEnd - -Section Install - SetOutPath $INSTDIR - - !insertmacro CheckIfAppIsRunning - - ; Copy main executable - File "${MAINBINARYSRCPATH}" - - ; Copy resources - {{#each resources_dirs}} - CreateDirectory "$INSTDIR\\{{this}}" - {{/each}} - {{#each resources}} - File /a "/oname={{this.[1]}}" "{{@key}}" - {{/each}} - - ; Copy external binaries - {{#each binaries}} - File /a "/oname={{this}}" "{{@key}}" - {{/each}} - - ; Create uninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - ; Save $INSTDIR in registry for future installations - WriteRegStr SHCTX "${MANUPRODUCTKEY}" "" $INSTDIR - - !if "${INSTALLMODE}" == "both" - ; Save install mode to be selected by default for the next installation such as updating - ; or when uninstalling - WriteRegStr SHCTX "${UNINSTKEY}" $MultiUser.InstallMode 1 - !endif - - ; Registry information for add/remove programs - WriteRegStr SHCTX "${UNINSTKEY}" "DisplayName" "${PRODUCTNAME}" - WriteRegStr SHCTX "${UNINSTKEY}" "DisplayIcon" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\"" - WriteRegStr SHCTX "${UNINSTKEY}" "DisplayVersion" "${VERSION}" - WriteRegStr SHCTX "${UNINSTKEY}" "Publisher" "${MANUFACTURER}" - WriteRegStr SHCTX "${UNINSTKEY}" "InstallLocation" "$\"$INSTDIR$\"" - WriteRegStr SHCTX "${UNINSTKEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1" - WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1" - WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "${ESTIMATEDSIZE}" +Function SetupPhcode ; Set file association and context menu for .asax files WriteRegStr HKCU "Software\Classes\.asax" "" "phcodeASAX" WriteRegStr HKCU "Software\Classes\phcodeASAX" "" "ASAX file" - WriteRegStr HKCU "Software\Classes\phcodeASAX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ashx files WriteRegStr HKCU "Software\Classes\.ashx" "" "phcodeASHX" WriteRegStr HKCU "Software\Classes\phcodeASHX" "" "ASHX file" - WriteRegStr HKCU "Software\Classes\phcodeASHX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .aspx files WriteRegStr HKCU "Software\Classes\.aspx" "" "phcodeASPX" WriteRegStr HKCU "Software\Classes\phcodeASPX" "" "ASPX file" - WriteRegStr HKCU "Software\Classes\phcodeASPX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .atom files WriteRegStr HKCU "Software\Classes\.atom" "" "phcodeATOM" WriteRegStr HKCU "Software\Classes\phcodeATOM" "" "ATOM file" - WriteRegStr HKCU "Software\Classes\phcodeATOM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cf files WriteRegStr HKCU "Software\Classes\.cf" "" "phcodeCF" WriteRegStr HKCU "Software\Classes\phcodeCF" "" "CF file" - WriteRegStr HKCU "Software\Classes\phcodeCF\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfc files WriteRegStr HKCU "Software\Classes\.cfc" "" "phcodeCFC" WriteRegStr HKCU "Software\Classes\phcodeCFC" "" "CFC file" - WriteRegStr HKCU "Software\Classes\phcodeCFC\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfm files WriteRegStr HKCU "Software\Classes\.cfm" "" "phcodeCFM" WriteRegStr HKCU "Software\Classes\phcodeCFM" "" "CFM file" - WriteRegStr HKCU "Software\Classes\phcodeCFM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfm1 files WriteRegStr HKCU "Software\Classes\.cfm1" "" "phcodeCFM1" WriteRegStr HKCU "Software\Classes\phcodeCFM1" "" "CFM1 file" - WriteRegStr HKCU "Software\Classes\phcodeCFM1\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .clj files WriteRegStr HKCU "Software\Classes\.clj" "" "phcodeCLJ" WriteRegStr HKCU "Software\Classes\phcodeCLJ" "" "CLJ file" - WriteRegStr HKCU "Software\Classes\phcodeCLJ\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .coffee files WriteRegStr HKCU "Software\Classes\.coffee" "" "phcodeCOFFEE" WriteRegStr HKCU "Software\Classes\phcodeCOFFEE" "" "COFFEE file" - WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cshtml files WriteRegStr HKCU "Software\Classes\.cshtml" "" "phcodeCSHTML" WriteRegStr HKCU "Software\Classes\phcodeCSHTML" "" "CSHTML file" - WriteRegStr HKCU "Software\Classes\phcodeCSHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cson files WriteRegStr HKCU "Software\Classes\.cson" "" "phcodeCSON" WriteRegStr HKCU "Software\Classes\phcodeCSON" "" "CSON file" - WriteRegStr HKCU "Software\Classes\phcodeCSON\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .css files WriteRegStr HKCU "Software\Classes\.css" "" "phcodeCSS" WriteRegStr HKCU "Software\Classes\phcodeCSS" "" "CSS file" - WriteRegStr HKCU "Software\Classes\phcodeCSS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ctp files WriteRegStr HKCU "Software\Classes\.ctp" "" "phcodeCTP" WriteRegStr HKCU "Software\Classes\phcodeCTP" "" "CTP file" - WriteRegStr HKCU "Software\Classes\phcodeCTP\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .dhtml files WriteRegStr HKCU "Software\Classes\.dhtml" "" "phcodeDHTML" WriteRegStr HKCU "Software\Classes\phcodeDHTML" "" "DHTML file" - WriteRegStr HKCU "Software\Classes\phcodeDHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .diff files WriteRegStr HKCU "Software\Classes\.diff" "" "phcodeDIFF" WriteRegStr HKCU "Software\Classes\phcodeDIFF" "" "DIFF file" - WriteRegStr HKCU "Software\Classes\phcodeDIFF\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ejs files WriteRegStr HKCU "Software\Classes\.ejs" "" "phcodeEJS" WriteRegStr HKCU "Software\Classes\phcodeEJS" "" "EJS file" - WriteRegStr HKCU "Software\Classes\phcodeEJS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .handlebars files WriteRegStr HKCU "Software\Classes\.handlebars" "" "phcodeHANDLEBARS" WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS" "" "HANDLEBARS file" - WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .hbs files WriteRegStr HKCU "Software\Classes\.hbs" "" "phcodeHBS" WriteRegStr HKCU "Software\Classes\phcodeHBS" "" "HBS file" - WriteRegStr HKCU "Software\Classes\phcodeHBS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .htm files WriteRegStr HKCU "Software\Classes\.htm" "" "phcodeHTM" WriteRegStr HKCU "Software\Classes\phcodeHTM" "" "HTM file" - WriteRegStr HKCU "Software\Classes\phcodeHTM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .html files WriteRegStr HKCU "Software\Classes\.html" "" "phcodeHTML" WriteRegStr HKCU "Software\Classes\phcodeHTML" "" "HTML file" - WriteRegStr HKCU "Software\Classes\phcodeHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .hx files WriteRegStr HKCU "Software\Classes\.hx" "" "phcodeHX" WriteRegStr HKCU "Software\Classes\phcodeHX" "" "HX file" - WriteRegStr HKCU "Software\Classes\phcodeHX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .js files WriteRegStr HKCU "Software\Classes\.js" "" "phcodeJS" WriteRegStr HKCU "Software\Classes\phcodeJS" "" "JS file" - WriteRegStr HKCU "Software\Classes\phcodeJS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .json files WriteRegStr HKCU "Software\Classes\.json" "" "phcodeJSON" WriteRegStr HKCU "Software\Classes\phcodeJSON" "" "JSON file" - WriteRegStr HKCU "Software\Classes\phcodeJSON\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .jsp files WriteRegStr HKCU "Software\Classes\.jsp" "" "phcodeJSP" WriteRegStr HKCU "Software\Classes\phcodeJSP" "" "JSP file" - WriteRegStr HKCU "Software\Classes\phcodeJSP\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .jsx files WriteRegStr HKCU "Software\Classes\.jsx" "" "phcodeJSX" WriteRegStr HKCU "Software\Classes\phcodeJSX" "" "JSX file" - WriteRegStr HKCU "Software\Classes\phcodeJSX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .kit files WriteRegStr HKCU "Software\Classes\.kit" "" "phcodeKIT" WriteRegStr HKCU "Software\Classes\phcodeKIT" "" "KIT file" - WriteRegStr HKCU "Software\Classes\phcodeKIT\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .less files WriteRegStr HKCU "Software\Classes\.less" "" "phcodeLESS" WriteRegStr HKCU "Software\Classes\phcodeLESS" "" "LESS file" - WriteRegStr HKCU "Software\Classes\phcodeLESS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .markdown files WriteRegStr HKCU "Software\Classes\.markdown" "" "phcodeMARKDOWN" WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN" "" "MARKDOWN file" - WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .mathml files WriteRegStr HKCU "Software\Classes\.mathml" "" "phcodeMATHML" WriteRegStr HKCU "Software\Classes\phcodeMATHML" "" "MATHML file" - WriteRegStr HKCU "Software\Classes\phcodeMATHML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .md files WriteRegStr HKCU "Software\Classes\.md" "" "phcodeMD" WriteRegStr HKCU "Software\Classes\phcodeMD" "" "MD file" - WriteRegStr HKCU "Software\Classes\phcodeMD\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .patch files WriteRegStr HKCU "Software\Classes\.patch" "" "phcodePATCH" WriteRegStr HKCU "Software\Classes\phcodePATCH" "" "PATCH file" - WriteRegStr HKCU "Software\Classes\phcodePATCH\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php files WriteRegStr HKCU "Software\Classes\.php" "" "phcodePHP" WriteRegStr HKCU "Software\Classes\phcodePHP" "" "PHP file" - WriteRegStr HKCU "Software\Classes\phcodePHP\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php3 files WriteRegStr HKCU "Software\Classes\.php3" "" "phcodePHP3" WriteRegStr HKCU "Software\Classes\phcodePHP3" "" "PHP3 file" - WriteRegStr HKCU "Software\Classes\phcodePHP3\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php4 files WriteRegStr HKCU "Software\Classes\.php4" "" "phcodePHP4" WriteRegStr HKCU "Software\Classes\phcodePHP4" "" "PHP4 file" - WriteRegStr HKCU "Software\Classes\phcodePHP4\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php5 files WriteRegStr HKCU "Software\Classes\.php5" "" "phcodePHP5" WriteRegStr HKCU "Software\Classes\phcodePHP5" "" "PHP5 file" - WriteRegStr HKCU "Software\Classes\phcodePHP5\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .phtm files WriteRegStr HKCU "Software\Classes\.phtm" "" "phcodePHTM" WriteRegStr HKCU "Software\Classes\phcodePHTM" "" "PHTM file" - WriteRegStr HKCU "Software\Classes\phcodePHTM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .phtml files WriteRegStr HKCU "Software\Classes\.phtml" "" "phcodePHTML" WriteRegStr HKCU "Software\Classes\phcodePHTML" "" "PHTML file" - WriteRegStr HKCU "Software\Classes\phcodePHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .rdf files WriteRegStr HKCU "Software\Classes\.rdf" "" "phcodeRDF" WriteRegStr HKCU "Software\Classes\phcodeRDF" "" "RDF file" - WriteRegStr HKCU "Software\Classes\phcodeRDF\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .rss files WriteRegStr HKCU "Software\Classes\.rss" "" "phcodeRSS" WriteRegStr HKCU "Software\Classes\phcodeRSS" "" "RSS file" - WriteRegStr HKCU "Software\Classes\phcodeRSS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .sass files WriteRegStr HKCU "Software\Classes\.sass" "" "phcodeSASS" WriteRegStr HKCU "Software\Classes\phcodeSASS" "" "SASS file" - WriteRegStr HKCU "Software\Classes\phcodeSASS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .scss files WriteRegStr HKCU "Software\Classes\.scss" "" "phcodeSCSS" WriteRegStr HKCU "Software\Classes\phcodeSCSS" "" "SCSS file" - WriteRegStr HKCU "Software\Classes\phcodeSCSS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .shtm files WriteRegStr HKCU "Software\Classes\.shtm" "" "phcodeSHTM" WriteRegStr HKCU "Software\Classes\phcodeSHTM" "" "SHTM file" - WriteRegStr HKCU "Software\Classes\phcodeSHTM\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .shtml files WriteRegStr HKCU "Software\Classes\.shtml" "" "phcodeSHTML" WriteRegStr HKCU "Software\Classes\phcodeSHTML" "" "SHTML file" - WriteRegStr HKCU "Software\Classes\phcodeSHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .sql files WriteRegStr HKCU "Software\Classes\.sql" "" "phcodeSQL" WriteRegStr HKCU "Software\Classes\phcodeSQL" "" "SQL file" - WriteRegStr HKCU "Software\Classes\phcodeSQL\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .svg files WriteRegStr HKCU "Software\Classes\.svg" "" "phcodeSVG" WriteRegStr HKCU "Software\Classes\phcodeSVG" "" "SVG file" - WriteRegStr HKCU "Software\Classes\phcodeSVG\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .tpl files WriteRegStr HKCU "Software\Classes\.tpl" "" "phcodeTPL" WriteRegStr HKCU "Software\Classes\phcodeTPL" "" "TPL file" - WriteRegStr HKCU "Software\Classes\phcodeTPL\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .twig files WriteRegStr HKCU "Software\Classes\.twig" "" "phcodeTWIG" WriteRegStr HKCU "Software\Classes\phcodeTWIG" "" "TWIG file" - WriteRegStr HKCU "Software\Classes\phcodeTWIG\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .wsgi files WriteRegStr HKCU "Software\Classes\.wsgi" "" "phcodeWSGI" WriteRegStr HKCU "Software\Classes\phcodeWSGI" "" "WSGI file" - WriteRegStr HKCU "Software\Classes\phcodeWSGI\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xbl files WriteRegStr HKCU "Software\Classes\.xbl" "" "phcodeXBL" WriteRegStr HKCU "Software\Classes\phcodeXBL" "" "XBL file" - WriteRegStr HKCU "Software\Classes\phcodeXBL\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xht files WriteRegStr HKCU "Software\Classes\.xht" "" "phcodeXHT" WriteRegStr HKCU "Software\Classes\phcodeXHT" "" "XHT file" - WriteRegStr HKCU "Software\Classes\phcodeXHT\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xhtml files WriteRegStr HKCU "Software\Classes\.xhtml" "" "phcodeXHTML" WriteRegStr HKCU "Software\Classes\phcodeXHTML" "" "XHTML file" - WriteRegStr HKCU "Software\Classes\phcodeXHTML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xml files WriteRegStr HKCU "Software\Classes\.xml" "" "phcodeXML" WriteRegStr HKCU "Software\Classes\phcodeXML" "" "XML file" - WriteRegStr HKCU "Software\Classes\phcodeXML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xslt files WriteRegStr HKCU "Software\Classes\.xslt" "" "phcodeXSLT" WriteRegStr HKCU "Software\Classes\phcodeXSLT" "" "XSLT file" - WriteRegStr HKCU "Software\Classes\phcodeXSLT\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xul files WriteRegStr HKCU "Software\Classes\.xul" "" "phcodeXUL" WriteRegStr HKCU "Software\Classes\phcodeXUL" "" "XUL file" - WriteRegStr HKCU "Software\Classes\phcodeXUL\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .yaml files WriteRegStr HKCU "Software\Classes\.yaml" "" "phcodeYAML" WriteRegStr HKCU "Software\Classes\phcodeYAML" "" "YAML file" - WriteRegStr HKCU "Software\Classes\phcodeYAML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .yml files WriteRegStr HKCU "Software\Classes\.yml" "" "phcodeYML" WriteRegStr HKCU "Software\Classes\phcodeYML" "" "YML file" - WriteRegStr HKCU "Software\Classes\phcodeYML\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ts files WriteRegStr HKCU "Software\Classes\.ts" "" "phcodeTS" WriteRegStr HKCU "Software\Classes\phcodeTS" "" "TS file" - WriteRegStr HKCU "Software\Classes\phcodeTS\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .tsx files WriteRegStr HKCU "Software\Classes\.tsx" "" "phcodeTSX" WriteRegStr HKCU "Software\Classes\phcodeTSX" "" "TSX file" - WriteRegStr HKCU "Software\Classes\phcodeTSX\DefaultIcon" "" "$INSTDIR\${MAINBINARYNAME}.exe,0" - WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' - WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "" "Open with phcode" - WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' +FunctionEnd + +Section Install + SetOutPath $INSTDIR + + !insertmacro CheckIfAppIsRunning + + ; Copy main executable + File "${MAINBINARYSRCPATH}" + + ; Copy resources + {{#each resources_dirs}} + CreateDirectory "$INSTDIR\\{{this}}" + {{/each}} + {{#each resources}} + File /a "/oname={{this.[1]}}" "{{@key}}" + {{/each}} + + ; Copy external binaries + {{#each binaries}} + File /a "/oname={{this}}" "{{@key}}" + {{/each}} + + ; Create uninstaller + WriteUninstaller "$INSTDIR\uninstall.exe" + + ; Save $INSTDIR in registry for future installations + WriteRegStr SHCTX "${MANUPRODUCTKEY}" "" $INSTDIR + + !if "${INSTALLMODE}" == "both" + ; Save install mode to be selected by default for the next installation such as updating + ; or when uninstalling + WriteRegStr SHCTX "${UNINSTKEY}" $MultiUser.InstallMode 1 + !endif + ; Registry information for add/remove programs + WriteRegStr SHCTX "${UNINSTKEY}" "DisplayName" "${PRODUCTNAME}" + WriteRegStr SHCTX "${UNINSTKEY}" "DisplayIcon" "$\"$INSTDIR\${MAINBINARYNAME}.exe$\"" + WriteRegStr SHCTX "${UNINSTKEY}" "DisplayVersion" "${VERSION}" + WriteRegStr SHCTX "${UNINSTKEY}" "Publisher" "${MANUFACTURER}" + WriteRegStr SHCTX "${UNINSTKEY}" "InstallLocation" "$\"$INSTDIR$\"" + WriteRegStr SHCTX "${UNINSTKEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" + WriteRegDWORD SHCTX "${UNINSTKEY}" "NoModify" "1" + WriteRegDWORD SHCTX "${UNINSTKEY}" "NoRepair" "1" + WriteRegDWORD SHCTX "${UNINSTKEY}" "EstimatedSize" "${ESTIMATEDSIZE}" ; Create start menu shortcut (GUI) !insertmacro MUI_STARTMENU_WRITE_BEGIN Application @@ -1210,6 +893,8 @@ Section Install ; Auto close this page for passive mode ${IfThen} $PassiveMode == 1 ${|} SetAutoClose true ${|} + + Call SetupPhcode SectionEnd Function .onInstSuccess @@ -1235,6 +920,187 @@ Function un.onInit !insertmacro MUI_UNGETLANGUAGE FunctionEnd +Function un.CleanPhcode +; NSIS Cleanup Script +DeleteRegKey HKCU "Software\Classes\.asax" +DeleteRegKey HKCU "Software\Classes\phcodeASAX" +DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.ashx" +DeleteRegKey HKCU "Software\Classes\phcodeASHX" +DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.aspx" +DeleteRegKey HKCU "Software\Classes\phcodeASPX" +DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.atom" +DeleteRegKey HKCU "Software\Classes\phcodeATOM" +DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.cf" +DeleteRegKey HKCU "Software\Classes\phcodeCF" +DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.cfc" +DeleteRegKey HKCU "Software\Classes\phcodeCFC" +DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.cfm" +DeleteRegKey HKCU "Software\Classes\phcodeCFM" +DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.cfm1" +DeleteRegKey HKCU "Software\Classes\phcodeCFM1" +DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.clj" +DeleteRegKey HKCU "Software\Classes\phcodeCLJ" +DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.coffee" +DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE" +DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.cshtml" +DeleteRegKey HKCU "Software\Classes\phcodeCSHTML" +DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.cson" +DeleteRegKey HKCU "Software\Classes\phcodeCSON" +DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.css" +DeleteRegKey HKCU "Software\Classes\phcodeCSS" +DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.ctp" +DeleteRegKey HKCU "Software\Classes\phcodeCTP" +DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.dhtml" +DeleteRegKey HKCU "Software\Classes\phcodeDHTML" +DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.diff" +DeleteRegKey HKCU "Software\Classes\phcodeDIFF" +DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.ejs" +DeleteRegKey HKCU "Software\Classes\phcodeEJS" +DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.handlebars" +DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS" +DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.hbs" +DeleteRegKey HKCU "Software\Classes\phcodeHBS" +DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.htm" +DeleteRegKey HKCU "Software\Classes\phcodeHTM" +DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.html" +DeleteRegKey HKCU "Software\Classes\phcodeHTML" +DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.hx" +DeleteRegKey HKCU "Software\Classes\phcodeHX" +DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.js" +DeleteRegKey HKCU "Software\Classes\phcodeJS" +DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.json" +DeleteRegKey HKCU "Software\Classes\phcodeJSON" +DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.jsp" +DeleteRegKey HKCU "Software\Classes\phcodeJSP" +DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.jsx" +DeleteRegKey HKCU "Software\Classes\phcodeJSX" +DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.kit" +DeleteRegKey HKCU "Software\Classes\phcodeKIT" +DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.less" +DeleteRegKey HKCU "Software\Classes\phcodeLESS" +DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.markdown" +DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN" +DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.mathml" +DeleteRegKey HKCU "Software\Classes\phcodeMATHML" +DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.md" +DeleteRegKey HKCU "Software\Classes\phcodeMD" +DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.patch" +DeleteRegKey HKCU "Software\Classes\phcodePATCH" +DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.php" +DeleteRegKey HKCU "Software\Classes\phcodePHP" +DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.php3" +DeleteRegKey HKCU "Software\Classes\phcodePHP3" +DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.php4" +DeleteRegKey HKCU "Software\Classes\phcodePHP4" +DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.php5" +DeleteRegKey HKCU "Software\Classes\phcodePHP5" +DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.phtm" +DeleteRegKey HKCU "Software\Classes\phcodePHTM" +DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.phtml" +DeleteRegKey HKCU "Software\Classes\phcodePHTML" +DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.rdf" +DeleteRegKey HKCU "Software\Classes\phcodeRDF" +DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.rss" +DeleteRegKey HKCU "Software\Classes\phcodeRSS" +DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.sass" +DeleteRegKey HKCU "Software\Classes\phcodeSASS" +DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.scss" +DeleteRegKey HKCU "Software\Classes\phcodeSCSS" +DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.shtm" +DeleteRegKey HKCU "Software\Classes\phcodeSHTM" +DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.shtml" +DeleteRegKey HKCU "Software\Classes\phcodeSHTML" +DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.sql" +DeleteRegKey HKCU "Software\Classes\phcodeSQL" +DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.svg" +DeleteRegKey HKCU "Software\Classes\phcodeSVG" +DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.tpl" +DeleteRegKey HKCU "Software\Classes\phcodeTPL" +DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.twig" +DeleteRegKey HKCU "Software\Classes\phcodeTWIG" +DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.wsgi" +DeleteRegKey HKCU "Software\Classes\phcodeWSGI" +DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.xbl" +DeleteRegKey HKCU "Software\Classes\phcodeXBL" +DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.xht" +DeleteRegKey HKCU "Software\Classes\phcodeXHT" +DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.xhtml" +DeleteRegKey HKCU "Software\Classes\phcodeXHTML" +DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.xml" +DeleteRegKey HKCU "Software\Classes\phcodeXML" +DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.xslt" +DeleteRegKey HKCU "Software\Classes\phcodeXSLT" +DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.xul" +DeleteRegKey HKCU "Software\Classes\phcodeXUL" +DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.yaml" +DeleteRegKey HKCU "Software\Classes\phcodeYAML" +DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.yml" +DeleteRegKey HKCU "Software\Classes\phcodeYML" +DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.ts" +DeleteRegKey HKCU "Software\Classes\phcodeTS" +DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\.tsx" +DeleteRegKey HKCU "Software\Classes\phcodeTSX" +DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\command" +FunctionEnd + Section Uninstall !insertmacro CheckIfAppIsRunning @@ -1263,364 +1129,7 @@ Section Uninstall {{/each}} RMDir "$INSTDIR" ${EndIf} - ; NSIS Cleanup Script - - DeleteRegKey HKCU "Software\Classes\.asax" - DeleteRegKey HKCU "Software\Classes\phcodeASAX" - DeleteRegKey HKCU "Software\Classes\phcodeASAX\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.ashx" - DeleteRegKey HKCU "Software\Classes\phcodeASHX" - DeleteRegKey HKCU "Software\Classes\phcodeASHX\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.aspx" - DeleteRegKey HKCU "Software\Classes\phcodeASPX" - DeleteRegKey HKCU "Software\Classes\phcodeASPX\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.atom" - DeleteRegKey HKCU "Software\Classes\phcodeATOM" - DeleteRegKey HKCU "Software\Classes\phcodeATOM\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.cf" - DeleteRegKey HKCU "Software\Classes\phcodeCF" - DeleteRegKey HKCU "Software\Classes\phcodeCF\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.cfc" - DeleteRegKey HKCU "Software\Classes\phcodeCFC" - DeleteRegKey HKCU "Software\Classes\phcodeCFC\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.cfm" - DeleteRegKey HKCU "Software\Classes\phcodeCFM" - DeleteRegKey HKCU "Software\Classes\phcodeCFM\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.cfm1" - DeleteRegKey HKCU "Software\Classes\phcodeCFM1" - DeleteRegKey HKCU "Software\Classes\phcodeCFM1\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.clj" - DeleteRegKey HKCU "Software\Classes\phcodeCLJ" - DeleteRegKey HKCU "Software\Classes\phcodeCLJ\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.coffee" - DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE" - DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.cshtml" - DeleteRegKey HKCU "Software\Classes\phcodeCSHTML" - DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.cson" - DeleteRegKey HKCU "Software\Classes\phcodeCSON" - DeleteRegKey HKCU "Software\Classes\phcodeCSON\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.css" - DeleteRegKey HKCU "Software\Classes\phcodeCSS" - DeleteRegKey HKCU "Software\Classes\phcodeCSS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.ctp" - DeleteRegKey HKCU "Software\Classes\phcodeCTP" - DeleteRegKey HKCU "Software\Classes\phcodeCTP\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.dhtml" - DeleteRegKey HKCU "Software\Classes\phcodeDHTML" - DeleteRegKey HKCU "Software\Classes\phcodeDHTML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.diff" - DeleteRegKey HKCU "Software\Classes\phcodeDIFF" - DeleteRegKey HKCU "Software\Classes\phcodeDIFF\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.ejs" - DeleteRegKey HKCU "Software\Classes\phcodeEJS" - DeleteRegKey HKCU "Software\Classes\phcodeEJS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.handlebars" - DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS" - DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.hbs" - DeleteRegKey HKCU "Software\Classes\phcodeHBS" - DeleteRegKey HKCU "Software\Classes\phcodeHBS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.htm" - DeleteRegKey HKCU "Software\Classes\phcodeHTM" - DeleteRegKey HKCU "Software\Classes\phcodeHTM\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.html" - DeleteRegKey HKCU "Software\Classes\phcodeHTML" - DeleteRegKey HKCU "Software\Classes\phcodeHTML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.hx" - DeleteRegKey HKCU "Software\Classes\phcodeHX" - DeleteRegKey HKCU "Software\Classes\phcodeHX\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.js" - DeleteRegKey HKCU "Software\Classes\phcodeJS" - DeleteRegKey HKCU "Software\Classes\phcodeJS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.json" - DeleteRegKey HKCU "Software\Classes\phcodeJSON" - DeleteRegKey HKCU "Software\Classes\phcodeJSON\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.jsp" - DeleteRegKey HKCU "Software\Classes\phcodeJSP" - DeleteRegKey HKCU "Software\Classes\phcodeJSP\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.jsx" - DeleteRegKey HKCU "Software\Classes\phcodeJSX" - DeleteRegKey HKCU "Software\Classes\phcodeJSX\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.kit" - DeleteRegKey HKCU "Software\Classes\phcodeKIT" - DeleteRegKey HKCU "Software\Classes\phcodeKIT\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.less" - DeleteRegKey HKCU "Software\Classes\phcodeLESS" - DeleteRegKey HKCU "Software\Classes\phcodeLESS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.markdown" - DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN" - DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.mathml" - DeleteRegKey HKCU "Software\Classes\phcodeMATHML" - DeleteRegKey HKCU "Software\Classes\phcodeMATHML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.md" - DeleteRegKey HKCU "Software\Classes\phcodeMD" - DeleteRegKey HKCU "Software\Classes\phcodeMD\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.patch" - DeleteRegKey HKCU "Software\Classes\phcodePATCH" - DeleteRegKey HKCU "Software\Classes\phcodePATCH\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.php" - DeleteRegKey HKCU "Software\Classes\phcodePHP" - DeleteRegKey HKCU "Software\Classes\phcodePHP\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.php3" - DeleteRegKey HKCU "Software\Classes\phcodePHP3" - DeleteRegKey HKCU "Software\Classes\phcodePHP3\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.php4" - DeleteRegKey HKCU "Software\Classes\phcodePHP4" - DeleteRegKey HKCU "Software\Classes\phcodePHP4\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.php5" - DeleteRegKey HKCU "Software\Classes\phcodePHP5" - DeleteRegKey HKCU "Software\Classes\phcodePHP5\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.phtm" - DeleteRegKey HKCU "Software\Classes\phcodePHTM" - DeleteRegKey HKCU "Software\Classes\phcodePHTM\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.phtml" - DeleteRegKey HKCU "Software\Classes\phcodePHTML" - DeleteRegKey HKCU "Software\Classes\phcodePHTML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.rdf" - DeleteRegKey HKCU "Software\Classes\phcodeRDF" - DeleteRegKey HKCU "Software\Classes\phcodeRDF\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.rss" - DeleteRegKey HKCU "Software\Classes\phcodeRSS" - DeleteRegKey HKCU "Software\Classes\phcodeRSS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.sass" - DeleteRegKey HKCU "Software\Classes\phcodeSASS" - DeleteRegKey HKCU "Software\Classes\phcodeSASS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.scss" - DeleteRegKey HKCU "Software\Classes\phcodeSCSS" - DeleteRegKey HKCU "Software\Classes\phcodeSCSS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.shtm" - DeleteRegKey HKCU "Software\Classes\phcodeSHTM" - DeleteRegKey HKCU "Software\Classes\phcodeSHTM\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.shtml" - DeleteRegKey HKCU "Software\Classes\phcodeSHTML" - DeleteRegKey HKCU "Software\Classes\phcodeSHTML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.sql" - DeleteRegKey HKCU "Software\Classes\phcodeSQL" - DeleteRegKey HKCU "Software\Classes\phcodeSQL\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.svg" - DeleteRegKey HKCU "Software\Classes\phcodeSVG" - DeleteRegKey HKCU "Software\Classes\phcodeSVG\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.tpl" - DeleteRegKey HKCU "Software\Classes\phcodeTPL" - DeleteRegKey HKCU "Software\Classes\phcodeTPL\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.twig" - DeleteRegKey HKCU "Software\Classes\phcodeTWIG" - DeleteRegKey HKCU "Software\Classes\phcodeTWIG\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.wsgi" - DeleteRegKey HKCU "Software\Classes\phcodeWSGI" - DeleteRegKey HKCU "Software\Classes\phcodeWSGI\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.xbl" - DeleteRegKey HKCU "Software\Classes\phcodeXBL" - DeleteRegKey HKCU "Software\Classes\phcodeXBL\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.xht" - DeleteRegKey HKCU "Software\Classes\phcodeXHT" - DeleteRegKey HKCU "Software\Classes\phcodeXHT\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.xhtml" - DeleteRegKey HKCU "Software\Classes\phcodeXHTML" - DeleteRegKey HKCU "Software\Classes\phcodeXHTML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.xml" - DeleteRegKey HKCU "Software\Classes\phcodeXML" - DeleteRegKey HKCU "Software\Classes\phcodeXML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.xslt" - DeleteRegKey HKCU "Software\Classes\phcodeXSLT" - DeleteRegKey HKCU "Software\Classes\phcodeXSLT\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.xul" - DeleteRegKey HKCU "Software\Classes\phcodeXUL" - DeleteRegKey HKCU "Software\Classes\phcodeXUL\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.yaml" - DeleteRegKey HKCU "Software\Classes\phcodeYAML" - DeleteRegKey HKCU "Software\Classes\phcodeYAML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.yml" - DeleteRegKey HKCU "Software\Classes\phcodeYML" - DeleteRegKey HKCU "Software\Classes\phcodeYML\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.ts" - DeleteRegKey HKCU "Software\Classes\phcodeTS" - DeleteRegKey HKCU "Software\Classes\phcodeTS\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode\command" - DeleteRegKey HKCU "Software\Classes\.tsx" - DeleteRegKey HKCU "Software\Classes\phcodeTSX" - DeleteRegKey HKCU "Software\Classes\phcodeTSX\DefaultIcon" - DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode" - DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode\command" - - ; Remove start menu shortcut + Call un.CleanPhcode !insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder Delete "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" RMDir "$SMPROGRAMS\$AppStartMenuFolder" @@ -1670,4 +1179,4 @@ Function CreateStartMenuShortcut CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder" CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" ApplicationID::Set "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "${BUNDLEID}" -FunctionEnd +FunctionEnd \ No newline at end of file From a0002ae8bec6bfae23c9030bcfb822bb6a5e1c57 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 18 Jan 2024 18:10:50 +0530 Subject: [PATCH 243/864] chore: code clean up --- .../src/bundle/windows/nsis/installer.nsi | 356 +++++++++--------- 1 file changed, 178 insertions(+), 178 deletions(-) diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi index e20e243a..43c5d54c 100644 --- a/src-tauri/src/bundle/windows/nsis/installer.nsi +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -921,184 +921,184 @@ Function un.onInit FunctionEnd Function un.CleanPhcode -; NSIS Cleanup Script -DeleteRegKey HKCU "Software\Classes\.asax" -DeleteRegKey HKCU "Software\Classes\phcodeASAX" -DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.ashx" -DeleteRegKey HKCU "Software\Classes\phcodeASHX" -DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.aspx" -DeleteRegKey HKCU "Software\Classes\phcodeASPX" -DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.atom" -DeleteRegKey HKCU "Software\Classes\phcodeATOM" -DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.cf" -DeleteRegKey HKCU "Software\Classes\phcodeCF" -DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.cfc" -DeleteRegKey HKCU "Software\Classes\phcodeCFC" -DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.cfm" -DeleteRegKey HKCU "Software\Classes\phcodeCFM" -DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.cfm1" -DeleteRegKey HKCU "Software\Classes\phcodeCFM1" -DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.clj" -DeleteRegKey HKCU "Software\Classes\phcodeCLJ" -DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.coffee" -DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE" -DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.cshtml" -DeleteRegKey HKCU "Software\Classes\phcodeCSHTML" -DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.cson" -DeleteRegKey HKCU "Software\Classes\phcodeCSON" -DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.css" -DeleteRegKey HKCU "Software\Classes\phcodeCSS" -DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.ctp" -DeleteRegKey HKCU "Software\Classes\phcodeCTP" -DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.dhtml" -DeleteRegKey HKCU "Software\Classes\phcodeDHTML" -DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.diff" -DeleteRegKey HKCU "Software\Classes\phcodeDIFF" -DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.ejs" -DeleteRegKey HKCU "Software\Classes\phcodeEJS" -DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.handlebars" -DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS" -DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.hbs" -DeleteRegKey HKCU "Software\Classes\phcodeHBS" -DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.htm" -DeleteRegKey HKCU "Software\Classes\phcodeHTM" -DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.html" -DeleteRegKey HKCU "Software\Classes\phcodeHTML" -DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.hx" -DeleteRegKey HKCU "Software\Classes\phcodeHX" -DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.js" -DeleteRegKey HKCU "Software\Classes\phcodeJS" -DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.json" -DeleteRegKey HKCU "Software\Classes\phcodeJSON" -DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.jsp" -DeleteRegKey HKCU "Software\Classes\phcodeJSP" -DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.jsx" -DeleteRegKey HKCU "Software\Classes\phcodeJSX" -DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.kit" -DeleteRegKey HKCU "Software\Classes\phcodeKIT" -DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.less" -DeleteRegKey HKCU "Software\Classes\phcodeLESS" -DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.markdown" -DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN" -DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.mathml" -DeleteRegKey HKCU "Software\Classes\phcodeMATHML" -DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.md" -DeleteRegKey HKCU "Software\Classes\phcodeMD" -DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.patch" -DeleteRegKey HKCU "Software\Classes\phcodePATCH" -DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.php" -DeleteRegKey HKCU "Software\Classes\phcodePHP" -DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.php3" -DeleteRegKey HKCU "Software\Classes\phcodePHP3" -DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.php4" -DeleteRegKey HKCU "Software\Classes\phcodePHP4" -DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.php5" -DeleteRegKey HKCU "Software\Classes\phcodePHP5" -DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.phtm" -DeleteRegKey HKCU "Software\Classes\phcodePHTM" -DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.phtml" -DeleteRegKey HKCU "Software\Classes\phcodePHTML" -DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.rdf" -DeleteRegKey HKCU "Software\Classes\phcodeRDF" -DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.rss" -DeleteRegKey HKCU "Software\Classes\phcodeRSS" -DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.sass" -DeleteRegKey HKCU "Software\Classes\phcodeSASS" -DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.scss" -DeleteRegKey HKCU "Software\Classes\phcodeSCSS" -DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.shtm" -DeleteRegKey HKCU "Software\Classes\phcodeSHTM" -DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.shtml" -DeleteRegKey HKCU "Software\Classes\phcodeSHTML" -DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.sql" -DeleteRegKey HKCU "Software\Classes\phcodeSQL" -DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.svg" -DeleteRegKey HKCU "Software\Classes\phcodeSVG" -DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.tpl" -DeleteRegKey HKCU "Software\Classes\phcodeTPL" -DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.twig" -DeleteRegKey HKCU "Software\Classes\phcodeTWIG" -DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.wsgi" -DeleteRegKey HKCU "Software\Classes\phcodeWSGI" -DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.xbl" -DeleteRegKey HKCU "Software\Classes\phcodeXBL" -DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.xht" -DeleteRegKey HKCU "Software\Classes\phcodeXHT" -DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.xhtml" -DeleteRegKey HKCU "Software\Classes\phcodeXHTML" -DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.xml" -DeleteRegKey HKCU "Software\Classes\phcodeXML" -DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.xslt" -DeleteRegKey HKCU "Software\Classes\phcodeXSLT" -DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.xul" -DeleteRegKey HKCU "Software\Classes\phcodeXUL" -DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.yaml" -DeleteRegKey HKCU "Software\Classes\phcodeYAML" -DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.yml" -DeleteRegKey HKCU "Software\Classes\phcodeYML" -DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.ts" -DeleteRegKey HKCU "Software\Classes\phcodeTS" -DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\.tsx" -DeleteRegKey HKCU "Software\Classes\phcodeTSX" -DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\command" + ; NSIS Cleanup Script + DeleteRegKey HKCU "Software\Classes\.asax" + DeleteRegKey HKCU "Software\Classes\phcodeASAX" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.ashx" + DeleteRegKey HKCU "Software\Classes\phcodeASHX" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.aspx" + DeleteRegKey HKCU "Software\Classes\phcodeASPX" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.atom" + DeleteRegKey HKCU "Software\Classes\phcodeATOM" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.cf" + DeleteRegKey HKCU "Software\Classes\phcodeCF" + DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.cfc" + DeleteRegKey HKCU "Software\Classes\phcodeCFC" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.cfm" + DeleteRegKey HKCU "Software\Classes\phcodeCFM" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.cfm1" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.clj" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.coffee" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.cshtml" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.cson" + DeleteRegKey HKCU "Software\Classes\phcodeCSON" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.css" + DeleteRegKey HKCU "Software\Classes\phcodeCSS" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.ctp" + DeleteRegKey HKCU "Software\Classes\phcodeCTP" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.dhtml" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.diff" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.ejs" + DeleteRegKey HKCU "Software\Classes\phcodeEJS" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.handlebars" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.hbs" + DeleteRegKey HKCU "Software\Classes\phcodeHBS" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.htm" + DeleteRegKey HKCU "Software\Classes\phcodeHTM" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.html" + DeleteRegKey HKCU "Software\Classes\phcodeHTML" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.hx" + DeleteRegKey HKCU "Software\Classes\phcodeHX" + DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.js" + DeleteRegKey HKCU "Software\Classes\phcodeJS" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.json" + DeleteRegKey HKCU "Software\Classes\phcodeJSON" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.jsp" + DeleteRegKey HKCU "Software\Classes\phcodeJSP" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.jsx" + DeleteRegKey HKCU "Software\Classes\phcodeJSX" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.kit" + DeleteRegKey HKCU "Software\Classes\phcodeKIT" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.less" + DeleteRegKey HKCU "Software\Classes\phcodeLESS" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.markdown" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.mathml" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.md" + DeleteRegKey HKCU "Software\Classes\phcodeMD" + DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.patch" + DeleteRegKey HKCU "Software\Classes\phcodePATCH" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.php" + DeleteRegKey HKCU "Software\Classes\phcodePHP" + DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.php3" + DeleteRegKey HKCU "Software\Classes\phcodePHP3" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.php4" + DeleteRegKey HKCU "Software\Classes\phcodePHP4" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.php5" + DeleteRegKey HKCU "Software\Classes\phcodePHP5" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.phtm" + DeleteRegKey HKCU "Software\Classes\phcodePHTM" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.phtml" + DeleteRegKey HKCU "Software\Classes\phcodePHTML" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.rdf" + DeleteRegKey HKCU "Software\Classes\phcodeRDF" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.rss" + DeleteRegKey HKCU "Software\Classes\phcodeRSS" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.sass" + DeleteRegKey HKCU "Software\Classes\phcodeSASS" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.scss" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.shtm" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.shtml" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.sql" + DeleteRegKey HKCU "Software\Classes\phcodeSQL" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.svg" + DeleteRegKey HKCU "Software\Classes\phcodeSVG" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.tpl" + DeleteRegKey HKCU "Software\Classes\phcodeTPL" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.twig" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.wsgi" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.xbl" + DeleteRegKey HKCU "Software\Classes\phcodeXBL" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.xht" + DeleteRegKey HKCU "Software\Classes\phcodeXHT" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.xhtml" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.xml" + DeleteRegKey HKCU "Software\Classes\phcodeXML" + DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.xslt" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.xul" + DeleteRegKey HKCU "Software\Classes\phcodeXUL" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.yaml" + DeleteRegKey HKCU "Software\Classes\phcodeYAML" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.yml" + DeleteRegKey HKCU "Software\Classes\phcodeYML" + DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.ts" + DeleteRegKey HKCU "Software\Classes\phcodeTS" + DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\.tsx" + DeleteRegKey HKCU "Software\Classes\phcodeTSX" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\command" FunctionEnd Section Uninstall From 77182c8e827afda464d9f48b4c5a42e9c9a5b37e Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 18 Jan 2024 12:54:46 +0000 Subject: [PATCH 244/864] ci: update phcode version to 3.2.19 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 4955d5f4..7877ffa3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.18", + "version": "3.2.19", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "b4e9306238b73cbb142dbbe08d7c23c4536af8cb" + "commit": "a230298b5846dc4304f0662622e1d96ee1ab9b26" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9e2d0dc0..9bb9ad5b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.18" +version = "3.2.19" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index b228b0e1..990b803f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.18" + "version": "3.2.19" }, "tauri": { "allowlist": { @@ -146,7 +146,7 @@ "nsis": { "displayLanguageSelector": true, "license": "./license/agpl", - "template" : "./src/bundle/windows/nsis/installer.nsi", + "template": "./src/bundle/windows/nsis/installer.nsi", "languages": [ "English", "Afrikaans", @@ -332,4 +332,4 @@ } ] } -} +} \ No newline at end of file From 55ef9fa703d5ddaa48850819c21d9b2ce8809769 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 19 Jan 2024 11:23:45 +0530 Subject: [PATCH 245/864] feat: only a single instance of phoenix, multiple windows from that instance --- package-lock.json | 4 +-- src-tauri/Cargo.lock | 21 +++++++++++-- src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 15 +++++++-- src-tauri/tauri.conf.json | 64 +++++++++++++++++++++++++++++++++++++-- 5 files changed, 96 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index dec2a090..fe2e9fea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.2.17", + "version": "3.2.19", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.17", + "version": "3.2.19", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.9", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9f886035..44d532a6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2680,7 +2680,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.18" +version = "3.2.19" dependencies = [ "clipboard-files", "fix-path-env", @@ -2694,6 +2694,7 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-fs-extra", + "tauri-plugin-single-instance", "tauri-plugin-window-state", "webkit2gtk", "winapi", @@ -3841,7 +3842,7 @@ dependencies = [ [[package]] name = "tauri-plugin-fs-extra" version = "0.0.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#ad5ec05e2639b33f0475a0eefa8684bfa4b92be8" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#cf0090029888efc6a1f4d178cec773e6cd4c5b69" dependencies = [ "log", "serde", @@ -3850,10 +3851,24 @@ dependencies = [ "thiserror", ] +[[package]] +name = "tauri-plugin-single-instance" +version = "0.0.0" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#cf0090029888efc6a1f4d178cec773e6cd4c5b69" +dependencies = [ + "log", + "serde", + "serde_json", + "tauri", + "thiserror", + "windows-sys 0.52.0", + "zbus", +] + [[package]] name = "tauri-plugin-window-state" version = "0.1.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#ad5ec05e2639b33f0475a0eefa8684bfa4b92be8" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#cf0090029888efc6a1f4d178cec773e6cd4c5b69" dependencies = [ "bincode", "bitflags 2.4.1", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9bb9ad5b..81edbc05 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -24,6 +24,7 @@ tauri = { version = "1.5.4", features = [ "cli", "api-all", "updater", "devtools winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } +tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } [target.'cfg(target_os = "linux")'.dependencies] diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index a729d84f..11dd7cc8 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,8 +3,8 @@ all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows" )] use std::env; -#[cfg(target_os = "linux")] -use tauri::Manager; // needed for the f10 key fix for now in linux only + +use tauri::{Manager}; #[cfg(target_os = "linux")] use std::fs::metadata; @@ -33,6 +33,12 @@ mod boot_config; mod platform; +#[derive(Clone, serde::Serialize)] +struct Payload { + args: Vec, + cwd: String, +} + // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command #[tauri::command] fn console_log(_handle: tauri::AppHandle, message: &str) { @@ -226,6 +232,11 @@ fn main() { }) .plugin(tauri_plugin_fs_extra::init()) .plugin(tauri_plugin_window_state::Builder::default().build()) + .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { + println!("{}, {argv:?}, {cwd}", app.package_info().name); + + app.emit_all("single-instance", Payload { args: argv, cwd }).unwrap(); + })) .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ toggle_devtools, console_log, console_error, _get_commandline_args, diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 990b803f..6d96994c 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -261,7 +261,37 @@ "phcode-27", "phcode-28", "phcode-29", - "phcode-30" + "phcode-30", + "extn-1", + "extn-2", + "extn-3", + "extn-4", + "extn-5", + "extn-6", + "extn-7", + "extn-8", + "extn-9", + "extn-10", + "extn-11", + "extn-12", + "extn-13", + "extn-14", + "extn-15", + "extn-16", + "extn-17", + "extn-18", + "extn-19", + "extn-20", + "extn-21", + "extn-22", + "extn-23", + "extn-24", + "extn-25", + "extn-26", + "extn-27", + "extn-28", + "extn-29", + "extn-30" ] }, { @@ -302,7 +332,37 @@ "phcode-27", "phcode-28", "phcode-29", - "phcode-30" + "phcode-30", + "extn-1", + "extn-2", + "extn-3", + "extn-4", + "extn-5", + "extn-6", + "extn-7", + "extn-8", + "extn-9", + "extn-10", + "extn-11", + "extn-12", + "extn-13", + "extn-14", + "extn-15", + "extn-16", + "extn-17", + "extn-18", + "extn-19", + "extn-20", + "extn-21", + "extn-22", + "extn-23", + "extn-24", + "extn-25", + "extn-26", + "extn-27", + "extn-28", + "extn-29", + "extn-30" ] } ] From ea62af47983aad5ac8e6db9edf2c5e1c7afb3ab2 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 18 Jan 2024 23:02:39 +0530 Subject: [PATCH 246/864] feat: adding contex menu for files --- .../src/bundle/windows/nsis/installer.nsi | 890 ++++++++++++++---- 1 file changed, 712 insertions(+), 178 deletions(-) diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi index 43c5d54c..1826e015 100644 --- a/src-tauri/src/bundle/windows/nsis/installer.nsi +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -533,300 +533,597 @@ SectionEnd Function SetupPhcode + ; Set file association and context menu for .asax files WriteRegStr HKCU "Software\Classes\.asax" "" "phcodeASAX" WriteRegStr HKCU "Software\Classes\phcodeASAX" "" "ASAX file" WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ashx files WriteRegStr HKCU "Software\Classes\.ashx" "" "phcodeASHX" WriteRegStr HKCU "Software\Classes\phcodeASHX" "" "ASHX file" WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .aspx files WriteRegStr HKCU "Software\Classes\.aspx" "" "phcodeASPX" WriteRegStr HKCU "Software\Classes\phcodeASPX" "" "ASPX file" WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .atom files WriteRegStr HKCU "Software\Classes\.atom" "" "phcodeATOM" WriteRegStr HKCU "Software\Classes\phcodeATOM" "" "ATOM file" WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cf files WriteRegStr HKCU "Software\Classes\.cf" "" "phcodeCF" WriteRegStr HKCU "Software\Classes\phcodeCF" "" "CF file" WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfc files WriteRegStr HKCU "Software\Classes\.cfc" "" "phcodeCFC" WriteRegStr HKCU "Software\Classes\phcodeCFC" "" "CFC file" WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfm files WriteRegStr HKCU "Software\Classes\.cfm" "" "phcodeCFM" WriteRegStr HKCU "Software\Classes\phcodeCFM" "" "CFM file" WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfm1 files WriteRegStr HKCU "Software\Classes\.cfm1" "" "phcodeCFM1" WriteRegStr HKCU "Software\Classes\phcodeCFM1" "" "CFM1 file" WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .clj files WriteRegStr HKCU "Software\Classes\.clj" "" "phcodeCLJ" WriteRegStr HKCU "Software\Classes\phcodeCLJ" "" "CLJ file" WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .coffee files WriteRegStr HKCU "Software\Classes\.coffee" "" "phcodeCOFFEE" WriteRegStr HKCU "Software\Classes\phcodeCOFFEE" "" "COFFEE file" WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cshtml files WriteRegStr HKCU "Software\Classes\.cshtml" "" "phcodeCSHTML" WriteRegStr HKCU "Software\Classes\phcodeCSHTML" "" "CSHTML file" WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cson files WriteRegStr HKCU "Software\Classes\.cson" "" "phcodeCSON" WriteRegStr HKCU "Software\Classes\phcodeCSON" "" "CSON file" WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .css files WriteRegStr HKCU "Software\Classes\.css" "" "phcodeCSS" WriteRegStr HKCU "Software\Classes\phcodeCSS" "" "CSS file" WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ctp files WriteRegStr HKCU "Software\Classes\.ctp" "" "phcodeCTP" WriteRegStr HKCU "Software\Classes\phcodeCTP" "" "CTP file" WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .dhtml files WriteRegStr HKCU "Software\Classes\.dhtml" "" "phcodeDHTML" WriteRegStr HKCU "Software\Classes\phcodeDHTML" "" "DHTML file" WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .diff files WriteRegStr HKCU "Software\Classes\.diff" "" "phcodeDIFF" WriteRegStr HKCU "Software\Classes\phcodeDIFF" "" "DIFF file" WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ejs files WriteRegStr HKCU "Software\Classes\.ejs" "" "phcodeEJS" WriteRegStr HKCU "Software\Classes\phcodeEJS" "" "EJS file" WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .handlebars files WriteRegStr HKCU "Software\Classes\.handlebars" "" "phcodeHANDLEBARS" WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS" "" "HANDLEBARS file" WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .hbs files WriteRegStr HKCU "Software\Classes\.hbs" "" "phcodeHBS" WriteRegStr HKCU "Software\Classes\phcodeHBS" "" "HBS file" WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .htm files WriteRegStr HKCU "Software\Classes\.htm" "" "phcodeHTM" WriteRegStr HKCU "Software\Classes\phcodeHTM" "" "HTM file" WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .html files WriteRegStr HKCU "Software\Classes\.html" "" "phcodeHTML" WriteRegStr HKCU "Software\Classes\phcodeHTML" "" "HTML file" WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .hx files WriteRegStr HKCU "Software\Classes\.hx" "" "phcodeHX" WriteRegStr HKCU "Software\Classes\phcodeHX" "" "HX file" WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .js files WriteRegStr HKCU "Software\Classes\.js" "" "phcodeJS" WriteRegStr HKCU "Software\Classes\phcodeJS" "" "JS file" WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .json files WriteRegStr HKCU "Software\Classes\.json" "" "phcodeJSON" WriteRegStr HKCU "Software\Classes\phcodeJSON" "" "JSON file" WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .jsp files WriteRegStr HKCU "Software\Classes\.jsp" "" "phcodeJSP" WriteRegStr HKCU "Software\Classes\phcodeJSP" "" "JSP file" WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .jsx files WriteRegStr HKCU "Software\Classes\.jsx" "" "phcodeJSX" WriteRegStr HKCU "Software\Classes\phcodeJSX" "" "JSX file" WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .kit files WriteRegStr HKCU "Software\Classes\.kit" "" "phcodeKIT" WriteRegStr HKCU "Software\Classes\phcodeKIT" "" "KIT file" WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .less files WriteRegStr HKCU "Software\Classes\.less" "" "phcodeLESS" WriteRegStr HKCU "Software\Classes\phcodeLESS" "" "LESS file" WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .markdown files WriteRegStr HKCU "Software\Classes\.markdown" "" "phcodeMARKDOWN" WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN" "" "MARKDOWN file" WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .mathml files WriteRegStr HKCU "Software\Classes\.mathml" "" "phcodeMATHML" WriteRegStr HKCU "Software\Classes\phcodeMATHML" "" "MATHML file" WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .md files WriteRegStr HKCU "Software\Classes\.md" "" "phcodeMD" WriteRegStr HKCU "Software\Classes\phcodeMD" "" "MD file" WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .patch files WriteRegStr HKCU "Software\Classes\.patch" "" "phcodePATCH" WriteRegStr HKCU "Software\Classes\phcodePATCH" "" "PATCH file" WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php files WriteRegStr HKCU "Software\Classes\.php" "" "phcodePHP" WriteRegStr HKCU "Software\Classes\phcodePHP" "" "PHP file" WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php3 files WriteRegStr HKCU "Software\Classes\.php3" "" "phcodePHP3" WriteRegStr HKCU "Software\Classes\phcodePHP3" "" "PHP3 file" WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php4 files WriteRegStr HKCU "Software\Classes\.php4" "" "phcodePHP4" WriteRegStr HKCU "Software\Classes\phcodePHP4" "" "PHP4 file" WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php5 files WriteRegStr HKCU "Software\Classes\.php5" "" "phcodePHP5" WriteRegStr HKCU "Software\Classes\phcodePHP5" "" "PHP5 file" WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .phtm files WriteRegStr HKCU "Software\Classes\.phtm" "" "phcodePHTM" WriteRegStr HKCU "Software\Classes\phcodePHTM" "" "PHTM file" WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .phtml files WriteRegStr HKCU "Software\Classes\.phtml" "" "phcodePHTML" WriteRegStr HKCU "Software\Classes\phcodePHTML" "" "PHTML file" WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .rdf files WriteRegStr HKCU "Software\Classes\.rdf" "" "phcodeRDF" WriteRegStr HKCU "Software\Classes\phcodeRDF" "" "RDF file" WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .rss files WriteRegStr HKCU "Software\Classes\.rss" "" "phcodeRSS" WriteRegStr HKCU "Software\Classes\phcodeRSS" "" "RSS file" WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .sass files WriteRegStr HKCU "Software\Classes\.sass" "" "phcodeSASS" WriteRegStr HKCU "Software\Classes\phcodeSASS" "" "SASS file" WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .scss files WriteRegStr HKCU "Software\Classes\.scss" "" "phcodeSCSS" WriteRegStr HKCU "Software\Classes\phcodeSCSS" "" "SCSS file" WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .shtm files WriteRegStr HKCU "Software\Classes\.shtm" "" "phcodeSHTM" WriteRegStr HKCU "Software\Classes\phcodeSHTM" "" "SHTM file" WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .shtml files WriteRegStr HKCU "Software\Classes\.shtml" "" "phcodeSHTML" WriteRegStr HKCU "Software\Classes\phcodeSHTML" "" "SHTML file" WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .sql files WriteRegStr HKCU "Software\Classes\.sql" "" "phcodeSQL" WriteRegStr HKCU "Software\Classes\phcodeSQL" "" "SQL file" WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .svg files WriteRegStr HKCU "Software\Classes\.svg" "" "phcodeSVG" WriteRegStr HKCU "Software\Classes\phcodeSVG" "" "SVG file" WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .tpl files WriteRegStr HKCU "Software\Classes\.tpl" "" "phcodeTPL" WriteRegStr HKCU "Software\Classes\phcodeTPL" "" "TPL file" WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .twig files WriteRegStr HKCU "Software\Classes\.twig" "" "phcodeTWIG" WriteRegStr HKCU "Software\Classes\phcodeTWIG" "" "TWIG file" WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .wsgi files WriteRegStr HKCU "Software\Classes\.wsgi" "" "phcodeWSGI" WriteRegStr HKCU "Software\Classes\phcodeWSGI" "" "WSGI file" WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xbl files WriteRegStr HKCU "Software\Classes\.xbl" "" "phcodeXBL" WriteRegStr HKCU "Software\Classes\phcodeXBL" "" "XBL file" WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xht files WriteRegStr HKCU "Software\Classes\.xht" "" "phcodeXHT" WriteRegStr HKCU "Software\Classes\phcodeXHT" "" "XHT file" WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xhtml files WriteRegStr HKCU "Software\Classes\.xhtml" "" "phcodeXHTML" WriteRegStr HKCU "Software\Classes\phcodeXHTML" "" "XHTML file" WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xml files WriteRegStr HKCU "Software\Classes\.xml" "" "phcodeXML" WriteRegStr HKCU "Software\Classes\phcodeXML" "" "XML file" WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xslt files WriteRegStr HKCU "Software\Classes\.xslt" "" "phcodeXSLT" WriteRegStr HKCU "Software\Classes\phcodeXSLT" "" "XSLT file" WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xul files WriteRegStr HKCU "Software\Classes\.xul" "" "phcodeXUL" WriteRegStr HKCU "Software\Classes\phcodeXUL" "" "XUL file" WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .yaml files WriteRegStr HKCU "Software\Classes\.yaml" "" "phcodeYAML" WriteRegStr HKCU "Software\Classes\phcodeYAML" "" "YAML file" WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .yml files WriteRegStr HKCU "Software\Classes\.yml" "" "phcodeYML" WriteRegStr HKCU "Software\Classes\phcodeYML" "" "YML file" WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ts files WriteRegStr HKCU "Software\Classes\.ts" "" "phcodeTS" WriteRegStr HKCU "Software\Classes\phcodeTS" "" "TS file" WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .tsx files WriteRegStr HKCU "Software\Classes\.tsx" "" "phcodeTSX" WriteRegStr HKCU "Software\Classes\phcodeTSX" "" "TSX file" WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + FunctionEnd Section Install @@ -921,184 +1218,421 @@ Function un.onInit FunctionEnd Function un.CleanPhcode - ; NSIS Cleanup Script - DeleteRegKey HKCU "Software\Classes\.asax" - DeleteRegKey HKCU "Software\Classes\phcodeASAX" - DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.ashx" - DeleteRegKey HKCU "Software\Classes\phcodeASHX" - DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.aspx" - DeleteRegKey HKCU "Software\Classes\phcodeASPX" - DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.atom" - DeleteRegKey HKCU "Software\Classes\phcodeATOM" - DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.cf" - DeleteRegKey HKCU "Software\Classes\phcodeCF" - DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.cfc" - DeleteRegKey HKCU "Software\Classes\phcodeCFC" - DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.cfm" - DeleteRegKey HKCU "Software\Classes\phcodeCFM" - DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.cfm1" - DeleteRegKey HKCU "Software\Classes\phcodeCFM1" - DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.clj" - DeleteRegKey HKCU "Software\Classes\phcodeCLJ" - DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.coffee" - DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE" - DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.cshtml" - DeleteRegKey HKCU "Software\Classes\phcodeCSHTML" - DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.cson" - DeleteRegKey HKCU "Software\Classes\phcodeCSON" - DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.css" - DeleteRegKey HKCU "Software\Classes\phcodeCSS" - DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.ctp" - DeleteRegKey HKCU "Software\Classes\phcodeCTP" - DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.dhtml" - DeleteRegKey HKCU "Software\Classes\phcodeDHTML" - DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.diff" - DeleteRegKey HKCU "Software\Classes\phcodeDIFF" - DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.ejs" - DeleteRegKey HKCU "Software\Classes\phcodeEJS" - DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.handlebars" - DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS" - DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.hbs" - DeleteRegKey HKCU "Software\Classes\phcodeHBS" - DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.htm" - DeleteRegKey HKCU "Software\Classes\phcodeHTM" - DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.html" - DeleteRegKey HKCU "Software\Classes\phcodeHTML" - DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.hx" - DeleteRegKey HKCU "Software\Classes\phcodeHX" - DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.js" - DeleteRegKey HKCU "Software\Classes\phcodeJS" - DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.json" - DeleteRegKey HKCU "Software\Classes\phcodeJSON" - DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.jsp" - DeleteRegKey HKCU "Software\Classes\phcodeJSP" - DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.jsx" - DeleteRegKey HKCU "Software\Classes\phcodeJSX" - DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.kit" - DeleteRegKey HKCU "Software\Classes\phcodeKIT" - DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.less" - DeleteRegKey HKCU "Software\Classes\phcodeLESS" - DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.markdown" - DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN" - DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.mathml" - DeleteRegKey HKCU "Software\Classes\phcodeMATHML" - DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.md" - DeleteRegKey HKCU "Software\Classes\phcodeMD" - DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.patch" - DeleteRegKey HKCU "Software\Classes\phcodePATCH" - DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.php" - DeleteRegKey HKCU "Software\Classes\phcodePHP" - DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.php3" - DeleteRegKey HKCU "Software\Classes\phcodePHP3" - DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.php4" - DeleteRegKey HKCU "Software\Classes\phcodePHP4" - DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.php5" - DeleteRegKey HKCU "Software\Classes\phcodePHP5" - DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.phtm" - DeleteRegKey HKCU "Software\Classes\phcodePHTM" - DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.phtml" - DeleteRegKey HKCU "Software\Classes\phcodePHTML" - DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.rdf" - DeleteRegKey HKCU "Software\Classes\phcodeRDF" - DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.rss" - DeleteRegKey HKCU "Software\Classes\phcodeRSS" - DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.sass" - DeleteRegKey HKCU "Software\Classes\phcodeSASS" - DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.scss" - DeleteRegKey HKCU "Software\Classes\phcodeSCSS" - DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.shtm" - DeleteRegKey HKCU "Software\Classes\phcodeSHTM" - DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.shtml" - DeleteRegKey HKCU "Software\Classes\phcodeSHTML" - DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.sql" - DeleteRegKey HKCU "Software\Classes\phcodeSQL" - DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.svg" - DeleteRegKey HKCU "Software\Classes\phcodeSVG" - DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.tpl" - DeleteRegKey HKCU "Software\Classes\phcodeTPL" - DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.twig" - DeleteRegKey HKCU "Software\Classes\phcodeTWIG" - DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.wsgi" - DeleteRegKey HKCU "Software\Classes\phcodeWSGI" - DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.xbl" - DeleteRegKey HKCU "Software\Classes\phcodeXBL" - DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.xht" - DeleteRegKey HKCU "Software\Classes\phcodeXHT" - DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.xhtml" - DeleteRegKey HKCU "Software\Classes\phcodeXHTML" - DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.xml" - DeleteRegKey HKCU "Software\Classes\phcodeXML" - DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.xslt" - DeleteRegKey HKCU "Software\Classes\phcodeXSLT" - DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.xul" - DeleteRegKey HKCU "Software\Classes\phcodeXUL" - DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.yaml" - DeleteRegKey HKCU "Software\Classes\phcodeYAML" - DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.yml" - DeleteRegKey HKCU "Software\Classes\phcodeYML" - DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.ts" - DeleteRegKey HKCU "Software\Classes\phcodeTS" - DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\command" - DeleteRegKey HKCU "Software\Classes\.tsx" - DeleteRegKey HKCU "Software\Classes\phcodeTSX" - DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\command" +; NSIS Cleanup Script + +DeleteRegKey HKCU "Software\Classes\.asax" +DeleteRegKey HKCU "Software\Classes\phcodeASAX" +DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.ashx" +DeleteRegKey HKCU "Software\Classes\phcodeASHX" +DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.aspx" +DeleteRegKey HKCU "Software\Classes\phcodeASPX" +DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.atom" +DeleteRegKey HKCU "Software\Classes\phcodeATOM" +DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.cf" +DeleteRegKey HKCU "Software\Classes\phcodeCF" +DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.cfc" +DeleteRegKey HKCU "Software\Classes\phcodeCFC" +DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.cfm" +DeleteRegKey HKCU "Software\Classes\phcodeCFM" +DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.cfm1" +DeleteRegKey HKCU "Software\Classes\phcodeCFM1" +DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.clj" +DeleteRegKey HKCU "Software\Classes\phcodeCLJ" +DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.coffee" +DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE" +DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.cshtml" +DeleteRegKey HKCU "Software\Classes\phcodeCSHTML" +DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.cson" +DeleteRegKey HKCU "Software\Classes\phcodeCSON" +DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.css" +DeleteRegKey HKCU "Software\Classes\phcodeCSS" +DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.ctp" +DeleteRegKey HKCU "Software\Classes\phcodeCTP" +DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.dhtml" +DeleteRegKey HKCU "Software\Classes\phcodeDHTML" +DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.diff" +DeleteRegKey HKCU "Software\Classes\phcodeDIFF" +DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.ejs" +DeleteRegKey HKCU "Software\Classes\phcodeEJS" +DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.handlebars" +DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS" +DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.hbs" +DeleteRegKey HKCU "Software\Classes\phcodeHBS" +DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.htm" +DeleteRegKey HKCU "Software\Classes\phcodeHTM" +DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.html" +DeleteRegKey HKCU "Software\Classes\phcodeHTML" +DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.hx" +DeleteRegKey HKCU "Software\Classes\phcodeHX" +DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.js" +DeleteRegKey HKCU "Software\Classes\phcodeJS" +DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.json" +DeleteRegKey HKCU "Software\Classes\phcodeJSON" +DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.jsp" +DeleteRegKey HKCU "Software\Classes\phcodeJSP" +DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.jsx" +DeleteRegKey HKCU "Software\Classes\phcodeJSX" +DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.kit" +DeleteRegKey HKCU "Software\Classes\phcodeKIT" +DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.less" +DeleteRegKey HKCU "Software\Classes\phcodeLESS" +DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.markdown" +DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN" +DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.mathml" +DeleteRegKey HKCU "Software\Classes\phcodeMATHML" +DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.md" +DeleteRegKey HKCU "Software\Classes\phcodeMD" +DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.patch" +DeleteRegKey HKCU "Software\Classes\phcodePATCH" +DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.php" +DeleteRegKey HKCU "Software\Classes\phcodePHP" +DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.php3" +DeleteRegKey HKCU "Software\Classes\phcodePHP3" +DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.php4" +DeleteRegKey HKCU "Software\Classes\phcodePHP4" +DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.php5" +DeleteRegKey HKCU "Software\Classes\phcodePHP5" +DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.phtm" +DeleteRegKey HKCU "Software\Classes\phcodePHTM" +DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.phtml" +DeleteRegKey HKCU "Software\Classes\phcodePHTML" +DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.rdf" +DeleteRegKey HKCU "Software\Classes\phcodeRDF" +DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.rss" +DeleteRegKey HKCU "Software\Classes\phcodeRSS" +DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.sass" +DeleteRegKey HKCU "Software\Classes\phcodeSASS" +DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.scss" +DeleteRegKey HKCU "Software\Classes\phcodeSCSS" +DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.shtm" +DeleteRegKey HKCU "Software\Classes\phcodeSHTM" +DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.shtml" +DeleteRegKey HKCU "Software\Classes\phcodeSHTML" +DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.sql" +DeleteRegKey HKCU "Software\Classes\phcodeSQL" +DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.svg" +DeleteRegKey HKCU "Software\Classes\phcodeSVG" +DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.tpl" +DeleteRegKey HKCU "Software\Classes\phcodeTPL" +DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.twig" +DeleteRegKey HKCU "Software\Classes\phcodeTWIG" +DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.wsgi" +DeleteRegKey HKCU "Software\Classes\phcodeWSGI" +DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.xbl" +DeleteRegKey HKCU "Software\Classes\phcodeXBL" +DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.xht" +DeleteRegKey HKCU "Software\Classes\phcodeXHT" +DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.xhtml" +DeleteRegKey HKCU "Software\Classes\phcodeXHTML" +DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.xml" +DeleteRegKey HKCU "Software\Classes\phcodeXML" +DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.xslt" +DeleteRegKey HKCU "Software\Classes\phcodeXSLT" +DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.xul" +DeleteRegKey HKCU "Software\Classes\phcodeXUL" +DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.yaml" +DeleteRegKey HKCU "Software\Classes\phcodeYAML" +DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.yml" +DeleteRegKey HKCU "Software\Classes\phcodeYML" +DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.ts" +DeleteRegKey HKCU "Software\Classes\phcodeTS" +DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\.tsx" +DeleteRegKey HKCU "Software\Classes\phcodeTSX" +DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\command" +DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\phcode\command" +DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode" +DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode\command" FunctionEnd Section Uninstall From 54c5d832830a0b1c36cdd4ce79eba51f06b674e9 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 19 Jan 2024 14:01:42 +0530 Subject: [PATCH 247/864] feat: added support for open with folder --- src-tauri/src/bundle/windows/nsis/installer.nsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi index 1826e015..94bc8ee1 100644 --- a/src-tauri/src/bundle/windows/nsis/installer.nsi +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -1124,6 +1124,15 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "" "Open with phcode" WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + ; Add a context menu item for folders + WriteRegStr HKCU "Software\Classes\Directory\shell\phcode" "" "Open as phcode project" + WriteRegStr HKCU "Software\Classes\Directory\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' + ; Optional: Set an icon for the context menu item + WriteRegStr HKCU "Software\Classes\Directory\shell\phcode" "Icon" '"$INSTDIR\${MAINBINARYNAME}.exe",0' + WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" "" "Open as phcode project" + WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" "Icon" '"$INSTDIR\${MAINBINARYNAME}.exe"' + WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%V"' + FunctionEnd Section Install @@ -1633,6 +1642,10 @@ DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\phcode" DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\phcode\command" DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode" DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode\command" +DeleteRegKey HKCU "Software\Classes\Directory\shell\phcode" +DeleteRegKey HKCU "Software\Classes\Directory\shell\phcode\command" +DeleteRegKey HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" +DeleteRegKey HKCU "SOFTWARE\Classes\Directory\background\shell\phcode\command" FunctionEnd Section Uninstall From 4f100a0cbcbb791824d548332fdca0120ec4f5f6 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 19 Jan 2024 15:43:43 +0530 Subject: [PATCH 248/864] feat: add _get_window_labels api as tauri js api is inconsistant --- src-tauri/src/main.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 11dd7cc8..7f595a13 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -66,6 +66,15 @@ fn _rename_path(old_path: &str, new_path: &str) -> Result<(), String> { platform::rename_path(old_path, new_path) } +#[tauri::command] +fn _get_window_labels(app: tauri::AppHandle) -> Vec { + app.windows() + .iter() + .map(|(label, _window)| label.to_string()) + .collect() +} + + #[tauri::command] fn _get_clipboard_files() -> Option> { match clipboard_files::read() { @@ -240,6 +249,7 @@ fn main() { .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ toggle_devtools, console_log, console_error, _get_commandline_args, + _get_window_labels, _get_windows_drives, _rename_path, show_in_folder, zoom_window, _get_clipboard_files]) .setup(|app| { init::init_app(app); From c2ca092c14675d2bea78746281fa62361589cec1 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 19 Jan 2024 18:20:26 +0000 Subject: [PATCH 249/864] ci: update phcode version to 3.2.20 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 7877ffa3..1f15b1e5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.19", + "version": "3.2.20", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "a230298b5846dc4304f0662622e1d96ee1ab9b26" + "commit": "1a302287c99288d48ddf663bde5e5a4947958a9e" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 81edbc05..abb299bc 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.19" +version = "3.2.20" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6d96994c..525eb748 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.19" + "version": "3.2.20" }, "tauri": { "allowlist": { From b6262039fbe9e5aa7cf109a0e0efabf79e7c621b Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 20 Jan 2024 00:03:23 +0530 Subject: [PATCH 250/864] fix: prod build break --- src-build/ci-createDistReleaseConfig.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index 5e410d55..f589705b 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -27,6 +27,9 @@ function _removeSuffixesFromName(name) { function _getProductName(name, stage) { name = _removeSuffixesFromName(name); + if(stage === 'production') { + return name; // Phoenix Code + } if(!PRODUCT_NAME_SUFFIX_FOR_STAGE[stage]) { throw new Error(`Cannot build Phoenix for unknown environment ${stage}`); } From 4553a92b8811be5232c500ee63cfd413ef28b041 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 21 Jan 2024 17:37:07 +0000 Subject: [PATCH 251/864] fix(deps): update rust crate regex to 1.10.3 --- src-tauri/Cargo.lock | 16 ++++++++-------- src-tauri/Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 44d532a6..467747f9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1484,7 +1484,7 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.3", + "regex-automata 0.4.4", "regex-syntax 0.8.2", ] @@ -1785,7 +1785,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.4", "same-file", "walkdir", "winapi-util", @@ -2680,7 +2680,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.19" +version = "3.2.20" dependencies = [ "clipboard-files", "fix-path-env", @@ -2998,13 +2998,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.4", "regex-syntax 0.8.2", ] @@ -3019,9 +3019,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" dependencies = [ "aho-corasick", "memchr", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index abb299bc..29849824 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,7 +17,7 @@ tauri-build = { version = "1.5.1", features = [] } serde_json = "1.0" once_cell = "1.19.0" percent-encoding = "2.3" -regex = "1.10.2" +regex = "1.10.3" clipboard-files = "0.1.1" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.4", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } From 933788b7b61ff537bccd3b132c0a7ef5db31487f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 18:22:13 +0000 Subject: [PATCH 252/864] build(deps): bump h2 from 0.3.22 to 0.3.24 in /src-tauri Bumps [h2](https://github.com/hyperium/h2) from 0.3.22 to 0.3.24. - [Release notes](https://github.com/hyperium/h2/releases) - [Changelog](https://github.com/hyperium/h2/blob/v0.3.24/CHANGELOG.md) - [Commits](https://github.com/hyperium/h2/compare/v0.3.22...v0.3.24) --- updated-dependencies: - dependency-name: h2 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 467747f9..1d489746 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1556,9 +1556,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", From 262ec6fb0d8b57be6e8f980cec3948f3bf5ab236 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 24 Jan 2024 13:22:44 +0530 Subject: [PATCH 253/864] feat: added install script for installation and uninstallation --- src-build/win/reg_gen.js | 127 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src-build/win/reg_gen.js diff --git a/src-build/win/reg_gen.js b/src-build/win/reg_gen.js new file mode 100644 index 00000000..c1cf0197 --- /dev/null +++ b/src-build/win/reg_gen.js @@ -0,0 +1,127 @@ +/** + * This module generates NSIS (Nullsoft Scriptable Install System) scripts for setting file + * associations and context menus, and a cleanup script to remove these settings. + */ +import fs from 'fs'; + +const installReg = 'install.txt'; // Replace with your file path +const outputFile = 'cleanup.txt'; // Output file path + +/** + * Creates an NSIS script to set file associations and context menu entries for various file extensions. + * The script is written to a file specified by `installReg`. + */ +function createInstallRegEntries() { + const extensions = [ + ".asax", ".ashx", ".aspx", ".atom", ".cf", ".cfc", ".cfm", ".cfm1", ".clj", + ".coffee", ".cshtml", ".cson", ".css", ".ctp", ".dhtml", ".diff", ".ejs", + ".handlebars", ".hbs", ".htm", ".html", ".hx", ".js", ".json", ".jsp", ".jsx", + ".kit", ".less", ".markdown", ".mathml", ".md", ".patch", ".php", ".php3", + ".php4", ".php5", ".phtm", ".phtml", ".rdf", ".rss", ".sass", ".scss", + ".shtm", ".shtml", ".sql", ".svg", ".tpl", ".twig", ".wsgi", ".xbl", ".xht", + ".xhtml", ".xml", ".xslt", ".xul", ".yaml", ".yml", ".ts", ".tsx" + ]; + + let nsisScript = ''; + + extensions.forEach(ext => { + const extName = ext.substring(1); // Remove the dot from the extension + const typeName = `phcode${extName.toUpperCase()}`; // Create a type name + + nsisScript += ` + ; Set file association and context menu for ${ext} files + WriteRegStr HKCU "Software\\Classes\\${ext}" "" "${typeName}" + WriteRegStr HKCU "Software\\Classes\\${typeName}" "" "${extName.toUpperCase()} file" + WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\open\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' + WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\open\\phcode" "" '"Open with phcode" "%1"' + WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\open\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' + WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode" "Icon" '${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe,0'}' + WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' +`; + }); + + nsisScript += ` + ; Add a context menu item for folders + WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode" "" "Open as phcode project" + WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' + ; Optional: Set an icon for the context menu item + WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode" "Icon" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}",0' + WriteRegStr HKCU "SOFTWARE\\Classes\\Directory\\background\\shell\\phcode" "" "Open as phcode project" + WriteRegStr HKCU "SOFTWARE\\Classes\\Directory\\background\\shell\\phcode" "Icon" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}"' + WriteRegStr HKCU "SOFTWARE\\Classes\\Directory\\background\\shell\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%V"' + +`; + fs.writeFileSync(installReg, nsisScript, err => { + if (err) { + console.error(err); + return; + } + console.log('NSIS script generated successfully.'); + }); +} + +/** + * Parses an NSIS script to extract registry keys and generates a cleanup script to remove these keys. + * The cleanup script is written to a file specified by `outputFile`. + */ +function createCleanUpEntries() { + /** + * Extracts registry keys from the given NSIS script. + * @param {string} script - NSIS script to parse. + * @returns {string[]} An array of extracted registry keys. + */ + function extractRegistryKeys(script) { + const regKeyPattern = /WriteRegStr\sHKCU\s"([^"]+)"/g; + const keys = new Set(); + + let match; + while ((match = regKeyPattern.exec(script)) !== null) { + keys.add(match[1]); + } + + return Array.from(keys); + } + + /** + * Generates an NSIS cleanup script using the provided registry keys. + * @param {string[]} keys - Array of registry keys to be removed. + * @returns {string} Generated NSIS cleanup script. + */ + function generateCleanupScript(keys) { + const commands = keys.map(key => `DeleteRegKey HKCU "${key}"`).join('\n'); + return `; NSIS Cleanup Script\n\n${commands}`; + } + +// Read the NSIS script, extract keys, generate cleanup script, and write to file + fs.readFile(installReg, 'utf8', (err, data) => { + if (err) { + console.error('Error reading file:', err); + return; + } + + const keys = extractRegistryKeys(data); + const cleanupScript = generateCleanupScript(keys); + + fs.writeFile(outputFile, cleanupScript, err => { + if (err) { + console.error('Error writing cleanup script:', err); + } else { + console.log('Cleanup script generated successfully:', outputFile); + } + }); + }); +} + +/** + * Main function to create both install and cleanup NSIS scripts. + */ +function createRegistryEntryForNsis() { + createInstallRegEntries(); + createCleanUpEntries(); +} +// Execute the main function to generate scripts +// Once script this script is executed install.txt will contain nsis code to create registry entire to be created during installation +// cleanup.txt will contain nsis code to delete registry entries during uninstallation +// Copy this code to src-tauri/src/bundle/windows/nsis/installer.nsi Function SetupPhcode and Function un.CleanPhcode sections +createRegistryEntryForNsis(); From 7a65500382ea9d7b2e027a70b9208546e3b31155 Mon Sep 17 00:00:00 2001 From: "charly@core.ai" Date: Wed, 24 Jan 2024 16:49:57 +0530 Subject: [PATCH 254/864] feat: intial commit for info.plist --- src-tauri/Info.plist | 385 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 385 insertions(+) create mode 100644 src-tauri/Info.plist diff --git a/src-tauri/Info.plist b/src-tauri/Info.plist new file mode 100644 index 00000000..ec1539b6 --- /dev/null +++ b/src-tauri/Info.plist @@ -0,0 +1,385 @@ + + + + + CFBundleDocumentTypes + + + CFBundleTypeName + Document + CFBundleTypeRole + Viewer + CFBundleTypeOSTypes + + **** + + CFBundleTypeExtensions + + gif + jpe + jpeg + jpg + png + + + + CFBundleTypeName + Text files + CFBundleTypeRole + Editor + LSItemContentTypes + + public.text + public.source-code + public.script + public.shell-script + + + + CFBundleTypeName + HTML source + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + htm + html + shtm + shtml + xhtml + cfm + cfml + cfc + dhtml + xht + tpl + twig + hbs + handlebars + kit + jsp + aspx + + + + CFBundleTypeName + JavaScript source + CFBundleTypeExtensions + + js + jsx + + CFBundleTypeRole + Editor + + + CFBundleTypeName + CSS source + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + css + less + + + + CFBundleTypeName + Markdown + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + md + mkd + mkdn + mdown + markdown + + + + CFBundleTypeName + Groovy source + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + groovy + + + + CFBundleTypeName + Properties + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + ini + properties + + + + CFBundleTypeName + SCSS + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + scss + + + + CFBundleTypeName + EJS + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + ejs + + + + CFBundleTypeName + JSON + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + json + + + + CFBundleTypeName + XML + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + svg + xml + wxs + wxl + wsdl + rss + atom + rdf + xslt + xul + xbl + mathml + config + + + + CFBundleTypeName + PHP + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + php + php3 + php4 + php5 + phtm + phtml + + + + CFBundleTypeName + C + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + c + h + i + + + + CFBundleTypeName + C++ + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + cc + cp + cpp + c++ + cxx + hh + hpp + hxx + h++ + ii + + + + CFBundleTypeName + C# + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + cs + cshtml + asax + ashx + + + + CFBundleTypeName + Java + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + java + + + + CFBundleTypeName + Scala + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + scala + sbt + + + + CFBundleTypeName + CoffeeScript + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + coffee + cf + cson + + + + CFBundleTypeName + Clojure + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + clj + + + + CFBundleTypeName + Perl + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + pl + pm + + + + CFBundleTypeName + Ruby + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + rb + ru + gemspec + rake + + + + CFBundleTypeName + Python + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + py + pyw + wsgi + + + + CFBundleTypeName + SASS + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + sass + + + + CFBundleTypeName + Lua + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + lua + + + + CFBundleTypeName + SQL + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + sql + + + + CFBundleTypeName + Diff + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + diff + patch + + + + CFBundleTypeName + YAML + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + yaml + yml + + + + CFBundleTypeName + Haxe + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + hx + + + + CFBundleTypeName + Bash + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + sh + + + + + \ No newline at end of file From 48417213f450b765208855fab9979ea0e0fbbbf0 Mon Sep 17 00:00:00 2001 From: "charly@core.ai" Date: Thu, 25 Jan 2024 12:39:04 +0530 Subject: [PATCH 255/864] feat: adding support for file association in mac --- src-tauri/Info.plist | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/src-tauri/Info.plist b/src-tauri/Info.plist index ec1539b6..5a8713dd 100644 --- a/src-tauri/Info.plist +++ b/src-tauri/Info.plist @@ -2,13 +2,27 @@ + CFBundleURLTypes + + + CFBundleURLName + + ai.core.dev + CFBundleURLSchemes + + + file + myscheme + + + CFBundleDocumentTypes CFBundleTypeName Document CFBundleTypeRole - Viewer + Editor CFBundleTypeOSTypes **** @@ -37,10 +51,11 @@ CFBundleTypeName - HTML source - CFBundleTypeRole - Editor - CFBundleTypeExtensions + HTML source + CFBundleTypeRole + Editor + CFBundleTypeExtensions + htm html @@ -64,13 +79,13 @@ CFBundleTypeName JavaScript source + CFBundleTypeRole + Editor CFBundleTypeExtensions js jsx - CFBundleTypeRole - Editor CFBundleTypeName @@ -107,6 +122,16 @@ groovy + + CFBundleTypeName + Groovy source + CFBundleTypeRole + Editor + CFBundleTypeExtensions + + groovy + + CFBundleTypeName Properties @@ -382,4 +407,4 @@ - \ No newline at end of file + From eabc4acd8b2a1f857952cdabcd342c5519b3d96b Mon Sep 17 00:00:00 2001 From: "charly@core.ai" Date: Thu, 25 Jan 2024 12:44:22 +0530 Subject: [PATCH 256/864] fix: update correct identifier --- src-tauri/Info.plist | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src-tauri/Info.plist b/src-tauri/Info.plist index 5a8713dd..885d2e3d 100644 --- a/src-tauri/Info.plist +++ b/src-tauri/Info.plist @@ -6,11 +6,9 @@ CFBundleURLName - - ai.core.dev + io.phcode CFBundleURLSchemes - file myscheme From ae11b260c05c0bf42e36f7f8b0f38050b37ff00a Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 25 Jan 2024 14:00:22 +0530 Subject: [PATCH 257/864] build: app bundle identifier reqrite in info.plist and main.rs in pipeline builds --- src-build/ci-createDistReleaseConfig.js | 24 ++++++++++++++++++++++++ src-tauri/Info.plist | 2 +- src-tauri/src/main.rs | 5 +++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index f589705b..e155d021 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -37,11 +37,24 @@ function _getProductName(name, stage) { return `${name} ${PRODUCT_NAME_SUFFIX_FOR_STAGE[stage]}`.trim(); } +function replaceBundleIdentifierString(sourceStr, newIdentifier) { + const IDENTIFIER_PLACEHOLDER = "TAURI_BUNDLE_IDENTIFIER_PLACE_HOLDER"; + let bundleIdentifiers = Object.values(BUNDLE_IDENTIFIER_FOR_STAGE); + // longest prefix first, else may cause substring replacement only + bundleIdentifiers.sort((a, b) => b.length - a.length); + for(const identifier of bundleIdentifiers){ + sourceStr = sourceStr.replace(identifier, IDENTIFIER_PLACEHOLDER); + } + return sourceStr.replace(IDENTIFIER_PLACEHOLDER, newIdentifier); +} + async function ciCreateDistReleaseConfig() { const phoenixConfigPath = join(__dirname, '..', 'phoenix', 'dist', 'config.json'); const packageJSONPath = join(__dirname, '..', 'package.json'); const tauriTOMLPath = join(__dirname, '..', 'src-tauri', 'Cargo.toml'); const tauriConfigPath = join(__dirname, '..', 'src-tauri', 'tauri.conf.json'); + const infoPLISTPath = join(__dirname, '..', 'src-tauri', 'Info.plist'); + const mainRustPath = join(__dirname, '..', 'src-tauri', "src", 'main.rs'); console.log("loading phoenix config: ", phoenixConfigPath); let configJson = JSON.parse(fs.readFileSync(phoenixConfigPath)); @@ -88,6 +101,17 @@ async function ciCreateDistReleaseConfig() { console.log("Product update endpoints are: ", configJson.tauri.updater.endpoints); console.log("Writing new dist config json ", tauriConfigPath); fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); + + // patch info.plist for mac + console.log("Writing new dist info plist", infoPLISTPath); + let infoPlist = fs.readFileSync(infoPLISTPath, "utf8"); + fs.writeFileSync(infoPLISTPath, replaceBundleIdentifierString(infoPlist, bundleIdentifier), "utf8"); + + // patch main.rs for mac + console.log("Writing new dist main.ts", mainRustPath); + let mainRustFileContent = fs.readFileSync(mainRustPath, "utf8"); + fs.writeFileSync(mainRustPath, replaceBundleIdentifierString(mainRustFileContent, bundleIdentifier), "utf8"); + return phoenixVersion; } diff --git a/src-tauri/Info.plist b/src-tauri/Info.plist index 885d2e3d..1096e9fa 100644 --- a/src-tauri/Info.plist +++ b/src-tauri/Info.plist @@ -6,7 +6,7 @@ CFBundleURLName - io.phcode + io.phcode.dev CFBundleURLSchemes file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 7f595a13..38f573fe 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -189,6 +189,11 @@ fn remove_version_from_url(url: &str) -> String { } fn main() { + // warning: any string that resembles the following strings will be rewritten in source in prod by build scripts. + // This is so that app bundle IDs are correct. IF they are app bundle IDs use the strings. else dont. + // do not use strings: "io.phcode.dev" "io.phcode.staging" "io.phcode" for anything other than bundle identifiers + // in this file!!! + // GUI apps on macOS and Linux do not inherit the $PATH from your shell dotfiles (.bashrc, .bash_profile, .zshrc, etc). // fix that https://github.com/tauri-apps/fix-path-env-rs let _ = fix_path_env::fix(); From cf6767310eecd64832eb7755f18c9d77e06563f5 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 25 Jan 2024 09:54:51 +0000 Subject: [PATCH 258/864] ci: update phcode version to 3.2.21 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 1f15b1e5..4432d9ee 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.20", + "version": "3.2.21", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "1a302287c99288d48ddf663bde5e5a4947958a9e" + "commit": "c5ea265163967d6e4bdc97139090fcee7510c72e" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 29849824..239c3a45 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.20" +version = "3.2.21" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 525eb748..7d4628f8 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.20" + "version": "3.2.21" }, "tauri": { "allowlist": { From 721ea0c425f4e3ca6674114b4ce17862b69f94c3 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 25 Jan 2024 14:53:01 +0530 Subject: [PATCH 259/864] refactor: rebase --- src-tauri/Cargo.toml | 1 + src-tauri/Info.plist | 2 +- src-tauri/src/main.rs | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 239c3a45..1263bfd8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -26,6 +26,7 @@ tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } +tauri-plugin-deep-link = "0.1.2" [target.'cfg(target_os = "linux")'.dependencies] gtk = "0.15" diff --git a/src-tauri/Info.plist b/src-tauri/Info.plist index 1096e9fa..150c90c9 100644 --- a/src-tauri/Info.plist +++ b/src-tauri/Info.plist @@ -10,7 +10,7 @@ CFBundleURLSchemes file - myscheme + file-scheme diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 38f573fe..40d65203 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -187,8 +187,13 @@ fn remove_version_from_url(url: &str) -> String { let re = Regex::new(r"([a-zA-Z]+://[^/]+)/v[\d+\.]+/").unwrap(); re.replace(url, "$1/").to_string() } - +use std::fs::File; +use std::io::{Write, Seek, SeekFrom}; +use std::path::Path; fn main() { + + tauri_plugin_deep_link::prepare("io.phcode"); + // warning: any string that resembles the following strings will be rewritten in source in prod by build scripts. // This is so that app bundle IDs are correct. IF they are app bundle IDs use the strings. else dont. // do not use strings: "io.phcode.dev" "io.phcode.staging" "io.phcode" for anything other than bundle identifiers @@ -268,7 +273,35 @@ fn main() { let gtk_settings = gtk_win.settings().unwrap(); gtk_settings.set_property("gtk-menu-bar-accel", "F25"); } - Ok(()) + #[cfg(target_os = "macos")] + { + let handle = app.handle(); + tauri_plugin_deep_link::register( + "file-scheme", + move |request| { + // Print the request for debugging + dbg!(&request); + + // Emit the event (as in the original code) + handle.emit_all("scheme-request-received", &request).unwrap(); + + // Write the request to a file in the /tmp folder + let path = Path::new("/tmp/scheme_request.txt"); + let mut file = match File::create(&path) { + Err(why) => panic!("couldn't create {}: {}", path.display(), why), + Ok(file) => file, + }; + + match file.write_all(request.as_bytes()) { + Err(why) => panic!("couldn't write to {}: {}", path.display(), why), + Ok(_) => println!("successfully wrote to {}", path.display()), + } + }, + ) + .unwrap(); + + Ok(()) + } }) .run(tauri::generate_context!()) .expect("error while running tauri application"); From 19a20602029259d8a2285ac0826b51d442d0ae60 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 25 Jan 2024 15:13:27 +0530 Subject: [PATCH 260/864] fix: build break --- src-tauri/Cargo.lock | 85 +++++++++++++++++++++++++++++++++++++++++++ src-tauri/Cargo.toml | 2 +- src-tauri/src/main.rs | 26 +++---------- 3 files changed, 92 insertions(+), 21 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1d489746..fa65be7c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -871,6 +871,15 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -881,6 +890,18 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1846,6 +1867,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "interprocess" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f2533f3be42fffe3b5e63b71aeca416c1c3bc33e4e27be018521e76b1f38fb" +dependencies = [ + "cfg-if", + "libc", + "rustc_version", + "to_method", + "winapi", +] + [[package]] name = "io-lifetimes" version = "1.0.11" @@ -2348,6 +2382,28 @@ dependencies = [ "objc_id", ] +[[package]] +name = "objc-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c71324e4180d0899963fc83d9d241ac39e699609fc1025a850aadac8257459" + +[[package]] +name = "objc2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-encode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" + [[package]] name = "objc_exception" version = "0.1.2" @@ -2435,6 +2491,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-stream" version = "0.2.0" @@ -2693,6 +2755,7 @@ dependencies = [ "serde_json", "tauri", "tauri-build", + "tauri-plugin-deep-link", "tauri-plugin-fs-extra", "tauri-plugin-single-instance", "tauri-plugin-window-state", @@ -3839,6 +3902,22 @@ dependencies = [ "tauri-utils", ] +[[package]] +name = "tauri-plugin-deep-link" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4536f5f6602e8fdfaa7b3b185076c2a0704f8eb7015f4e58461eb483ec3ed1f8" +dependencies = [ + "dirs", + "interprocess", + "log", + "objc2", + "once_cell", + "tauri-utils", + "windows-sys 0.48.0", + "winreg 0.50.0", +] + [[package]] name = "tauri-plugin-fs-extra" version = "0.0.0" @@ -4101,6 +4180,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "to_method" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" + [[package]] name = "tokio" version = "1.34.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1263bfd8..5825de13 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -26,7 +26,6 @@ tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } -tauri-plugin-deep-link = "0.1.2" [target.'cfg(target_os = "linux")'.dependencies] gtk = "0.15" @@ -34,6 +33,7 @@ webkit2gtk = "0.18" # if tauri build fails, make sure to match this version to w [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2" +tauri-plugin-deep-link = "0.1.2" [features] # by default Tauri runs in production mode diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 40d65203..c86ff692 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -187,12 +187,12 @@ fn remove_version_from_url(url: &str) -> String { let re = Regex::new(r"([a-zA-Z]+://[^/]+)/v[\d+\.]+/").unwrap(); re.replace(url, "$1/").to_string() } -use std::fs::File; -use std::io::{Write, Seek, SeekFrom}; -use std::path::Path; + fn main() { - tauri_plugin_deep_link::prepare("io.phcode"); + #[cfg(target_os = "macos")]{ + tauri_plugin_deep_link::prepare("io.phcode"); + } // warning: any string that resembles the following strings will be rewritten in source in prod by build scripts. // This is so that app bundle IDs are correct. IF they are app bundle IDs use the strings. else dont. @@ -281,27 +281,13 @@ fn main() { move |request| { // Print the request for debugging dbg!(&request); - // Emit the event (as in the original code) handle.emit_all("scheme-request-received", &request).unwrap(); - - // Write the request to a file in the /tmp folder - let path = Path::new("/tmp/scheme_request.txt"); - let mut file = match File::create(&path) { - Err(why) => panic!("couldn't create {}: {}", path.display(), why), - Ok(file) => file, - }; - - match file.write_all(request.as_bytes()) { - Err(why) => panic!("couldn't write to {}: {}", path.display(), why), - Ok(_) => println!("successfully wrote to {}", path.display()), - } }, ) - .unwrap(); - - Ok(()) + .unwrap(); } + Ok(()) }) .run(tauri::generate_context!()) .expect("error while running tauri application"); From 783c39d6b8bf73b41299b2a3e598bffa693bdae0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 01:32:51 +0000 Subject: [PATCH 261/864] chore(deps): update dependency axios to v1.6.6 --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index fe2e9fea..d30c152c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "phoenix-code-ide", - "version": "3.2.19", + "version": "3.2.20", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.19", + "version": "3.2.20", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.9", "adm-zip": "0.5.10", - "axios": "1.6.5", + "axios": "1.6.6", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", @@ -258,9 +258,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", - "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.6.tgz", + "integrity": "sha512-XZLZDFfXKM9U/Y/B4nNynfCRUqNyVZ4sBC/n9GDRCkq9vd2mIvKjKKsbIh1WPmHmNbg6ND7cTBY3Y2+u1G3/2Q==", "dev": true, "dependencies": { "follow-redirects": "^1.15.4", @@ -1499,9 +1499,9 @@ "dev": true }, "axios": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", - "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.6.tgz", + "integrity": "sha512-XZLZDFfXKM9U/Y/B4nNynfCRUqNyVZ4sBC/n9GDRCkq9vd2mIvKjKKsbIh1WPmHmNbg6ND7cTBY3Y2+u1G3/2Q==", "dev": true, "requires": { "follow-redirects": "^1.15.4", diff --git a/package.json b/package.json index 4432d9ee..dc8723c6 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.0", - "axios": "1.6.5" + "axios": "1.6.6" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From ff7ae0eba39de644cbe5095aa080a5b862f075bf Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 25 Jan 2024 19:11:39 +0530 Subject: [PATCH 262/864] chore: get_mac_deep_link_requests tauri command api --- src-tauri/Cargo.lock | 2 +- src-tauri/src/main.rs | 30 +++++++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fa65be7c..ccac1320 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2742,7 +2742,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.20" +version = "3.2.21" dependencies = [ "clipboard-files", "fix-path-env", diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c86ff692..eaf4389f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,7 +4,7 @@ windows_subsystem = "windows" )] use std::env; -use tauri::{Manager}; +use tauri::{Manager, Window}; #[cfg(target_os = "linux")] use std::fs::metadata; @@ -188,6 +188,29 @@ fn remove_version_from_url(url: &str) -> String { re.replace(url, "$1/").to_string() } +#[cfg(target_os = "macos")] +use std::sync::{Arc, Mutex}; + +#[cfg(target_os = "macos")] +struct AppState { + deep_link_requests: Arc>>, +} + +#[tauri::command] +fn get_mac_deep_link_requests(_window: Window) -> Vec { + #[cfg(target_os = "macos")] + { + let state = _window.state::(); + let requests = state.deep_link_requests.lock().unwrap(); + requests.clone() + } + #[cfg(not(target_os = "macos"))] + { + // This code will be compiled and run on operating systems other than macOS (like Linux and Windows) + Vec::new() // Return an empty vector + } +} + fn main() { #[cfg(target_os = "macos")]{ @@ -258,6 +281,7 @@ fn main() { })) .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ + get_mac_deep_link_requests, toggle_devtools, console_log, console_error, _get_commandline_args, _get_window_labels, _get_windows_drives, _rename_path, show_in_folder, zoom_window, _get_clipboard_files]) @@ -281,6 +305,10 @@ fn main() { move |request| { // Print the request for debugging dbg!(&request); + // save the requests as at boot, the js layer may not yet be present to process + // the file open requests from mac os. + let mut requests = deep_link_requests.lock().unwrap(); + requests.push(request.clone()); // Emit the event (as in the original code) handle.emit_all("scheme-request-received", &request).unwrap(); }, From 6dc6d4cd4f0e16f8cec9556ae8075a8d1f90d878 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 25 Jan 2024 19:31:42 +0530 Subject: [PATCH 263/864] chore: global vector to store mac open with file requests --- src-tauri/Cargo.lock | 1 + src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 20 +++++++++++++------- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ccac1320..f1ee3416 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2747,6 +2747,7 @@ dependencies = [ "clipboard-files", "fix-path-env", "gtk", + "lazy_static", "objc", "once_cell", "percent-encoding", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5825de13..9accd384 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -34,6 +34,7 @@ webkit2gtk = "0.18" # if tauri build fails, make sure to match this version to w [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2" tauri-plugin-deep-link = "0.1.2" +lazy_static = "1.4" [features] # by default Tauri runs in production mode diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index eaf4389f..2c1570b0 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,7 +4,7 @@ windows_subsystem = "windows" )] use std::env; -use tauri::{Manager, Window}; +use tauri::{Manager}; #[cfg(target_os = "linux")] use std::fs::metadata; @@ -191,18 +191,24 @@ fn remove_version_from_url(url: &str) -> String { #[cfg(target_os = "macos")] use std::sync::{Arc, Mutex}; +#[cfg(target_os = "macos")] +use lazy_static::lazy_static; + +#[cfg(target_os = "macos")] +lazy_static! { + static ref GLOBAL_STRING_VECTOR: Arc>> = Arc::new(Mutex::new(Vec::new())); +} + #[cfg(target_os = "macos")] struct AppState { deep_link_requests: Arc>>, } #[tauri::command] -fn get_mac_deep_link_requests(_window: Window) -> Vec { +fn get_mac_deep_link_requests() -> Vec { #[cfg(target_os = "macos")] { - let state = _window.state::(); - let requests = state.deep_link_requests.lock().unwrap(); - requests.clone() + GLOBAL_STRING_VECTOR.lock().unwrap() } #[cfg(not(target_os = "macos"))] { @@ -307,8 +313,8 @@ fn main() { dbg!(&request); // save the requests as at boot, the js layer may not yet be present to process // the file open requests from mac os. - let mut requests = deep_link_requests.lock().unwrap(); - requests.push(request.clone()); + let mut vec = GLOBAL_STRING_VECTOR.lock().unwrap(); + vec.push(request.clone()); // Emit the event (as in the original code) handle.emit_all("scheme-request-received", &request).unwrap(); }, From 4d2c76624cc950bcbc8d0c4de33f964a4d316c6c Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 25 Jan 2024 19:35:28 +0530 Subject: [PATCH 264/864] fix: mac build break --- src-tauri/src/main.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 2c1570b0..21589081 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -199,16 +199,11 @@ lazy_static! { static ref GLOBAL_STRING_VECTOR: Arc>> = Arc::new(Mutex::new(Vec::new())); } -#[cfg(target_os = "macos")] -struct AppState { - deep_link_requests: Arc>>, -} - #[tauri::command] fn get_mac_deep_link_requests() -> Vec { #[cfg(target_os = "macos")] { - GLOBAL_STRING_VECTOR.lock().unwrap() + GLOBAL_STRING_VECTOR.lock().unwrap().to_vec() } #[cfg(not(target_os = "macos"))] { From 5384b5a7410dcd95b854bf6b13d1a2748c0edf6f Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 25 Jan 2024 14:36:56 +0000 Subject: [PATCH 265/864] ci: update phcode version to 3.2.22 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index dc8723c6..12c3ecb7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.21", + "version": "3.2.22", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "c5ea265163967d6e4bdc97139090fcee7510c72e" + "commit": "1a621f520a53751dc2f4944bc98c04d8b72ccc2e" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9accd384..db0bd36b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.21" +version = "3.2.22" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 7d4628f8..329a7628 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.21" + "version": "3.2.22" }, "tauri": { "allowlist": { From fe65aef339e3ef7351bfc100aafd619dc9670a39 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 25 Jan 2024 21:48:08 +0530 Subject: [PATCH 266/864] chore: clone and clear mac open file with vector --- src-tauri/src/main.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 21589081..8f7acb0b 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -203,7 +203,10 @@ lazy_static! { fn get_mac_deep_link_requests() -> Vec { #[cfg(target_os = "macos")] { - GLOBAL_STRING_VECTOR.lock().unwrap().to_vec() + let mut vector = GLOBAL_STRING_VECTOR.lock().unwrap(); + let cloned_vector = vector.clone(); // Clone the vector's contents + vector.clear(); // Clear the vector + cloned_vector // Return the cloned vector } #[cfg(not(target_os = "macos"))] { From 7850698249c89d048592fd7805f68273147f45e1 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 25 Jan 2024 17:21:10 +0000 Subject: [PATCH 267/864] ci: update phcode version to 3.2.23 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 12c3ecb7..549879af 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.22", + "version": "3.2.23", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "1a621f520a53751dc2f4944bc98c04d8b72ccc2e" + "commit": "49bef69a5d28135b380b416a5155472461f0b77c" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index db0bd36b..b94f7069 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.22" +version = "3.2.23" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 329a7628..c9c5b06f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.22" + "version": "3.2.23" }, "tauri": { "allowlist": { From 0132f4ab41a9799fd25cc141cbe9eb03f1444b93 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 29 Jan 2024 13:38:22 +0530 Subject: [PATCH 268/864] fix: open as phcode in windows --- src-build/win/reg_gen.js | 6 +- .../src/bundle/windows/nsis/installer.nsi | 960 +++++++++--------- 2 files changed, 482 insertions(+), 484 deletions(-) diff --git a/src-build/win/reg_gen.js b/src-build/win/reg_gen.js index c1cf0197..4ea88060 100644 --- a/src-build/win/reg_gen.js +++ b/src-build/win/reg_gen.js @@ -36,18 +36,18 @@ function createInstallRegEntries() { WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\open\\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\open\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode" "Icon" '${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe,0'}' - WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' `; }); nsisScript += ` ; Add a context menu item for folders - WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode" "" "Open as phcode project" + WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode" "" "Open as phoenix code project" WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' ; Optional: Set an icon for the context menu item WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode" "Icon" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}",0' - WriteRegStr HKCU "SOFTWARE\\Classes\\Directory\\background\\shell\\phcode" "" "Open as phcode project" + WriteRegStr HKCU "SOFTWARE\\Classes\\Directory\\background\\shell\\phcode" "" "Open as phoenix code project" WriteRegStr HKCU "SOFTWARE\\Classes\\Directory\\background\\shell\\phcode" "Icon" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}"' WriteRegStr HKCU "SOFTWARE\\Classes\\Directory\\background\\shell\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%V"' diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi index 94bc8ee1..37226851 100644 --- a/src-tauri/src/bundle/windows/nsis/installer.nsi +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -533,7 +533,6 @@ SectionEnd Function SetupPhcode - ; Set file association and context menu for .asax files WriteRegStr HKCU "Software\Classes\.asax" "" "phcodeASAX" WriteRegStr HKCU "Software\Classes\phcodeASAX" "" "ASAX file" @@ -541,7 +540,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ashx files @@ -551,7 +550,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .aspx files @@ -561,7 +560,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .atom files @@ -571,7 +570,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cf files @@ -581,7 +580,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfc files @@ -591,7 +590,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfm files @@ -601,7 +600,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfm1 files @@ -611,7 +610,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .clj files @@ -621,7 +620,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .coffee files @@ -631,7 +630,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cshtml files @@ -641,7 +640,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cson files @@ -651,7 +650,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .css files @@ -661,7 +660,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ctp files @@ -671,7 +670,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .dhtml files @@ -681,7 +680,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .diff files @@ -691,7 +690,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ejs files @@ -701,7 +700,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .handlebars files @@ -711,7 +710,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .hbs files @@ -721,7 +720,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .htm files @@ -731,7 +730,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .html files @@ -741,7 +740,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .hx files @@ -751,7 +750,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .js files @@ -761,7 +760,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .json files @@ -771,7 +770,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .jsp files @@ -781,7 +780,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .jsx files @@ -791,7 +790,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .kit files @@ -801,7 +800,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .less files @@ -811,7 +810,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .markdown files @@ -821,7 +820,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .mathml files @@ -831,7 +830,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .md files @@ -841,7 +840,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .patch files @@ -851,7 +850,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php files @@ -861,7 +860,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php3 files @@ -871,7 +870,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php4 files @@ -881,7 +880,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php5 files @@ -891,7 +890,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .phtm files @@ -901,7 +900,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .phtml files @@ -911,7 +910,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .rdf files @@ -921,7 +920,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .rss files @@ -931,7 +930,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .sass files @@ -941,7 +940,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .scss files @@ -951,7 +950,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .shtm files @@ -961,7 +960,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .shtml files @@ -971,7 +970,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .sql files @@ -981,7 +980,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .svg files @@ -991,7 +990,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .tpl files @@ -1001,7 +1000,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .twig files @@ -1011,7 +1010,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .wsgi files @@ -1021,7 +1020,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xbl files @@ -1031,7 +1030,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xht files @@ -1041,7 +1040,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xhtml files @@ -1051,7 +1050,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xml files @@ -1061,7 +1060,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xslt files @@ -1071,7 +1070,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xul files @@ -1081,7 +1080,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .yaml files @@ -1091,7 +1090,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .yml files @@ -1101,7 +1100,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ts files @@ -1111,7 +1110,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .tsx files @@ -1121,18 +1120,17 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "" "Open with phcode" + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "" "Open with phoenix code" WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Add a context menu item for folders - WriteRegStr HKCU "Software\Classes\Directory\shell\phcode" "" "Open as phcode project" + WriteRegStr HKCU "Software\Classes\Directory\shell\phcode" "" "Open as phoenix code project" WriteRegStr HKCU "Software\Classes\Directory\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Optional: Set an icon for the context menu item WriteRegStr HKCU "Software\Classes\Directory\shell\phcode" "Icon" '"$INSTDIR\${MAINBINARYNAME}.exe",0' - WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" "" "Open as phcode project" + WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" "" "Open as phoenix code project" WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" "Icon" '"$INSTDIR\${MAINBINARYNAME}.exe"' WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%V"' - FunctionEnd Section Install @@ -1229,423 +1227,423 @@ FunctionEnd Function un.CleanPhcode ; NSIS Cleanup Script -DeleteRegKey HKCU "Software\Classes\.asax" -DeleteRegKey HKCU "Software\Classes\phcodeASAX" -DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.ashx" -DeleteRegKey HKCU "Software\Classes\phcodeASHX" -DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.aspx" -DeleteRegKey HKCU "Software\Classes\phcodeASPX" -DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.atom" -DeleteRegKey HKCU "Software\Classes\phcodeATOM" -DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.cf" -DeleteRegKey HKCU "Software\Classes\phcodeCF" -DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.cfc" -DeleteRegKey HKCU "Software\Classes\phcodeCFC" -DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.cfm" -DeleteRegKey HKCU "Software\Classes\phcodeCFM" -DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.cfm1" -DeleteRegKey HKCU "Software\Classes\phcodeCFM1" -DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.clj" -DeleteRegKey HKCU "Software\Classes\phcodeCLJ" -DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.coffee" -DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE" -DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.cshtml" -DeleteRegKey HKCU "Software\Classes\phcodeCSHTML" -DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.cson" -DeleteRegKey HKCU "Software\Classes\phcodeCSON" -DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.css" -DeleteRegKey HKCU "Software\Classes\phcodeCSS" -DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.ctp" -DeleteRegKey HKCU "Software\Classes\phcodeCTP" -DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.dhtml" -DeleteRegKey HKCU "Software\Classes\phcodeDHTML" -DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.diff" -DeleteRegKey HKCU "Software\Classes\phcodeDIFF" -DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.ejs" -DeleteRegKey HKCU "Software\Classes\phcodeEJS" -DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.handlebars" -DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS" -DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.hbs" -DeleteRegKey HKCU "Software\Classes\phcodeHBS" -DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.htm" -DeleteRegKey HKCU "Software\Classes\phcodeHTM" -DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.html" -DeleteRegKey HKCU "Software\Classes\phcodeHTML" -DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.hx" -DeleteRegKey HKCU "Software\Classes\phcodeHX" -DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.js" -DeleteRegKey HKCU "Software\Classes\phcodeJS" -DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.json" -DeleteRegKey HKCU "Software\Classes\phcodeJSON" -DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.jsp" -DeleteRegKey HKCU "Software\Classes\phcodeJSP" -DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.jsx" -DeleteRegKey HKCU "Software\Classes\phcodeJSX" -DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.kit" -DeleteRegKey HKCU "Software\Classes\phcodeKIT" -DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.less" -DeleteRegKey HKCU "Software\Classes\phcodeLESS" -DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.markdown" -DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN" -DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.mathml" -DeleteRegKey HKCU "Software\Classes\phcodeMATHML" -DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.md" -DeleteRegKey HKCU "Software\Classes\phcodeMD" -DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.patch" -DeleteRegKey HKCU "Software\Classes\phcodePATCH" -DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.php" -DeleteRegKey HKCU "Software\Classes\phcodePHP" -DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.php3" -DeleteRegKey HKCU "Software\Classes\phcodePHP3" -DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.php4" -DeleteRegKey HKCU "Software\Classes\phcodePHP4" -DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.php5" -DeleteRegKey HKCU "Software\Classes\phcodePHP5" -DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.phtm" -DeleteRegKey HKCU "Software\Classes\phcodePHTM" -DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.phtml" -DeleteRegKey HKCU "Software\Classes\phcodePHTML" -DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.rdf" -DeleteRegKey HKCU "Software\Classes\phcodeRDF" -DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.rss" -DeleteRegKey HKCU "Software\Classes\phcodeRSS" -DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.sass" -DeleteRegKey HKCU "Software\Classes\phcodeSASS" -DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.scss" -DeleteRegKey HKCU "Software\Classes\phcodeSCSS" -DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.shtm" -DeleteRegKey HKCU "Software\Classes\phcodeSHTM" -DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.shtml" -DeleteRegKey HKCU "Software\Classes\phcodeSHTML" -DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.sql" -DeleteRegKey HKCU "Software\Classes\phcodeSQL" -DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.svg" -DeleteRegKey HKCU "Software\Classes\phcodeSVG" -DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.tpl" -DeleteRegKey HKCU "Software\Classes\phcodeTPL" -DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.twig" -DeleteRegKey HKCU "Software\Classes\phcodeTWIG" -DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.wsgi" -DeleteRegKey HKCU "Software\Classes\phcodeWSGI" -DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.xbl" -DeleteRegKey HKCU "Software\Classes\phcodeXBL" -DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.xht" -DeleteRegKey HKCU "Software\Classes\phcodeXHT" -DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.xhtml" -DeleteRegKey HKCU "Software\Classes\phcodeXHTML" -DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.xml" -DeleteRegKey HKCU "Software\Classes\phcodeXML" -DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.xslt" -DeleteRegKey HKCU "Software\Classes\phcodeXSLT" -DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.xul" -DeleteRegKey HKCU "Software\Classes\phcodeXUL" -DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.yaml" -DeleteRegKey HKCU "Software\Classes\phcodeYAML" -DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.yml" -DeleteRegKey HKCU "Software\Classes\phcodeYML" -DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.ts" -DeleteRegKey HKCU "Software\Classes\phcodeTS" -DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\.tsx" -DeleteRegKey HKCU "Software\Classes\phcodeTSX" -DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\command" -DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\phcode\command" -DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode" -DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode\command" -DeleteRegKey HKCU "Software\Classes\Directory\shell\phcode" -DeleteRegKey HKCU "Software\Classes\Directory\shell\phcode\command" -DeleteRegKey HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" -DeleteRegKey HKCU "SOFTWARE\Classes\Directory\background\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.asax" + DeleteRegKey HKCU "Software\Classes\phcodeASAX" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeASAX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.ashx" + DeleteRegKey HKCU "Software\Classes\phcodeASHX" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeASHX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.aspx" + DeleteRegKey HKCU "Software\Classes\phcodeASPX" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeASPX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.atom" + DeleteRegKey HKCU "Software\Classes\phcodeATOM" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeATOM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cf" + DeleteRegKey HKCU "Software\Classes\phcodeCF" + DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCF\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cfc" + DeleteRegKey HKCU "Software\Classes\phcodeCFC" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCFC\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cfm" + DeleteRegKey HKCU "Software\Classes\phcodeCFM" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCFM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cfm1" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.clj" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.coffee" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cshtml" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.cson" + DeleteRegKey HKCU "Software\Classes\phcodeCSON" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCSON\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.css" + DeleteRegKey HKCU "Software\Classes\phcodeCSS" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCSS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.ctp" + DeleteRegKey HKCU "Software\Classes\phcodeCTP" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeCTP\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.dhtml" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.diff" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.ejs" + DeleteRegKey HKCU "Software\Classes\phcodeEJS" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeEJS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.handlebars" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.hbs" + DeleteRegKey HKCU "Software\Classes\phcodeHBS" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHBS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.htm" + DeleteRegKey HKCU "Software\Classes\phcodeHTM" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHTM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.html" + DeleteRegKey HKCU "Software\Classes\phcodeHTML" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.hx" + DeleteRegKey HKCU "Software\Classes\phcodeHX" + DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeHX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.js" + DeleteRegKey HKCU "Software\Classes\phcodeJS" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.json" + DeleteRegKey HKCU "Software\Classes\phcodeJSON" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJSON\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.jsp" + DeleteRegKey HKCU "Software\Classes\phcodeJSP" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJSP\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.jsx" + DeleteRegKey HKCU "Software\Classes\phcodeJSX" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeJSX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.kit" + DeleteRegKey HKCU "Software\Classes\phcodeKIT" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeKIT\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.less" + DeleteRegKey HKCU "Software\Classes\phcodeLESS" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeLESS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.markdown" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.mathml" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.md" + DeleteRegKey HKCU "Software\Classes\phcodeMD" + DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeMD\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.patch" + DeleteRegKey HKCU "Software\Classes\phcodePATCH" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePATCH\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.php" + DeleteRegKey HKCU "Software\Classes\phcodePHP" + DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.php3" + DeleteRegKey HKCU "Software\Classes\phcodePHP3" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP3\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.php4" + DeleteRegKey HKCU "Software\Classes\phcodePHP4" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP4\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.php5" + DeleteRegKey HKCU "Software\Classes\phcodePHP5" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHP5\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.phtm" + DeleteRegKey HKCU "Software\Classes\phcodePHTM" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHTM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.phtml" + DeleteRegKey HKCU "Software\Classes\phcodePHTML" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodePHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.rdf" + DeleteRegKey HKCU "Software\Classes\phcodeRDF" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeRDF\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.rss" + DeleteRegKey HKCU "Software\Classes\phcodeRSS" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeRSS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.sass" + DeleteRegKey HKCU "Software\Classes\phcodeSASS" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSASS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.scss" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.shtm" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.shtml" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.sql" + DeleteRegKey HKCU "Software\Classes\phcodeSQL" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSQL\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.svg" + DeleteRegKey HKCU "Software\Classes\phcodeSVG" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeSVG\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.tpl" + DeleteRegKey HKCU "Software\Classes\phcodeTPL" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTPL\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.twig" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.wsgi" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xbl" + DeleteRegKey HKCU "Software\Classes\phcodeXBL" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXBL\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xht" + DeleteRegKey HKCU "Software\Classes\phcodeXHT" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXHT\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xhtml" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xml" + DeleteRegKey HKCU "Software\Classes\phcodeXML" + DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xslt" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.xul" + DeleteRegKey HKCU "Software\Classes\phcodeXUL" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeXUL\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.yaml" + DeleteRegKey HKCU "Software\Classes\phcodeYAML" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeYAML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.yml" + DeleteRegKey HKCU "Software\Classes\phcodeYML" + DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeYML\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.ts" + DeleteRegKey HKCU "Software\Classes\phcodeTS" + DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTS\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\.tsx" + DeleteRegKey HKCU "Software\Classes\phcodeTSX" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\command" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\open\phcode\command" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode" + DeleteRegKey HKCU "Software\Classes\phcodeTSX\shell\phcode\command" + DeleteRegKey HKCU "Software\Classes\Directory\shell\phcode" + DeleteRegKey HKCU "Software\Classes\Directory\shell\phcode\command" + DeleteRegKey HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" + DeleteRegKey HKCU "SOFTWARE\Classes\Directory\background\shell\phcode\command" FunctionEnd Section Uninstall @@ -1726,4 +1724,4 @@ Function CreateStartMenuShortcut CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder" CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" ApplicationID::Set "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "${BUNDLEID}" -FunctionEnd \ No newline at end of file +FunctionEnd From 97010be27ff9e54191fc2c5d6d66b4acdfcffa50 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 29 Jan 2024 13:43:15 +0530 Subject: [PATCH 269/864] chore: add two spaces to delete reg generator --- src-build/win/reg_gen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-build/win/reg_gen.js b/src-build/win/reg_gen.js index 4ea88060..37d9374a 100644 --- a/src-build/win/reg_gen.js +++ b/src-build/win/reg_gen.js @@ -89,7 +89,7 @@ function createCleanUpEntries() { * @returns {string} Generated NSIS cleanup script. */ function generateCleanupScript(keys) { - const commands = keys.map(key => `DeleteRegKey HKCU "${key}"`).join('\n'); + const commands = keys.map(key => ` DeleteRegKey HKCU "${key}"`).join('\n'); return `; NSIS Cleanup Script\n\n${commands}`; } From 15d746cd6b5864463e5e6c54cbdc24d7f1e41f42 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 29 Jan 2024 14:47:11 +0530 Subject: [PATCH 270/864] fix: open with string --- src-build/win/reg_gen.js | 4 +- .../src/bundle/windows/nsis/installer.nsi | 122 +++++++++--------- 2 files changed, 64 insertions(+), 62 deletions(-) diff --git a/src-build/win/reg_gen.js b/src-build/win/reg_gen.js index 37d9374a..d9a89e5a 100644 --- a/src-build/win/reg_gen.js +++ b/src-build/win/reg_gen.js @@ -36,14 +36,14 @@ function createInstallRegEntries() { WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\open\\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\open\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode" "Icon" '${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe,0'}' - WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\\Classes\\${typeName}\\shell\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' `; }); nsisScript += ` ; Add a context menu item for folders - WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode" "" "Open as phoenix code project" + WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode" "" "Open as Phoenix Code project" WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode\\command" "" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}" "%1"' ; Optional: Set an icon for the context menu item WriteRegStr HKCU "Software\\Classes\\Directory\\shell\\phcode" "Icon" '"${'$INSTDIR'}\\${'${MAINBINARYNAME}.exe'}",0' diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi index 37226851..12deabfb 100644 --- a/src-tauri/src/bundle/windows/nsis/installer.nsi +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -540,7 +540,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeASAX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ashx files @@ -550,7 +550,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeASHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .aspx files @@ -560,7 +560,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeASPX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .atom files @@ -570,7 +570,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeATOM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cf files @@ -580,7 +580,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCF\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfc files @@ -590,7 +590,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCFC\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfm files @@ -600,7 +600,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCFM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cfm1 files @@ -610,7 +610,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCFM1\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .clj files @@ -620,7 +620,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCLJ\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .coffee files @@ -630,7 +630,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCOFFEE\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cshtml files @@ -640,7 +640,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .cson files @@ -650,7 +650,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .css files @@ -660,7 +660,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ctp files @@ -670,7 +670,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeCTP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .dhtml files @@ -680,7 +680,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeDHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .diff files @@ -690,7 +690,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeDIFF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ejs files @@ -700,7 +700,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeEJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .handlebars files @@ -710,7 +710,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeHANDLEBARS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .hbs files @@ -720,7 +720,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeHBS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .htm files @@ -730,7 +730,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .html files @@ -740,7 +740,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .hx files @@ -750,7 +750,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeHX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .js files @@ -760,7 +760,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeJS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .json files @@ -770,7 +770,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeJSON\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .jsp files @@ -780,7 +780,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeJSP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .jsx files @@ -790,7 +790,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeJSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .kit files @@ -800,7 +800,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeKIT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .less files @@ -810,7 +810,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeLESS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .markdown files @@ -820,7 +820,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeMARKDOWN\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .mathml files @@ -830,7 +830,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeMATHML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .md files @@ -840,7 +840,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMD\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeMD\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .patch files @@ -850,7 +850,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodePATCH\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php files @@ -860,7 +860,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodePHP\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php3 files @@ -870,7 +870,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodePHP3\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php4 files @@ -880,7 +880,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodePHP4\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .php5 files @@ -890,7 +890,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodePHP5\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .phtm files @@ -900,7 +900,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodePHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .phtml files @@ -910,7 +910,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodePHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .rdf files @@ -920,7 +920,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeRDF\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .rss files @@ -930,7 +930,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeRSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .sass files @@ -940,7 +940,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeSASS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .scss files @@ -950,7 +950,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeSCSS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .shtm files @@ -960,7 +960,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeSHTM\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .shtml files @@ -970,7 +970,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeSHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .sql files @@ -980,7 +980,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeSQL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .svg files @@ -990,7 +990,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeSVG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .tpl files @@ -1000,7 +1000,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeTPL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .twig files @@ -1010,7 +1010,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeTWIG\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .wsgi files @@ -1020,7 +1020,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeWSGI\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xbl files @@ -1030,7 +1030,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeXBL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xht files @@ -1040,7 +1040,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeXHT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xhtml files @@ -1050,7 +1050,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeXHTML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xml files @@ -1060,7 +1060,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeXML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xslt files @@ -1070,7 +1070,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeXSLT\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .xul files @@ -1080,7 +1080,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeXUL\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .yaml files @@ -1090,7 +1090,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeYAML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .yml files @@ -1100,7 +1100,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeYML\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeYML\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .ts files @@ -1110,7 +1110,7 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTS\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeTS\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Set file association and context menu for .tsx files @@ -1120,17 +1120,19 @@ Function SetupPhcode WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\phcode" "" '"Open with phcode" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\open\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "Icon" '$INSTDIR\${MAINBINARYNAME}.exe,0' - WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "" "Open with phoenix code" + WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode" "" "Open with Phoenix Code" WriteRegStr HKCU "Software\Classes\phcodeTSX\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Add a context menu item for folders - WriteRegStr HKCU "Software\Classes\Directory\shell\phcode" "" "Open as phoenix code project" + WriteRegStr HKCU "Software\Classes\Directory\shell\phcode" "" "Open as Phoenix Code project" WriteRegStr HKCU "Software\Classes\Directory\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%1"' ; Optional: Set an icon for the context menu item WriteRegStr HKCU "Software\Classes\Directory\shell\phcode" "Icon" '"$INSTDIR\${MAINBINARYNAME}.exe",0' WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" "" "Open as phoenix code project" WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode" "Icon" '"$INSTDIR\${MAINBINARYNAME}.exe"' WriteRegStr HKCU "SOFTWARE\Classes\Directory\background\shell\phcode\command" "" '"$INSTDIR\${MAINBINARYNAME}.exe" "%V"' + + FunctionEnd Section Install From d88a61f9610bf4ac9bf4e15fb388b96d10cda5b5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jan 2024 20:59:02 +0000 Subject: [PATCH 271/864] chore(deps): update dependency axios to v1.6.7 --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index d30c152c..b4dc4d65 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "phoenix-code-ide", - "version": "3.2.20", + "version": "3.2.23", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.20", + "version": "3.2.23", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.9", "adm-zip": "0.5.10", - "axios": "1.6.6", + "axios": "1.6.7", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", @@ -258,9 +258,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.6.tgz", - "integrity": "sha512-XZLZDFfXKM9U/Y/B4nNynfCRUqNyVZ4sBC/n9GDRCkq9vd2mIvKjKKsbIh1WPmHmNbg6ND7cTBY3Y2+u1G3/2Q==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", "dev": true, "dependencies": { "follow-redirects": "^1.15.4", @@ -1499,9 +1499,9 @@ "dev": true }, "axios": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.6.tgz", - "integrity": "sha512-XZLZDFfXKM9U/Y/B4nNynfCRUqNyVZ4sBC/n9GDRCkq9vd2mIvKjKKsbIh1WPmHmNbg6ND7cTBY3Y2+u1G3/2Q==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", "dev": true, "requires": { "follow-redirects": "^1.15.4", diff --git a/package.json b/package.json index 549879af..17dd4cb4 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.0", - "axios": "1.6.6" + "axios": "1.6.7" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From f27084665fc8bd82d5a75abeb5872862c880f1fa Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 30 Jan 2024 13:18:35 +0530 Subject: [PATCH 272/864] feat: adding support for linux install and uninstall script --- src-build/linux/install.sh | 68 +++++++++++++++++++++++++++++++ src-build/linux/phoenix_icon.png | Bin 0 -> 42130 bytes src-build/linux/uninstall.sh | 36 ++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100755 src-build/linux/install.sh create mode 100644 src-build/linux/phoenix_icon.png create mode 100755 src-build/linux/uninstall.sh diff --git a/src-build/linux/install.sh b/src-build/linux/install.sh new file mode 100755 index 00000000..662bf08e --- /dev/null +++ b/src-build/linux/install.sh @@ -0,0 +1,68 @@ +#!/bin/bash +set -x +# Define the directory to store the AppImage +APPIMAGE_DIR=$HOME/.local/bin + +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + +# Find the first AppImage file in the script's directory with the 'phoenix-code' prefix +APPIMAGE=$(find "$SCRIPT_DIR" -maxdepth 1 -name 'phoenix-code*.AppImage' -print -quit) + +# If no AppImage file is found, exit the script +if [ -z "$APPIMAGE" ]; then + echo "No 'phoenix-code' AppImage file found in the script directory." + exit 1 +fi + +# Extract filename from the full path +APPIMAGE_NAME=$(basename "$APPIMAGE") +NEW_APPIMAGE=phcode.AppImage +ICON=phoenix_icon.png # Ensure this icon file is in the script's directory + +# Create the AppImage directory if it doesn't exist +mkdir -p $APPIMAGE_DIR + +# Create the applications directory if it doesn't exist +DESKTOP_DIR=$HOME/.local/share/applications +mkdir -p $DESKTOP_DIR + +# Copy and rename the AppImage, and copy the icon to the AppImage directory +echo "Installing Phoenix..." +cp "$APPIMAGE" $APPIMAGE_DIR/$NEW_APPIMAGE +cp "$SCRIPT_DIR/$ICON" $APPIMAGE_DIR + +# Make the new AppImage executable +chmod +x $APPIMAGE_DIR/$NEW_APPIMAGE + +# Define MIME types for file extensions +MIME_TYPES="text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;" + +# Add directory association +MIME_TYPES+="inode/directory;" + +# Create a desktop entry for the AppImage with MIME type associations +echo "[Desktop Entry] +Type=Application +Name=Phoenix Code +Exec=$APPIMAGE_DIR/$NEW_APPIMAGE %F +Icon=$APPIMAGE_DIR/$ICON +Terminal=false +MimeType=$MIME_TYPES +" > $DESKTOP_DIR/PhoenixCode.desktop + +# Update the desktop database for GNOME, Unity, XFCE, etc. +if command -v update-desktop-database &> /dev/null +then + update-desktop-database $DESKTOP_DIR +fi + +# Update the KDE desktop database if KDE is in use +if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null + then + kbuildsycoca5 + fi +fi + +echo "Phoenix Code installed successfully." diff --git a/src-build/linux/phoenix_icon.png b/src-build/linux/phoenix_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..451c0be826579fbb6f0025bd6fe4343eb0df2cf2 GIT binary patch literal 42130 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

0HSWCyvWr6B-lL=!WFwQ(N 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 Y6>fI-*oI9n0>D2T%YznGW)%AW0xra9sQ>@~ literal 0 HcmV?d00001 diff --git a/src-build/linux/uninstall.sh b/src-build/linux/uninstall.sh new file mode 100755 index 00000000..93f8d3d3 --- /dev/null +++ b/src-build/linux/uninstall.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# Define the directory where the AppImage and icon are stored +APPIMAGE_DIR=$HOME/.local/bin + +# Name of the installed AppImage and icon file +NEW_APPIMAGE=phcode.AppImage +ICON=phoenix_icon.png + +# Define the desktop directory +DESKTOP_DIR=$HOME/.local/share/applications + +# Remove the AppImage and the icon +echo "Uninstalling Phoenix..." +rm -f $APPIMAGE_DIR/$NEW_APPIMAGE +rm -f $APPIMAGE_DIR/$ICON + +# Remove the desktop entry +rm -f $DESKTOP_DIR/PhoenixCode.desktop + +# Update the desktop database for GNOME, Unity, XFCE, etc. (if available) +if command -v update-desktop-database &> /dev/null +then + update-desktop-database $DESKTOP_DIR +fi + +# Update the KDE desktop database if KDE is in use +if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null + then + kbuildsycoca5 + fi +fi + +echo "Phoenix uninstalled successfully." + From d165734d354a779969252070b1d4372a2275fe3f Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 30 Jan 2024 18:58:04 +0530 Subject: [PATCH 273/864] ci: m1 macs node modules generation --- .github/workflows/tauri-build-dev.yml | 29 ++++++++++++++++++++++- .github/workflows/tauri-build-prod.yml | 29 ++++++++++++++++++++++- .github/workflows/tauri-build-staging.yml | 28 +++++++++++++++++++++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index a8b4fa22..b0b363bb 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -39,8 +39,35 @@ jobs: }) return data.id + build-mac-m1-node-modules: + permissions: + contents: write + timeout-minutes: 15 + runs-on: macos-latest-xlarge + steps: + - uses: actions/checkout@v4 + - name: macos hardware info + run: system_profiler SPSoftwareDataType SPHardwareDataType + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: install frontend dependencies + run: | + npm ci + npm run _ci-cloneAndBuildPhoenix + npm run _ci_make_src-node + cd src-tauri + tar -czvf src-node.tar.gz src-node + cd .. + - name: Upload src-node.tar.gz with installed mac bins + uses: actions/upload-artifact@v2 + with: + name: src-node.tar.gz + path: src-tauri/src-node.tar.gz + build-tauri: - needs: create-release + needs: [create-release, build-mac-m1-node-modules] permissions: contents: write strategy: diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 632b1590..c2dc6630 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -39,8 +39,35 @@ jobs: }) return data.id + build-mac-m1-node-modules: + permissions: + contents: write + timeout-minutes: 15 + runs-on: macos-latest-xlarge + steps: + - uses: actions/checkout@v4 + - name: macos hardware info + run: system_profiler SPSoftwareDataType SPHardwareDataType + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: install frontend dependencies + run: | + npm ci + npm run _ci-cloneAndBuildPhoenix + npm run _ci_make_src-node + cd src-tauri + tar -czvf src-node.tar.gz src-node + cd .. + - name: Upload src-node.tar.gz with installed mac bins + uses: actions/upload-artifact@v2 + with: + name: src-node.tar.gz + path: src-tauri/src-node.tar.gz + build-tauri: - needs: create-release + needs: [create-release, build-mac-m1-node-modules] permissions: contents: write timeout-minutes: 45 diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index cf39de05..a5cd85fc 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -38,9 +38,35 @@ jobs: prerelease: true }) return data.id + build-mac-m1-node-modules: + permissions: + contents: write + timeout-minutes: 15 + runs-on: macos-latest-xlarge + steps: + - uses: actions/checkout@v4 + - name: macos hardware info + run: system_profiler SPSoftwareDataType SPHardwareDataType + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + - name: install frontend dependencies + run: | + npm ci + npm run _ci-cloneAndBuildPhoenix + npm run _ci_make_src-node + cd src-tauri + tar -czvf src-node.tar.gz src-node + cd .. + - name: Upload src-node.tar.gz with installed mac bins + uses: actions/upload-artifact@v2 + with: + name: src-node.tar.gz + path: src-tauri/src-node.tar.gz build-tauri: - needs: create-release + needs: [create-release, build-mac-m1-node-modules] permissions: contents: write strategy: From ea2054027eea49cfd6457efb9a2bb165299f6a42 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 13:30:28 +0000 Subject: [PATCH 274/864] chore(deps): update actions/upload-artifact action to v4 --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index b0b363bb..7e61bef3 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -61,7 +61,7 @@ jobs: tar -czvf src-node.tar.gz src-node cd .. - name: Upload src-node.tar.gz with installed mac bins - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: src-node.tar.gz path: src-tauri/src-node.tar.gz diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index c2dc6630..99da2486 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -61,7 +61,7 @@ jobs: tar -czvf src-node.tar.gz src-node cd .. - name: Upload src-node.tar.gz with installed mac bins - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: src-node.tar.gz path: src-tauri/src-node.tar.gz diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index a5cd85fc..e9ef1362 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -60,7 +60,7 @@ jobs: tar -czvf src-node.tar.gz src-node cd .. - name: Upload src-node.tar.gz with installed mac bins - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: src-node.tar.gz path: src-tauri/src-node.tar.gz From e9d20c236747d14debc269631f24db48809e99da Mon Sep 17 00:00:00 2001 From: charly p abraham Date: Tue, 30 Jan 2024 21:32:33 +0530 Subject: [PATCH 275/864] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5a1246e6..823b313f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Phoenix Desktop -This repo deals with Windows, Mac and Linux Desktop builds of [Phoenix IDE](https://github.com/phcode-dev/phoenix). +This repo deals with Windows, Mac and Linux Desktop builds of [Phoenix Code Editor](https://github.com/phcode-dev/phoenix). Please see https://github.com/phcode-dev/phoenix on how to Contribute or get in touch with the community. @@ -147,4 +147,4 @@ This program is free software: you can redistribute it and/or modify it under th This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. -You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://opensource.org/licenses/AGPL-3.0. \ No newline at end of file +You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://opensource.org/licenses/AGPL-3.0. From 30c33e8f890fbc4b180f44e66ad7f02a8ad676d6 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 30 Jan 2024 21:07:36 +0530 Subject: [PATCH 276/864] test: node built node src --- .github/workflows/tauri-build-dev.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 7e61bef3..beaca9f3 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -99,6 +99,20 @@ jobs: run: | npm ci npm run _ci-release:dev + - name: Download src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + uses: actions/download-artifact@v2 + with: + name: src-node.tar.gz + path: /tmp/src-node.tar.gz + - name: inject src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + run: | + cd src-tauri + rm -rf src-node + tar -xzvf /tmp/src-node.tar.gz + cd .. + - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' run: | From 34fe85b720f469c4d1e6075339807d6471a1bacf Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 30 Jan 2024 21:15:14 +0530 Subject: [PATCH 277/864] node built node src --- .github/workflows/tauri-build-dev.yml | 31 ++++++++++++++++++--------- .gitignore | 2 ++ src-build/mac/filesToSign | 10 ++++----- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index beaca9f3..f3c11e60 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -85,6 +85,14 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20 + + - name: Download src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + uses: actions/download-artifact@v4 + with: + name: src-node.tar.gz + path: /tmp/src-node.tar.gz + - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) @@ -99,19 +107,14 @@ jobs: run: | npm ci npm run _ci-release:dev - - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' - uses: actions/download-artifact@v2 - with: - name: src-node.tar.gz - path: /tmp/src-node.tar.gz - - name: inject src-node built on mac arm (Mac only) + + - name: setup src-node built on mac arm (Mac only) if: matrix.platform == 'macos-latest' run: | - cd src-tauri + ls /tmp/src-node.tar.gz rm -rf src-node - tar -xzvf /tmp/src-node.tar.gz - cd .. + tar -xzvf /tmp/src-node.tar.gz/src-node.tar.gz + ls src-node - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' @@ -217,6 +220,14 @@ jobs: updaterJsonPreferNsis: true tagName: ${{ env.GIT_TAG_NAME }} + - name: inject src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + run: | + ls src-node + rm -rf src-tauri/src-node + mv src-node src-tauri/src-node + ls src-tauri/src-node + - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' run: | diff --git a/.gitignore b/.gitignore index 6ac2d84e..7decb6c7 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,9 @@ lerna-debug.log* node-bins src-build/node-* src-tauri/node-* +src-tauri/src-node.tar.gz src-tauri/src-node +src-node/* src-build/phnode-* src-tauri/phnode-* src-tauri/tauri-local.conf.json diff --git a/src-build/mac/filesToSign b/src-build/mac/filesToSign index 88eeaf46..9804486d 100644 --- a/src-build/mac/filesToSign +++ b/src-build/mac/filesToSign @@ -1,11 +1,11 @@ src-tauri/src-node/node_modules/fsevents/fsevents.node src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.napi.node -src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.napi.node +src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.napi.node src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.abi108.node -src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.abi108.node +src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.abi108.node src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.abi115.node -src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.abi115.node +src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.abi115.node src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/node.abi108.glibc.node -src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.abi108.glibc.node +src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.abi108.glibc.node src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/node.napi.glibc.node -src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.napi.glibc.node +src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.napi.glibc.node From 8618577acaf133ebf0f05b0dd12b37d2d29b72cd Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 30 Jan 2024 23:22:59 +0530 Subject: [PATCH 278/864] fix: sign fails in mac m1 release gen --- src-build/mac/filesToSign | 1 + 1 file changed, 1 insertion(+) diff --git a/src-build/mac/filesToSign b/src-build/mac/filesToSign index 9804486d..5ced227e 100644 --- a/src-build/mac/filesToSign +++ b/src-build/mac/filesToSign @@ -1,4 +1,5 @@ src-tauri/src-node/node_modules/fsevents/fsevents.node +src-node/node_modules/fsevents/fsevents.node src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.napi.node src-node/node_modules/@lmdb/lmdb-darwin-arm64/node.napi.node src-tauri/src-node/node_modules/@lmdb/lmdb-darwin-x64/node.abi108.node From e1b3d5355b68d7b151b5a9364d24aaa4ba90dd3c Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 31 Jan 2024 09:33:32 +0530 Subject: [PATCH 279/864] ci: refactor github interim artifact name from src-node.tar.gz to src-node-darwin-arm64.tar.gz --- .github/workflows/tauri-build-dev.yml | 19 +++++++++++-------- .gitignore | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index f3c11e60..5c3d1805 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -58,13 +58,15 @@ jobs: npm run _ci-cloneAndBuildPhoenix npm run _ci_make_src-node cd src-tauri - tar -czvf src-node.tar.gz src-node + mv src-node src-node-darwin-arm64 + tar -czvf src-node-darwin-arm64.tar.gz src-node-darwin-arm64 + mv src-node-darwin-arm64 src-node cd .. - name: Upload src-node.tar.gz with installed mac bins uses: actions/upload-artifact@v4 with: - name: src-node.tar.gz - path: src-tauri/src-node.tar.gz + name: src-node-darwin-arm64.tar.gz + path: src-tauri/src-node-darwin-arm64.tar.gz build-tauri: needs: [create-release, build-mac-m1-node-modules] @@ -90,8 +92,8 @@ jobs: if: matrix.platform == 'macos-latest' uses: actions/download-artifact@v4 with: - name: src-node.tar.gz - path: /tmp/src-node.tar.gz + name: src-node-darwin-arm64.tar.gz + path: /tmp/src-node-darwin-arm64.tar.gz - name: install Rust stable uses: dtolnay/rust-toolchain@stable @@ -111,10 +113,11 @@ jobs: - name: setup src-node built on mac arm (Mac only) if: matrix.platform == 'macos-latest' run: | - ls /tmp/src-node.tar.gz + ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node - tar -xzvf /tmp/src-node.tar.gz/src-node.tar.gz - ls src-node + tar -xzvf /tmp/src-node-darwin-arm64.tar.gz/src-node-darwin-arm64.tar.gz + ls src-node-darwin-arm64 + mv src-node-darwin-arm64 src-node - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' diff --git a/.gitignore b/.gitignore index 7decb6c7..5b4c7492 100644 --- a/.gitignore +++ b/.gitignore @@ -10,8 +10,9 @@ lerna-debug.log* node-bins src-build/node-* src-tauri/node-* -src-tauri/src-node.tar.gz +src-tauri/src-node-darwin-arm64.tar.gz src-tauri/src-node +src-node-darwin-arm64/* src-node/* src-build/phnode-* src-tauri/phnode-* From d9c20e7ec33a7b21fc5a72826230e30d94eb61c4 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 31 Jan 2024 09:56:19 +0530 Subject: [PATCH 280/864] ci: generate mac m1 pre release builds fix --- .github/workflows/tauri-build-staging.yml | 35 +++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index e9ef1362..28f73309 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -38,6 +38,7 @@ jobs: prerelease: true }) return data.id + build-mac-m1-node-modules: permissions: contents: write @@ -57,13 +58,15 @@ jobs: npm run _ci-cloneAndBuildPhoenix npm run _ci_make_src-node cd src-tauri - tar -czvf src-node.tar.gz src-node + mv src-node src-node-darwin-arm64 + tar -czvf src-node-darwin-arm64.tar.gz src-node-darwin-arm64 + mv src-node-darwin-arm64 src-node cd .. - name: Upload src-node.tar.gz with installed mac bins uses: actions/upload-artifact@v4 with: - name: src-node.tar.gz - path: src-tauri/src-node.tar.gz + name: src-node-darwin-arm64.tar.gz + path: src-tauri/src-node-darwin-arm64.tar.gz build-tauri: needs: [create-release, build-mac-m1-node-modules] @@ -84,6 +87,14 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20 + + - name: Download src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + uses: actions/download-artifact@v4 + with: + name: src-node-darwin-arm64.tar.gz + path: /tmp/src-node-darwin-arm64.tar.gz + - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) @@ -98,6 +109,16 @@ jobs: run: | npm ci npm run _ci-release:staging + + - name: setup src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + run: | + ls /tmp/src-node-darwin-arm64.tar.gz + rm -rf src-node + tar -xzvf /tmp/src-node-darwin-arm64.tar.gz/src-node-darwin-arm64.tar.gz + ls src-node-darwin-arm64 + mv src-node-darwin-arm64 src-node + - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' run: | @@ -202,6 +223,14 @@ jobs: updaterJsonPreferNsis: true tagName: ${{ env.GIT_TAG_NAME }} + - name: inject src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + run: | + ls src-node + rm -rf src-tauri/src-node + mv src-node src-tauri/src-node + ls src-tauri/src-node + - name: setup env for mac arm (Mac only) if: matrix.platform == 'macos-latest' run: | From 1a6b9211c13d71ec5ae8a054e2c366c20fdd19a3 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 31 Jan 2024 10:14:13 +0530 Subject: [PATCH 281/864] fix: prod build egenration for m1 macs --- .github/workflows/tauri-build-dev.yml | 2 + .github/workflows/tauri-build-prod.yml | 45 +++++++++++++++++------ .github/workflows/tauri-build-staging.yml | 2 + 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 5c3d1805..cbb66116 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -72,6 +72,7 @@ jobs: needs: [create-release, build-mac-m1-node-modules] permissions: contents: write + timeout-minutes: 45 strategy: fail-fast: false matrix: @@ -258,6 +259,7 @@ jobs: publish-release: permissions: contents: write + timeout-minutes: 15 runs-on: ubuntu-latest needs: [ create-release, build-tauri ] diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 99da2486..f6a3e795 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -58,13 +58,15 @@ jobs: npm run _ci-cloneAndBuildPhoenix npm run _ci_make_src-node cd src-tauri - tar -czvf src-node.tar.gz src-node + mv src-node src-node-darwin-arm64 + tar -czvf src-node-darwin-arm64.tar.gz src-node-darwin-arm64 + mv src-node-darwin-arm64 src-node cd .. - name: Upload src-node.tar.gz with installed mac bins uses: actions/upload-artifact@v4 with: - name: src-node.tar.gz - path: src-tauri/src-node.tar.gz + name: src-node-darwin-arm64.tar.gz + path: src-tauri/src-node-darwin-arm64.tar.gz build-tauri: needs: [create-release, build-mac-m1-node-modules] @@ -74,14 +76,11 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, macos-latest-xlarge, ubuntu-latest, windows-latest ] + platform: [ macos-latest, ubuntu-latest, windows-latest ] runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v4 - - name: macos hardware info - if: matrix.platform == 'macos-latest-xlarge' - run: system_profiler SPSoftwareDataType SPHardwareDataType - name: get Git Tag shell: bash run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV @@ -89,6 +88,14 @@ jobs: uses: actions/setup-node@v4 with: node-version: 20 + + - name: Download src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + uses: actions/download-artifact@v4 + with: + name: src-node-darwin-arm64.tar.gz + path: /tmp/src-node-darwin-arm64.tar.gz + - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) @@ -104,6 +111,15 @@ jobs: npm ci npm run _ci-release:prod + - name: setup src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + run: | + ls /tmp/src-node-darwin-arm64.tar.gz + rm -rf src-node + tar -xzvf /tmp/src-node-darwin-arm64.tar.gz/src-node-darwin-arm64.tar.gz + ls src-node-darwin-arm64 + mv src-node-darwin-arm64 src-node + - name: install AzureSignTool (windows only) if: matrix.platform == 'windows-latest' run: | @@ -150,7 +166,7 @@ jobs: shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-latest' || matrix.platform == 'macos-latest-xlarge' + if: matrix.platform == 'macos-latest' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -193,7 +209,6 @@ jobs: shell: bash - uses: tauri-apps/tauri-action@v0 - if: matrix.platform != 'macos-latest-xlarge' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} @@ -210,13 +225,21 @@ jobs: updaterJsonPreferNsis: true tagName: ${{ env.GIT_TAG_NAME }} + - name: inject src-node built on mac arm (Mac only) + if: matrix.platform == 'macos-latest' + run: | + ls src-node + rm -rf src-tauri/src-node + mv src-node src-tauri/src-node + ls src-tauri/src-node + - name: setup env for mac arm (Mac only) - if: matrix.platform == 'macos-latest-xlarge' + if: matrix.platform == 'macos-latest' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-latest-xlarge' + if: matrix.platform == 'macos-latest' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 28f73309..d4c3048d 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -72,6 +72,7 @@ jobs: needs: [create-release, build-mac-m1-node-modules] permissions: contents: write + timeout-minutes: 45 strategy: fail-fast: false matrix: @@ -258,6 +259,7 @@ jobs: publish-release: permissions: contents: write + timeout-minutes: 15 runs-on: ubuntu-latest needs: [ create-release, build-tauri ] From 69115c25fa48a4690185a7d1d5c5b486b222e256 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 31 Jan 2024 11:18:28 +0530 Subject: [PATCH 282/864] ci: increase release build gen timeout to 60 mins --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index cbb66116..aeff1c28 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -72,7 +72,7 @@ jobs: needs: [create-release, build-mac-m1-node-modules] permissions: contents: write - timeout-minutes: 45 + timeout-minutes: 60 strategy: fail-fast: false matrix: diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index f6a3e795..880f870d 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -72,7 +72,7 @@ jobs: needs: [create-release, build-mac-m1-node-modules] permissions: contents: write - timeout-minutes: 45 + timeout-minutes: 60 strategy: fail-fast: false matrix: diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index d4c3048d..7fbec7d1 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -72,7 +72,7 @@ jobs: needs: [create-release, build-mac-m1-node-modules] permissions: contents: write - timeout-minutes: 45 + timeout-minutes: 60 strategy: fail-fast: false matrix: From ff2dcd4863d49d277b3a4919763c9aba58771196 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 13:25:11 +0530 Subject: [PATCH 283/864] feat: adding support for free m1 runner in devo --- .github/workflows/tauri-build-staging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 7fbec7d1..e95275fe 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -43,7 +43,7 @@ jobs: permissions: contents: write timeout-minutes: 15 - runs-on: macos-latest-xlarge + runs-on: macos-14 steps: - uses: actions/checkout@v4 - name: macos hardware info From 509651842710f227413725fa41413f26fce8be5d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 18:20:34 +0000 Subject: [PATCH 284/864] chore(deps): update nick-fields/retry action to v3 --- .github/workflows/desktop-linux-test-pull.yml | 10 +++---- .github/workflows/desktop-mac-test-pull.yml | 10 +++---- .../workflows/desktop-windows-test-pull.yml | 10 +++---- .../prod-desktop-mac-m1-tests-on-pull.yml | 10 +++---- .../workflows/prod-desktop-tests-on-pull.yml | 30 +++++++++---------- .../staging-desktop-tests-on-pull.yml | 26 ++++++++-------- 6 files changed, 48 insertions(+), 48 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index bf05e28f..fccd1010 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -45,35 +45,35 @@ jobs: npm run releaseDistTestDebug - name: Run tauri unit tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - name: Run tauri integration tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - name: Run tauri mainview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - name: Run tauri livepreview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 20 max_attempts: 3 diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 8034c01c..276ea26a 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -38,35 +38,35 @@ jobs: npm run releaseDistTestDebug - name: Run tauri unit tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - name: Run tauri integration tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - name: Run tauri mainview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - name: Run tauri livepreview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 30 max_attempts: 3 diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index 614c724d..ea7a36a1 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -39,7 +39,7 @@ jobs: - name: Run tauri unit tests in windows # GUI apps in windows doesn't log on console. so we capture the output to a text file and print it, then fail on error. - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunUnit continue-on-error: true with: @@ -53,7 +53,7 @@ jobs: shell: cmd - name: Run tauri integration tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunIntegration continue-on-error: true with: @@ -67,7 +67,7 @@ jobs: shell: cmd - name: Run tauri mainview tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunMainview continue-on-error: true with: @@ -81,7 +81,7 @@ jobs: shell: cmd - name: Run tauri livepreview tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunLivepreview continue-on-error: true with: @@ -95,7 +95,7 @@ jobs: shell: cmd - name: Run tauri LegacyInteg tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunLegacyInteg continue-on-error: true with: diff --git a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml index d94e890f..07b7b010 100644 --- a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml @@ -40,35 +40,35 @@ jobs: npm run releaseDistTestDebug - name: Run tauri unit tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 10 max_attempts: 2 command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - name: Run tauri integration tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 10 max_attempts: 2 command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - name: Run tauri mainview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 10 max_attempts: 2 command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - name: Run tauri livepreview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 10 max_attempts: 2 command: ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 30 max_attempts: 1 diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index 3bf21e38..41349bd6 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -43,35 +43,35 @@ jobs: npm run releaseDistTestDebug - name: Run tauri unit tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - name: Run tauri integration tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - name: Run tauri mainview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - name: Run tauri livepreview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 20 max_attempts: 3 @@ -107,35 +107,35 @@ jobs: npm run releaseDistTestDebug - name: Run tauri unit tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - name: Run tauri integration tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - name: Run tauri mainview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - name: Run tauri livepreview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 30 max_attempts: 3 @@ -172,7 +172,7 @@ jobs: - name: Run tauri unit tests in windows # GUI apps in windows doesn't log on console. so we capture the output to a text file and print it, then fail on error. - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunUnit continue-on-error: true with: @@ -186,7 +186,7 @@ jobs: shell: cmd - name: Run tauri integration tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunIntegration continue-on-error: true with: @@ -200,7 +200,7 @@ jobs: shell: cmd - name: Run tauri mainview tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunMainview continue-on-error: true with: @@ -214,7 +214,7 @@ jobs: shell: cmd - name: Run tauri livepreview tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunLivepreview continue-on-error: true with: @@ -228,7 +228,7 @@ jobs: shell: cmd - name: Run tauri LegacyInteg tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunLegacyInteg continue-on-error: true with: diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index 7c52431c..4b29e81b 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -43,28 +43,28 @@ jobs: npm run releaseDistTestDebug - name: Run tauri unit tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - name: Run tauri integration tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - name: Run tauri mainview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 20 max_attempts: 3 @@ -100,28 +100,28 @@ jobs: npm run releaseDistTestDebug - name: Run tauri unit tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - name: Run tauri integration tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - name: Run tauri mainview tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 12 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 with: timeout_minutes: 30 max_attempts: 3 @@ -158,7 +158,7 @@ jobs: - name: Run tauri unit tests in windows # GUI apps in windows doesn't log on console. so we capture the output to a text file and print it, then fail on error. - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunUnit continue-on-error: true with: @@ -172,7 +172,7 @@ jobs: shell: cmd - name: Run tauri integration tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunIntegration continue-on-error: true with: @@ -186,7 +186,7 @@ jobs: shell: cmd - name: Run tauri mainview tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunMainview continue-on-error: true with: @@ -200,7 +200,7 @@ jobs: shell: cmd - name: Run tauri livepreview tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunLivepreview continue-on-error: true with: @@ -214,7 +214,7 @@ jobs: shell: cmd - name: Run tauri LegacyInteg tests in windows - uses: nick-fields/retry@v2 + uses: nick-fields/retry@v3 id: windowsRunLegacyInteg continue-on-error: true with: From fbf05ea309a2ed3a25be4b230ee78c1ebb26a0f2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 Jan 2024 13:36:50 +0000 Subject: [PATCH 285/864] chore(deps): update peter-evans/create-pull-request action to v6 --- .github/workflows/update-phcode-build.yml | 2 +- .github/workflows/updateNotification.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index fb081895..8da5dc58 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -33,7 +33,7 @@ jobs: - name: Create phcode patch update Pull Request id: cpr - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v6 with: commit-message: 'ci: update phcode version to ${{ env.PHOENIX_VERSION }}' committer: GitHub diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml index 31fceb46..291f8c5c 100644 --- a/.github/workflows/updateNotification.yml +++ b/.github/workflows/updateNotification.yml @@ -32,7 +32,7 @@ jobs: - name: Create update notification Pull Request id: cpr - uses: peter-evans/create-pull-request@v5 + uses: peter-evans/create-pull-request@v6 with: commit-message: 'ci: tauri release update notification json' committer: GitHub From cbb76f33e2b1b0a0f20e6842f3b3805a6f2c6ae8 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 1 Feb 2024 14:11:01 +0530 Subject: [PATCH 286/864] ci: m1 macs in github actions --- ...-pull.yml => desktop-mac-m1-test-pull.yml} | 26 +++++++++---------- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) rename .github/workflows/{prod-desktop-mac-m1-tests-on-pull.yml => desktop-mac-m1-test-pull.yml} (81%) diff --git a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml b/.github/workflows/desktop-mac-m1-test-pull.yml similarity index 81% rename from .github/workflows/prod-desktop-mac-m1-tests-on-pull.yml rename to .github/workflows/desktop-mac-m1-test-pull.yml index 07b7b010..26432218 100644 --- a/.github/workflows/prod-desktop-mac-m1-tests-on-pull.yml +++ b/.github/workflows/desktop-mac-m1-test-pull.yml @@ -1,7 +1,7 @@ -name: 'Expensive Desktop-mac M1 prod only full test suite run on pull request' +name: 'Desktop-mac M1 full test suite run on pull request' on: pull_request: - branches: [ prod ] + branches: [ main ] concurrency: group: pr-desktop-mac-m1-${{ github.event.pull_request.number }} @@ -9,8 +9,8 @@ concurrency: jobs: test-desktop-mac-m1: - runs-on: macos-latest-xlarge - timeout-minutes: 45 + runs-on: macos-14 + timeout-minutes: 90 steps: - uses: actions/checkout@v4 - name: macos hardware info @@ -42,34 +42,34 @@ jobs: - name: Run tauri unit tests uses: nick-fields/retry@v3 with: - timeout_minutes: 10 - max_attempts: 2 + timeout_minutes: 12 + max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - name: Run tauri integration tests uses: nick-fields/retry@v3 with: - timeout_minutes: 10 - max_attempts: 2 + timeout_minutes: 12 + max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - name: Run tauri mainview tests uses: nick-fields/retry@v3 with: - timeout_minutes: 10 - max_attempts: 2 + timeout_minutes: 12 + max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - name: Run tauri livepreview tests uses: nick-fields/retry@v3 with: - timeout_minutes: 10 - max_attempts: 2 + timeout_minutes: 12 + max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v3 with: timeout_minutes: 30 - max_attempts: 1 + max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index aeff1c28..b0df61d5 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -43,7 +43,7 @@ jobs: permissions: contents: write timeout-minutes: 15 - runs-on: macos-latest-xlarge + runs-on: macos-14 steps: - uses: actions/checkout@v4 - name: macos hardware info diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 880f870d..8bc43f50 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -43,7 +43,7 @@ jobs: permissions: contents: write timeout-minutes: 15 - runs-on: macos-latest-xlarge + runs-on: macos-14 steps: - uses: actions/checkout@v4 - name: macos hardware info From cc9cf42cbf8985bf6ae7f681bd50992cc21518e3 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 14:32:35 +0530 Subject: [PATCH 287/864] feat: merge installer and unistall script --- src-build/linux/install.sh | 68 ----------------------- src-build/linux/installer.sh | 104 +++++++++++++++++++++++++++++++++++ src-build/linux/uninstall.sh | 36 ------------ 3 files changed, 104 insertions(+), 104 deletions(-) delete mode 100755 src-build/linux/install.sh create mode 100644 src-build/linux/installer.sh delete mode 100755 src-build/linux/uninstall.sh diff --git a/src-build/linux/install.sh b/src-build/linux/install.sh deleted file mode 100755 index 662bf08e..00000000 --- a/src-build/linux/install.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/bash -set -x -# Define the directory to store the AppImage -APPIMAGE_DIR=$HOME/.local/bin - -# Get the directory where the script is located -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" - -# Find the first AppImage file in the script's directory with the 'phoenix-code' prefix -APPIMAGE=$(find "$SCRIPT_DIR" -maxdepth 1 -name 'phoenix-code*.AppImage' -print -quit) - -# If no AppImage file is found, exit the script -if [ -z "$APPIMAGE" ]; then - echo "No 'phoenix-code' AppImage file found in the script directory." - exit 1 -fi - -# Extract filename from the full path -APPIMAGE_NAME=$(basename "$APPIMAGE") -NEW_APPIMAGE=phcode.AppImage -ICON=phoenix_icon.png # Ensure this icon file is in the script's directory - -# Create the AppImage directory if it doesn't exist -mkdir -p $APPIMAGE_DIR - -# Create the applications directory if it doesn't exist -DESKTOP_DIR=$HOME/.local/share/applications -mkdir -p $DESKTOP_DIR - -# Copy and rename the AppImage, and copy the icon to the AppImage directory -echo "Installing Phoenix..." -cp "$APPIMAGE" $APPIMAGE_DIR/$NEW_APPIMAGE -cp "$SCRIPT_DIR/$ICON" $APPIMAGE_DIR - -# Make the new AppImage executable -chmod +x $APPIMAGE_DIR/$NEW_APPIMAGE - -# Define MIME types for file extensions -MIME_TYPES="text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;" - -# Add directory association -MIME_TYPES+="inode/directory;" - -# Create a desktop entry for the AppImage with MIME type associations -echo "[Desktop Entry] -Type=Application -Name=Phoenix Code -Exec=$APPIMAGE_DIR/$NEW_APPIMAGE %F -Icon=$APPIMAGE_DIR/$ICON -Terminal=false -MimeType=$MIME_TYPES -" > $DESKTOP_DIR/PhoenixCode.desktop - -# Update the desktop database for GNOME, Unity, XFCE, etc. -if command -v update-desktop-database &> /dev/null -then - update-desktop-database $DESKTOP_DIR -fi - -# Update the KDE desktop database if KDE is in use -if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null - then - kbuildsycoca5 - fi -fi - -echo "Phoenix Code installed successfully." diff --git a/src-build/linux/installer.sh b/src-build/linux/installer.sh new file mode 100644 index 00000000..354f2817 --- /dev/null +++ b/src-build/linux/installer.sh @@ -0,0 +1,104 @@ +#!/bin/bash +# Define common variables +APPIMAGE_DIR=$HOME/.local/bin +DESKTOP_DIR=$HOME/.local/share/applications +NEW_APPIMAGE=phcode.AppImage +ICON=phoenix_icon.png +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + +install() { + # Define the directory to store the AppImage + # Get the directory where the script is located + # Find the first AppImage file in the script's directory with the 'phoenix-code' prefix + APPIMAGE=$(find "$SCRIPT_DIR" -maxdepth 1 -name 'phoenix-code*.AppImage' -print -quit) + + # If no AppImage file is found, exit the script + if [ -z "$APPIMAGE" ]; then + echo "No 'phoenix-code' AppImage file found in the script directory." + exit 1 + fi + + # Extract filename from the full path + APPIMAGE_NAME=$(basename "$APPIMAGE") + ICON=phoenix_icon.png # Ensure this icon file is in the script's directory + + # Create the AppImage directory if it doesn't exist + mkdir -p $APPIMAGE_DIR + + # Create the applications directory if it doesn't exist + mkdir -p $DESKTOP_DIR + + # Copy and rename the AppImage, and copy the icon to the AppImage directory + echo "Installing Phoenix..." + cp "$APPIMAGE" $APPIMAGE_DIR/$NEW_APPIMAGE + cp "$SCRIPT_DIR/$ICON" $APPIMAGE_DIR + + # Make the new AppImage executable + chmod +x $APPIMAGE_DIR/$NEW_APPIMAGE + + # Define MIME types for file extensions + MIME_TYPES="text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;" + + # Add directory association + MIME_TYPES+="inode/directory;" + + # Create a desktop entry for the AppImage with MIME type associations +cat > $DESKTOP_DIR/PhoenixCode.desktop < /dev/null + then + update-desktop-database $DESKTOP_DIR + fi + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null + then + kbuildsycoca5 + fi + fi + + echo "Phoenix Code installed successfully." +} + +uninstall() { + # Remove the AppImage and the icon + echo "Uninstalling Phoenix..." + rm -f $APPIMAGE_DIR/$NEW_APPIMAGE + rm -f $APPIMAGE_DIR/$ICON + + # Remove the desktop entry + rm -f $DESKTOP_DIR/PhoenixCode.desktop + + # Update the desktop database for GNOME, Unity, XFCE, etc. (if available) + if command -v update-desktop-database &> /dev/null + then + update-desktop-database $DESKTOP_DIR + fi + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null + then + kbuildsycoca5 + fi + fi + + echo "Phoenix uninstalled successfully." +} + +# Check for command-line arguments +if [[ "$1" == "--uninstall" ]]; then + uninstall +else + install +fi diff --git a/src-build/linux/uninstall.sh b/src-build/linux/uninstall.sh deleted file mode 100755 index 93f8d3d3..00000000 --- a/src-build/linux/uninstall.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# Define the directory where the AppImage and icon are stored -APPIMAGE_DIR=$HOME/.local/bin - -# Name of the installed AppImage and icon file -NEW_APPIMAGE=phcode.AppImage -ICON=phoenix_icon.png - -# Define the desktop directory -DESKTOP_DIR=$HOME/.local/share/applications - -# Remove the AppImage and the icon -echo "Uninstalling Phoenix..." -rm -f $APPIMAGE_DIR/$NEW_APPIMAGE -rm -f $APPIMAGE_DIR/$ICON - -# Remove the desktop entry -rm -f $DESKTOP_DIR/PhoenixCode.desktop - -# Update the desktop database for GNOME, Unity, XFCE, etc. (if available) -if command -v update-desktop-database &> /dev/null -then - update-desktop-database $DESKTOP_DIR -fi - -# Update the KDE desktop database if KDE is in use -if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null - then - kbuildsycoca5 - fi -fi - -echo "Phoenix uninstalled successfully." - From 7083415650b93b8776da34da3f8157f4c6cae61e Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 15:30:40 +0530 Subject: [PATCH 288/864] chore: adding phoenix icon for app distribution --- docs/icons/phoenix_icon.png | Bin 0 -> 42130 bytes src-build/linux/installer.sh | 36 ++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 docs/icons/phoenix_icon.png diff --git a/docs/icons/phoenix_icon.png b/docs/icons/phoenix_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..451c0be826579fbb6f0025bd6fe4343eb0df2cf2 GIT binary patch literal 42130 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

0HSWCyvWr6B-lL=!WFwQ(N zMOn(=%mMR-!prN3LA1PQ; zoL{s%5lq}}#@YRYA7LD{y3A;dE{jj^wL&@UJTC{#?ExuZh$)4PRc;Wz45;x0JUAl9 z`L-+>llb38WB`xTTH;m4ZOeq?7dNoYO{tXSDs0~vz!ZTy+aF8+4A)iqIbmRqB)i&G zD=UF3p_2`vrA{Nt#40(C1MrLacvnHe{MTD;f|3%vkGpO;Rr}p(S=Y81@obhoz#MB1S>HjdX{HpO(OTR=FgX*(q<}zxufLFwsKj}iujgaq|KtN4 znO>IW0K+jh=+^)E-jtf&?3c~24iCVRgie=72V5oj(Re>Es?v&7l3Vr*i1&D|hT8jy z$^o&Oy*JB2(2!6*w71i zaeZSYd#-n;{BrVd-WWp1W`F^MPz?v?y~&~@;HuTkg1i77>TW9O)LV`K5A!JZU|3(-ngTD%cvl) za;BcY$yAuCFI9nI=Ijb1u9J0#53y4=@Np;2Km+M`Fs{4>I6vGraRiAwcAhxg%rpa@ zWnEazsGL(!fZk`o6>rPro&JU#8`b4R!bOje`;L@@9{BEe;nQ1qduc$U^cE|Rg`-8f zxo^s~cmN_7>v>u3_u)Z^lbr%?oJzb|~ z5kFZV_`5Rg)QcF8Y^oCvr+OQ(UcfhvABg+B#C7I}jJF&YEBZSo0h+nOJ@ZUz*qZrK zw+2m`yP-(1Pbl9nD%u7S0UZ)Hk$JWw&jU6lY85GBL;28f?cJi##}KK|EnyxakIMu&p*G`j3Ui)|~gG0MqpE zrN_esNIBF%ZE6Nv^L1T7%!JdL(|i7_f~-rmsrwS2aM98UTEE%_Agxk|@%Eb|LQI+I z%&(B}BSLk__!d~6Ot#Qo)S$Nov}}I88o!ia3}8P%uTOTl@B*Q1-7d+2(K1Nen)X8w z=5xB1;#*@s7p2Xu>urlGr4%+YC(9%echyw)o8lTHaKxGi&acNjQ``^aHWt`|1nyl* zX66=57q9pp2?>i&0uZDs0?Qkpw@retwK3MtR_>1FHW^RW)f-dG?hX4> zL77~$d2hZYOc{%k`rQZVw93=mR8)ukL0-iRivpD!XlaCmc_pyfF2X;8?F+ z-AvzO(J2hIEw5-IXFnib4S6vYD-O$>_&L^__UV<8 zs$3vEIg)D+Rp$-ZL0Y5`s%!RKYLkH-30mhb0whDxDK@+q?q^(Gl$U|bL}1;iSLOygYM#{vv0-X;9yU=43t-vZdI9!P< zhOx4+Sq-t$r|AygR4&yIt4|w?P&=Kq#zN_ulk{4sf_X zsN~hZ!{MPQT;H%>=Yv2oNDJLt3`!dLo#VUP@G8=+(!;7UD@jT=gDTF4yw8txzD(WKthd_)yvLnfntKDZ;`WD14+J)4 z{%#DJ721?R3=kx3)2b;M$ZW|K_HqJw`A!Nq$4toerZ4+l`wWQV7N@=GE^q*R$5OMY z2R9mC*qIXj)=3UC_`Vvvc4%&a_}ae^R|nf{jP_;Smo1L*WSe`8p+0`nI8u`~0x z54Q*|B{5*Ecff<`|4FQ?8k=@NH(>akUQAE>W@`I#-GT8J1{4yiF-89#9PC$2-A<{O zVD1f=Ej}rRnO}X`zzr3cFDgGA;f3+bCxS;Xj0!g+2mzf2_MUC#C=CSrVZri&luAB5 z8D>c7eR^gee{(5d_R5{r@F2dl$|?U&r$(AwPGdq z{0V$)LS{?Qw51W|ds$Xs@B6A=Okd^Z9AT?K(vQEQ(uBT=*DFLiVK)twpCB$NXx}>9 zay6FeX@(g2Bdz~wcjQjpMfo&v=O5T-;ko4t;1F@hu-M8`pZd#uWAs3RRtLL_N_qjW zn1^@~ka3qz3-k+#&su04OvF%K3UxA$|8+toX}~n?_czTh$c!H%jli<^QY0LJ6K?VZ zPJNkp%ewg6X15?^VIT{P|Bvw^7q^zR)uBMX@d$JFO6pE>xU^OokI^4{v}>Yh99Z|c zU@lTuOg->YcNaK4UzUZ--|2xjbL<%7-j*6Uj~GT$5_)7HB$rnY8Sj1v+6tUnk-fJA zc-5k7OmuGESR8otKSy)JDtEScll|hUy~g1(fgfUaI`Mc->VOQ*<-qkB#r6CBJz(_t zYAU>GCSdR}fG7V7L_%_719wo3MjoMs1eR7z1Xhf1T%w9#DXheV1GV+`xFee32vqbn*~CSHji4@oA3IKE55A2=Dbl?5e^m#9)`o7gCeS=Rlij8 zv3s_kS4#fB<&#aHAd6A%em$#OlZ6C(0*@#O+xMGbRAwyUuTBBR`z;MW>^ug#knC&1 z`u_x%Z&ji#dFgGO_qEzQDi4sN0=C`X!%{ewJDy5##$IlD!}%#i@ZiE?8G1mN~u&L?SKG|wA{w=&(j>&w~qgH4W*M6G&fskSmDwOgAKAw&Q zG;rIxx}9cZ;q0L_P-p#$1-)-e^=w(<~n|+JhAMB_+@1QpJny0b%tEqTPgmS zn#ZMPXNh$fDvF#1o*vs$zX(a%+(BHRpIk9cTbLh9+rX(f(!L9HaU@UUVDNpPnA440n4AM<`{b0xmd?thj4 zrwT8r0NVYttxPU4Kt@YQaq=D}00yyn0XupNk&Dir4TJkkcou=$^J|jf^Y0U1YwB6I znD>o?Ni#CUG^%Yp*+|mQDEq?_T?xD0f;=xCPYTH?o_`D2<9pf4Bf`E?! z_)B)oMbTW}b`>*V0Q%6`;vcR~SmjjC2LRlJiF$Upmq*u_NMMA;D4ZB|E?0pWJXG-% zltU3dW0N%5)IM*F^0olvx0*P-zZ`gf>Q{3cW|t-1xfq$Zd;rtJsQ;7iVVOx`)K*|y+ zKor*`mjRToPA?wjS?YrKT__UPq5XgVp9H`>1V^+5>iARoMToI@$H+FeZQOJ)-kpaN zco#a}rXqUdpFY58^T@1Udc*SdFz|%oes@+KWEBzDaPdjXXKA=-Z~E{bt?mE1r8ji} z35`w$U@wl&vAf+mNT_?e+m{s}+?OR)pfAnao^j|e9%M`_4m|jShp9IGTQCy(lFHoR Y6>fI-*oI9n0>D2T%YznGW)%AW0xra9sQ>@~ literal 0 HcmV?d00001 diff --git a/src-build/linux/installer.sh b/src-build/linux/installer.sh index 354f2817..90066d20 100644 --- a/src-build/linux/installer.sh +++ b/src-build/linux/installer.sh @@ -4,9 +4,43 @@ APPIMAGE_DIR=$HOME/.local/bin DESKTOP_DIR=$HOME/.local/share/applications NEW_APPIMAGE=phcode.AppImage ICON=phoenix_icon.png -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +GITHUB_REPO="charlypa/phoenix-desktop" +API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" install() { + # Fetch the latest release data from GitHub + echo "Fetching latest release from $GITHUB_REPO..." + wget -qO- $API_URL > latest_release.json + + # Extract the download URL for the AppImage + APPIMAGE_URL=$(grep -oP '"browser_download_url": "\K(.*phoenix-desktop.*\.AppImage)(?=")' latest_release.json) + + # If no AppImage URL is found, exit the script + if [ -z "$APPIMAGE_URL" ]; then + echo "No AppImage URL found in the latest release." + rm latest_release.json + exit 1 + fi + + # Download the AppImage + echo "Downloading AppImage from $APPIMAGE_URL..." + wget -qO $NEW_APPIMAGE $APPIMAGE_URL + + # Remove the temporary JSON file + rm latest_release.json + + # Proceed with installation steps as before... + # Create necessary directories + mkdir -p $APPIMAGE_DIR + mkdir -p $DESKTOP_DIR + + # Copy and rename the AppImage, and copy the icon to the AppImage directory + echo "Installing Phoenix..." + mv $NEW_APPIMAGE $APPIMAGE_DIR/$NEW_APPIMAGE + cp "$ICON" $APPIMAGE_DIR # Ensure this icon file is in the current directory + + # Make the new AppImage executable + chmod +x $APPIMAGE_DIR/$NEW_APPIMAGE # Define the directory to store the AppImage # Get the directory where the script is located # Find the first AppImage file in the script's directory with the 'phoenix-code' prefix From ad6dd6a425e23d83c160eec427f75f0259af78c3 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 1 Feb 2024 17:21:08 +0530 Subject: [PATCH 289/864] chore: update cname for github pages --- docs/CNAME | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/CNAME diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 00000000..9cf83537 --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +updates.phcode.io \ No newline at end of file From c17e9a2900120eb048733c6dab058f171b3bfcc6 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 18:04:03 +0530 Subject: [PATCH 290/864] feat: installer for linux gnome and kde --- src-build/linux/installer.sh | 35 +++++-------------------------- src-build/linux/phoenix_icon.png | Bin 42130 -> 0 bytes 2 files changed, 5 insertions(+), 30 deletions(-) mode change 100644 => 100755 src-build/linux/installer.sh delete mode 100644 src-build/linux/phoenix_icon.png diff --git a/src-build/linux/installer.sh b/src-build/linux/installer.sh old mode 100644 new mode 100755 index 90066d20..01c70d36 --- a/src-build/linux/installer.sh +++ b/src-build/linux/installer.sh @@ -6,6 +6,7 @@ NEW_APPIMAGE=phcode.AppImage ICON=phoenix_icon.png GITHUB_REPO="charlypa/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" +ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" install() { # Fetch the latest release data from GitHub @@ -24,11 +25,12 @@ install() { # Download the AppImage echo "Downloading AppImage from $APPIMAGE_URL..." - wget -qO $NEW_APPIMAGE $APPIMAGE_URL - + wget --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL + wget --show-progress -qO $ICON $ICON_URL # Remove the temporary JSON file rm latest_release.json + # Proceed with installation steps as before... # Create necessary directories mkdir -p $APPIMAGE_DIR @@ -37,38 +39,11 @@ install() { # Copy and rename the AppImage, and copy the icon to the AppImage directory echo "Installing Phoenix..." mv $NEW_APPIMAGE $APPIMAGE_DIR/$NEW_APPIMAGE - cp "$ICON" $APPIMAGE_DIR # Ensure this icon file is in the current directory + mv "$ICON" $APPIMAGE_DIR # Ensure this icon file is in the current directory # Make the new AppImage executable chmod +x $APPIMAGE_DIR/$NEW_APPIMAGE - # Define the directory to store the AppImage - # Get the directory where the script is located - # Find the first AppImage file in the script's directory with the 'phoenix-code' prefix - APPIMAGE=$(find "$SCRIPT_DIR" -maxdepth 1 -name 'phoenix-code*.AppImage' -print -quit) - - # If no AppImage file is found, exit the script - if [ -z "$APPIMAGE" ]; then - echo "No 'phoenix-code' AppImage file found in the script directory." - exit 1 - fi - - # Extract filename from the full path - APPIMAGE_NAME=$(basename "$APPIMAGE") - ICON=phoenix_icon.png # Ensure this icon file is in the script's directory - - # Create the AppImage directory if it doesn't exist - mkdir -p $APPIMAGE_DIR - # Create the applications directory if it doesn't exist - mkdir -p $DESKTOP_DIR - - # Copy and rename the AppImage, and copy the icon to the AppImage directory - echo "Installing Phoenix..." - cp "$APPIMAGE" $APPIMAGE_DIR/$NEW_APPIMAGE - cp "$SCRIPT_DIR/$ICON" $APPIMAGE_DIR - - # Make the new AppImage executable - chmod +x $APPIMAGE_DIR/$NEW_APPIMAGE # Define MIME types for file extensions MIME_TYPES="text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;" diff --git a/src-build/linux/phoenix_icon.png b/src-build/linux/phoenix_icon.png deleted file mode 100644 index 451c0be826579fbb6f0025bd6fe4343eb0df2cf2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42130 zcmZ5{cRbbc_y7A|7uU+YwybNDy=7jz5F&eBTQ(sx_u8u{63HlKBq4jmC5g;35(&xP zn~2|=KHv5G>)yxpdLQR~&hwn}Jm>X#B^c;wQIK9H1pt8J`ZaY!0DyvDp#Yo+{MZc| z{sVqM?igyR0&n}7mjD0-Tvu1Q6=bveo}`)C>G8pty#Aiw0hc2u6W6;aKIkPB%nL@< z{(|%RxTzy^lnC@QK#+*NWV5G1_%NrUS&saHhYUm=#mmjcj8=D$eb{E2VGjAylT%9U<-M?{lKr=NDfq<%_;cy5$LJmqJ zm-5k$9R-WVp8pDP0KeJ)`>(1{4nTEm@z=ZmdH@M*lY@_4tcJ5gkN~@fzpweZr1PKP zKrqoiF=%*nDi)4KNH^9C{*#RF4}FlwdSA1UYDX3zN~_^~+Bq>+ds{JQ&!cgKF#&Mh zqoX_f_b`SA;%u;dN_hN16^dua^m3`vOj7`gpA70g4es%33(8nB=D@KgUe;ST{{3f7 z;PfWa$&&%W)4Pe-2)IakNzJmqro#@@Mbj)?iqNn;YL+*7qFyl1);Z@FDv*XB}n!eB& zICkDszS8R7n_fXo$0?0?UgBP`j3$H2rsJfAFzVk5CFVzR@U|FklA z1StD`jo!r`-Np_OY}(;%X3GyaF*PJ|twLL4dAsYbKTE*}yeAUo{_}u3W@7Sv+Biq0 zk%~Vn!!Z!=s%CGd8x|~1-CDL#9Vg>9_3b5nBH;QpmbxnD0%sUW+!|$X9+k|Nxo8d< zhB7qNRwkJt$OsuO_AdCt&^y`+CO^Nj|G*AMgdF=4@#`(J|JmF47ShdipkaMle1G7T zLBl!~WYB7jdzAD7x@ZUvcTC?eDL!hbAsdIgZ8L+|WEKd}^#AgD!6NwVOjU^kXjT&P z`%mOZrUM6Tb(Tb(Pk^v2oOP+>d?EQ)<<)BnM<$QwB>UDlfTx8e9R~lv)F7leY>|o*9kzCbtpuXo#HilhsrwIoCAdvI zH=j2b@~gtoLz0gfuAB!UTn6|2lzRW>^c|8zW&-NJ`6~DjiKtgw*9Owk&2qO3dY$>z zVCbsq^fCU6!k^Ruokz*j zAB$CVw%Q#A4A}(pdM<_easbdNb^H8t0HB`13=f14`3UIK+Pi^}up)H5)azl|YS)qM zmM4=iLeO-PnpD&mrnBR~1FuX472qD$Pz*c6q||0awxNG5GDS(fDB5K$f?W#YE)jr-kR^m)q#8P2{NMN1*Q>(~A@tBN z25hZGqb^=VcY4J$VMOHHyWIRILQvGA5Z6A*IdCm9K_JQqf9!;ESOL=*VC!;IHgtxG zprk8jR{3o4Sn937;Kw8Y?!Oc7dm(<5yJGHb8jpXClU}Xvvw>bV_7|=!&3`43BKJ4z z&+#y^c7;rCBt(q=n!fKy`8eJE!5)6JidLDO2)(R6x;k^Hiei;p`Jg7{I3 z?76U!kQR1BDbQ^^K9{Jy0T>|4Utatz@y5qFY-^c*#mog$N(DiT6(T=eEH2Z)ZrF+n zJ#M34oz{) zFkN@7a(3qCtGc^frUT}Gh7AaoDXkuZNc+ZRpL&k8{2KVC$o#?VGFI{O;`C(5h{jz!fbj&YrfcSS8PE)I2kj5d93e63HImz^%XPyCw+ih7VQ=h_ z0K^?3rgdR;QdsOC`qdKb9sKv}5owo~s3pz>=@P8;l1y5DUXzbBse@zlYvRW^FEsIk zsvWR4)rr5bCEQtn=z3Jh%iGPcy|~iw%yI3kxDWvuoaQxpO%DYjP)!9!>dwI{cn`xPjHjvx~O*NT68!=<-W zUisi~0$0I{){F<>1`hH37sztvPHnz>8kexB$`KZe+fvz#!uF~A&&xLljJ)ZPh*GKG zza|Z?H*}8|x>(P{m1^bNt`%Qa{^5l_ZjhRWp24gye`kU!o;y0wp} zfR!d53RpuV!dbFLzjoF3=?|F?6cRXFqIy9D#ycZ8|Di+!Rr9Muty{eHBi1AYQO%U`&6>o$=L@I21=*B0x}9bjvuUp4w^s>aK%&IDEK44H?|zK@eOh z-^R0P6XE?$_5q6)UIy(iiZ#Ou{cKOJlJ-nc6#x4sju`6U^8Y=-UD0q>@0&woey!J* z*awAm^(iBaUnEI-b7wZ`TQiNLd=w@d#Cdh(7+7Jz7eGPo{eDR@57Gg$FeGx{Ns|lf zO!u@y{Uis@)WcWlriSh{wEg*na3m1Z*c4RXlBeb)17} zRG?5qv-sE)EH|W$@9)>@!_Wnm=;aGw!jgfh@YUgJyJtk7bC>Jnv4!!pSE^SU}o^RMlU@BP3erxOW!P&6;Y=SG`{5 zfGS zbAskUFxm#Ies-UvUoCoYvWCa&J*+uv{GkpkK6y)H_oInLl0% zEA<&HbWoR`j=kKM>F@yMwh2GJkb7Alp3N*R5IOryy!N(UIql!?)Y| z%`0WmK0mpksAp@!He?``2a~{G-qnK4Gf4CRWb9RfuSbQT66a~|mTXSlmG2$*h9~`z zK!BDo?LXlnvmymIuGsl3ElWJ1f&470y}0o*YgUPxfZ{mzyd$bS*k z*WQ}>09j$|@FJ*WOZUx}7_i7V|L)()i`f0kbMR_?J_#t6_bV~Da18^r`;?lJOT3k+ zvj~#xo=kf>@;O;qAnA!_vhSHn!dzhlcU%D%DBjg&%McWwN_|bSV!EKhN6cI{3zs{J zZ&Q}C3$IhG+`m7%S=3?^4-|`dmt2s2gS*fYS~6wLi~#<4J~<538rVatD9% zA#14#cmNwTIks4_BtWu?bvIUcZp}uNc=weVgHbo?roW|mVe#pSO9{@M`f{YvN<^24 z5$-C?j8JPj$XPm7sZ3pdM8F*|XG|LCXj~-Iapbgo$iyR-FZx%+Pf4cL0Cjg$OHQ3a z)A+Ji56`au&G?i1S@P>6=W@Q9X z%cd&}d+!wfCe48ZScX}=MxIB|a3sDkPh@o|(VUl{J{cPhVW=tQMLDhC%D+QFUX~A* zcBsA4&{KA3{_Si%axkP(tFYQ10bipZT>B$|YJ}lgfm=xuMJR0{1Yd z>He`w#M2x=RXaZV{}da$&4y8>M4(v8j^Fkik<*-zmWa0MFS&xnKDLgr5!G`9hLqZAoqS4vFRI88kXYp2eVL3unNL^Cb-b%@p$9v=ITFHI( z?WV%FplE&@{)?V$niAJ`tpCH>eEvz-FOewM*UGP?wfK9@iUi$nJ5J0OExmCW>az>j zETe%SPNb>GK$;4_ihF*X@)u$LP(+~9kf<;k@oAFh(DJ;Mi5)z6+8_wccXoY+xnP`o zuvio3)+hFI#JUm07{fhoX-g6XxWQr5RNMD-Cbdc#se@U)t)`tqbACut$H%4tU=QqdM)0cy1Y+-I)qA zB3fb#8;|`tgh9NAVNT<^4e8r{4FC-E_RN-)dz?; z_67tOs^edI=L@wxqlWm$F~qFNQE%Pl@DMEMcum3Xa+CT%0~m&t(p|!VFi;TxHBLVpDU&X%zq+qYJN$AVHohqh33K*1MP)k6hrkg)N7oPzoY z66COddKi$0n-k;oBM}POrJcFS1Wq~JJ{W7$p2OS~d2LeSOjO+GD!~rm_N}pGPvkPx z(l&|e>=~7NU2RL#{Vf9++M!;j>^$%wFOT(QBip7R4#IHHNXKY=lBnzL-I!0guawN% zUrEE%f#KNF^b56%uc5-HwzR}c&IqRAfNz^I8tdbJt3<%{%WIh!oi#X^vC zv48|$m3`aI-a{p9D+EEUTLAYkO6-^Z^(AhR#{Af}#|3QEgqF0wpX-2wLQhJ6b`5qe ziV+RdcF1Ppih;{&)3;;gcyrD6wCs#5&)=`dRQsaLI+ARDj`6({7w}Bukd=WAf`LD+ zgu&}MsAiZJhov@1^2VtU5Ch8=!^ZQd1Wq>jS)9dd2H$P60LKu6$X8rA3c3pa$&i}B z@*NZIn46v?pyEQd{MHwFd^+yIs@^L(WsPKSf@)siXgwpC2Y!-I(pWE4`DZRwSvtVi zmbIf1lc9YMRxm0H?uIoAoHEw>Ttzy^J;aga8C7iFhe-G>91bY|X-PW%ZI}WYF$l(6 zchOy3L5}T%Sz@Ah(O%S+6m$2vaTXwP>S57bJ;`vumTu-nT0Tw<>L1!^7&WgXd zBcm6$Pee3!rGP5c`4+9aM@2kuHfniCTV^VOhCXg^h$W2cp1ZK5HZ1UTCGvJ9L&Q%G zD|9}iYEKq`td*E8{o;E92$@w49bIZ@rv%M;lF#RKG4xt}b?-0lz%}1L8?-Z}U^=)7IkfI4d(LP`oi`I`pFU2W~2R)sdG zliyw!0LLEFuV&djqiCmR$Yl0oemluKjWjZ+uNAs?BJ$QdgXuK~3Yvc<%&!VGiXD&W za74QjX_zo1&jDkfX&$tzsFvTuF`Z{NMCm3X$Ir0TJj6IZwVX8ue<7Q zfBF2aRN&hBzACty-pwxsT>YFoby@iog$`%IgPpx9*^7`*cdraK5XG7p{3>A?q37kU z=SD&CLShXzAiM^tuI&vdN9POMZIS?us$}hKpUwm>&q#o{jo2)b<^L!I8rv(Odk^$w z^dt1^h_)%wojRH?yo`(F+%UEro)~wI=+fI?mhXlMnk4$EfO?Rb`IUfr%y6YP-kq7z zHDN=tQ5b~E@*gfpL9&HjNI0a$ntW|8iail9*Y;BbA7HY$m`Xk8Otn!uqwZY}1=vVX zta5;qPbOn&*5XNRheO0`l`X@UJfJR5^M8wj?rGOTO-8ieByWM@X8`*dP6O(c8~>}K zNR_CNj)49_lciaKjU{>v{&FKbLXze$mXVDZL6Ln{v;Bl|MX<->&o8ipVG9|pTCy17 zoRb4_KHYomEf}RJbr?hb^JBW*%h3XmFmg1P`uevIBTY9p>&B_wZOXKq47GwmZ2exk z=r4X>bTCn6`+{esfE)tL?sLM0kHW}Bgj!6>Z0#CPoCunK_R|MnHq_bgyy+3T22M#j z9yL4QI8NE|$B@*Gf{nG_0gX1Dhe0O?u!@b3I=Hv+E`oK^CsyFJ7cD>qPD$1Z#{*wD z%@70oZW?R^Gt^)1GwNA?e;Bk~h90B#<5UNtPauec81xv4PlUHA>6Sj^L=hU!x2oW_ zpzLi|_&@!Nn`uh=8y!#^Vg3d^5Cs{W_`jd->u_!}Vnv8Wi{_ZgQ`KM!cKk{*EkS)c z5OIOwLa@yY*h$(^MK#0fBie*-587iz2r5E@t`C2_!}DuHeauWV!I){;u;A9OYoK6G zj)wCzYQkCZK4Rv#?3)4cS$mFNH>tD8c}mDermoJJ_GGIZs#1Yg^0?hC1&*z#Z9Wu& zscK`i!2Z9}E{Et>gkxuKs(o?!MD#r!4Pj5q-9>@DGBdYQbx^zl+c_R%@#wQ|3G)6h zNXG(|sG{Tpnb9xo2wNJb6=Cf+ljCMaFZa)7og3cz<`CNiD#kMa2 zve)r!WBC#mwoDbY-z|7(r42}A`v%pt)RtC4V$GG*#GjkD>)M-9$ zjHD|Ik+|lZAoOnNu>t|8N3|^Ep3e+x2~FOOjtEMOUs4m3!1bYsIL7C{d&*Qv7b{j5@)?^R&(nyCmK)t5I%)2dK;{t4@&_z1*U5f%+7KC820F( z|4fu|HwE*I6chINWB1xmxJL!{)yimTO(@v2ES131T8udqc5e`7{R3=T-l0g&gRaekzVf_7q&%M*%4X79zku_K-l>b@_)Ql9 zA8Yz+&3wOh>U!SMN4ki_bi)%KFu!=eFw6yUPQjkqco3bE_RCw`hZ)-+%fSA4p5!C} zrodu!^7+e^&JuPny}Yn9d}i1gj@R`uTc9nCMkX! z(!ChaL$;#Y?BH_AM0Ci}i9WF0gi(5gtJVC@zITZl)gI^^CMDNFIY>XcN+a9`CcBGC zS`63=$MVq>wnwUxPYfokrDI>}3n&mT&5_MR>mwQCAn`G)4@q7(4OFyeZG9}YC4Y^x zH`RMX0td6rWqqu7n+IPQbMl9_cp!*4nI1FEt&5k_Mn5nRax2{3rVhzE(guhL%$>K% z0LXtgIBdY3j%ZRC7Xd0I4&f>aX`vVbo)J%zO|M2!Gwh!olUW8?@GFp#iD1NkBG^TL zm@UomGWU2`Qw-vOWFnd8x6UBA8>IfRUo=XW)Xk6Cc8NibGH7{i)jb#*#?%j;%?6yE za^{}(94X^kv0IYZ$3QM+6XHCj!|?jRA6FB>ZV^!!Ls0bNe*-rvhJudNcd*}c598F} zlBvKHR`yptJziDx7dIjLIReOyO?WKY&JPRRJy^f2aY6*ugARVd7pA@bMAc=M-}CEV zJ%iAMfngOnrD<F&lqI@_!m9P`o_=zKWp0Thb7Nz)s#NhEa&nZ<$J_!Ie;)Cs zy>L&@`a$La^?*2H@0;!GA4xp|{&&%n{7O|~2|^iA)bo3cC?)}IbquX1#;Z6Oo_$n< zXq;u^p4<*{MMC{n^93&!j+UIH~No5J&#$Mvor0|GvE|A$RWh&9miKnj+^s>N(E= z9Fhm$^!)C-`l;BH@jKh75P)PrRWhcT9axmb*%nC zv9s72?fp$g|K+F3t~Mf12(e%s1Co)M2rp=uKrU>MtiR9oTQ}@hKh+6svTfAnH328s zVaE0Mz18ISd$f5BmauAl9Bq{bwwJ7UXd>XoFn*-kbx%Ivwf^fZ9B4>3lr~Z||1t;^ zR@iLEs$QU1WUHDcfVYL5j7x60#%_iwB!0^dcEwvsACKL|`F@rbfopi@6BM(06`HJ7 z#famfg@*O~_7-=M(S7=2Pn2;@RK76MVU~+JpRjjA1E$~{DeS7Fu+Qtw-DQ3MoJ-yO z{mOgqRHn^AK(f)f`CoErj8Ay`ey=GODb{@X818o)08=R(%^6QJ!vo3<1^S5`3^gFr zstn1W5j2kEtJ@?&A9Fb|;;d5SCoSgU&}NTqeTG9ptgxwmGBR#NiP6MEHLyGXW0Ib*}HBK($%ZUtMB1zyVW<!Z(ef4x6P3x(dBdVa0PN&L3X@MfW9Mb1Wo>j*C8RdU?yQ4 zZ)y{;c5LradFTy=qpR2_n$#(0xtcxt8ycT;0=QB75!SvsPO2C|NDD15zI_kaXXOU8 z3AePr<05VD#h{cu&~wRnci72gI#v}}E2XL?);qVEmuB6ev&~pp%`prGLguz1tN18pPT(J)+r%oVMg;AuWt>?!>hyh?^rtAtn=CsL*@ZFw#liIibYi zClu@VqN#d_Cnp6=iDR$|dn&g{DmklRhdj&x!CjnPp11A2lU8-gsVDcNu8iD1NMS68 z9Nx|MRmDEJq4>aV5{6-$Vx@Vp8V1zz5+}laVjg381wSry(w7H!kKFh3%|A!wtvm5z zc3i27RI+K46oW_CFf6!fQJiS2x=(b?(2vM4O(3Z6-6j){f`{YgafmZayoX2RCY}-! z)-~l4{Z4@3O>Osd{4=iN?u@KMd4B1P0A3T%!DcOCG8E`qhzE@rzZL9|XcrYZ0$lp` z8MvkWcLCO3jM|`?W)TOtO}Lu%0yVK1eYz9HMmJ?ie4Q>BJZG@MHx>#k%uLE*k1#LQ zE+PE@UA#Qc(AQSOgYrw)1ocN=D8B6dg8wtmAT1fLG}IA4@jAM2|dsQEOT8|x(w zef3so>#jpBt*`?nq}(!jimy||=(fUHAgsK9N$tjdq>Oj2pBVCNw#$Y@DkyhVC@M|^ zT@;Vi4kP)Sk!UquyZFV_ZIIm1k>$J#=JY7hhNpwEv#A5{V#S(`b3VXYAIbk+iihO5 z`}5G#z2yLGTtZ!eAlas>`~=f(7j`htBJyw|1es<%MezlSA2?9s+#LCmi~qw6EqZEG z-?@Wq9KFV9LXc$hEbo>Q5S{9z;CAGkH)_@SRX8Il+3J($?7riy+nCW)mu-&MM%G8M=7a z={j|ay>N@_<-U;WsNtLcGjFhf1u?dyge6Y!qgLVx?(3o(?1;)sVcL$uqhd2MiJJyj z5*8eMn}0dEf-1Ke@sz`S1hI`QOD+S1U5Qw;lz8mS!fmFg{s#f-Y%h#hSqDQZ=3bz| z#s{%DkDP5+#d>#g_tsD7{K;w zNp_Q~6kn5_p>@Ou4ve-Qj3J;*-siDcuCw9A_?{x`Di~!^Wj1_S}}donx-Uq@R_Np|_`r zv#^_q0MXlcjYA^2fWFWNgTEsS&(kme)9c9|0nldhBHUI4(EFtuNWMBQLmyuyBDp|^ zyhS}GkVh-}gZc6?GQIJEP&3InR^XQzAvV%;oaCpb0Nd^1JD3d`*MPAPkXeBA6?_Z> z(fL+p>V6>SZT#-$8fx#)d8gE>@Jf<>Isur9PE)BT!rQbs0se+(HsVmdHe1sm(Vx}4 zWa2YVh-Mr7)CiWG(jJJR>wvKVYO6di`vOl{YDAp|da{t?&@nvVqv)Xu(FMB(w*m+s8=V1&e6RxQ+S^YHLi%1sdiqkfZazJU2wiGh`C-(_%91T$wNt1l2?#XN zM~45Iwk6{w+b%Ow?#l>}!YVSIVi~qpp8*2WtOg$}rK6`^HumrON{-*-4WFmCRGs#A zwF0N5PYda^qI9uOW;ikAMGXO=gRh{inpoB>^rEf)DM7WIdEEBtdyRBjC?zc^uD36( zwK)D57*|Ai7Tbeyqy#YtS`Z6P7c^ZV}Z*>f?X_>sShz>ourhb1b9|(U3R;dXtpD>Ow*BeMQKG1NN)&U=q z+EU@{($gBxen%ATZPeA3)TEk^J?{;^nvu0znKeA~Q!!v8`P$H0n%Q}G`TOzXKL?f1 z5>JubUs#h2wRG9(ATNlZoUkrBNRwj>kQ}t)1Z5bgz+KFz_(VKbkl@yEi02hnDSk)` zV@jl$a?^x0t>T|wp`|~+4}3yz_;-CNo=M?g{}2luf06%y0m==#)|RN>n}DsIj;Ch( zN#Jbtm}hqUZO7+5B^q80STe{9u~PAw)HcvC>UGHGZ6B}J&>Y_rD<4+c-|roP*GT3V zXj@OJ%G?p)urHPW41pDb{Zi?Mk8xn2W4ZL0>bgYu*h{nvgLU;&z4V&1vO_0u>YrG4 zMM;VqvZMK<5S~X+5ZZxra~^rJ)bQj+T`2OB4Yb9UF{T-@DA)xr*1Y!>&df$x>Pfmf zNkAZ>JG149nMRt7#&{;Noh5zZ_+5*ocKtm;?C@B4X zeRm+;?EUv5`&XG*(4vS6BIKQR9jteUjEXE}GXF?O{qk5d$8`D4cEje(uvl=x;o+c=n=A1!~&;xrIsmF(QtAU96 z8<$gUiVd2kEiruPVZB@tgEnP0XCK5qhdcQ z7k5PNexHHJFcRgk136AfO6jwF4?d5nJfvd8g^=J}O{J+ZQgQHl9=B;Xi|Ri)JR#v7 zw&ojdc5_17 z-npU| z#^^vj^c&t(4lM4IJ#scoE?_QCZU0ZqS8F8j+#}FeE*^I1rmL#Z#IiX>b5LBvyL?2O zIr(xqVA;RE&{6Y4+2&wnK{{VI87}u3qS#jx|C4`kxk3Y9pPvAv#h>!qzw|CL${VBU zxU255{RHg0B7(JVtKuafEs*`&;_i&HS0cox_}C2?rmw){O^JzvNuJg)Yx{62_-DWx zw+85-ISruK5GoWBP>q`c!0=*PVCAX z*rDbdA|F8p&F{lODo;au8-sGHn~V~hGZejLAPs2p`tgPQ`b%|@+{#+{ytz372Bps- zCR;NjkS&rn1VsIAmd9VC^G?Gq{H%Q*Jo8dfQ-8?h3Jr4zyoBe+RNu~dw!ofmV&%8+ zy!o9uDev>=oF)om1&Yt69c}NqVyu{N39#qenbw^?4@LqP`X0%&R6aQ&#dstjb*(>cHWx1#9>8a03B6GmTw^o)mN<`?3FZcA<*ZY)I!6U+q|rl< zlCgQJ*cTP!ypgliZJKXRIj~EeB+Iw1(WVBYM~ZF4l?IJA z8#RpVXIhWXWo`{tYlX4_ecPYMY1va1B}IinU?-z%RIxOI@??Y3B+R!fu{LXeIcYVIkP(uc61D0SZA=Cs^vVXRJjF591h<9;B-2!Ae|8 zY=0B+U;nn-P0Dh^*9?B^I@TLsg0UjRq-d)F-`zgL_Frf8HjtzS+vdPxv%BwJ-b=|s zn+2tG{(YQb>Q>gww~#Vxq$_pU}0aVpX`0NBgD?1SwCQe-d%{KMlr-h?O?E97ruxyxA*7Zov-a z!k&?w>Eh!A_BG${`rkPS%GI!CX3+U=5M#|rvBqV_4E4Wpvh&N7D-Rj(BtbB|?)d=t z)VZLJ%^}$|hLN}ZN_z3RF$vtwj9u2CcBuj})D?w-LDjJl$?uVE?|To;Mg?Y*4S!z-CC&*0{Z1oO7tOO+I zULsZ*{{oy-D_+d02i;MH!wFyxm&0YaMPn~PT1cDx$XmJEKe4!cTyWW2h%`QR8qFmv z=VWf)4bveZ7MV-$7M1*=T%MH@rim{=OuG(%I0-!BhI%DjUOqlQ^(i+{Xf+f9s$Ff9 zov3v~7hA3(FYtzYnmUFNn^-kJxtkdf*`lZaT?hTGTlM#6mdBmtj`~u8^%X9+ENR~K zcbVi3AZW@i@jVgi5~f{c?FVC_k@51h>%k_ws&OI!t+miy=#YCs`Gud7QgTaxv(OaW zDniq4{x)GZAcKY}jzTkuJ2$cAM%cU8MvlKa1Uke`sS!Ut4VGi*PO`msWU37xGlv%0 zRtpF~-?-K-=mNM?Au6%{=SFOQ*@~8bPgy>}b`Fg;_9wZhqT*q1RyF|!UP#43G|TDL z1R%#oyovB4)UBNEa)AX_#-L%YDYxjL4BevHLrOm?%O) z>pGjV$(3f~>oPK*Ysxf0ySUdB1r0%AhapzPol{X_EmlO}RuoXb6x`HMi$>LN58Pn! zdMm_fw#|rp_*=KZ7))#EgsV{6sw?}iA)ycO9Sp_t&@o;_Mh`p)0U^JaszP7KZPNM! zTAoyIKnTL#7@uYtgBF5ke*4t~d!~keDF(%>0ZiYoirn2O-ffE8ekX1G(6BtHoO1tA ze4)+ztoiWq09-d2qWEy8AYO+AQo!Q;iDvAW(A5!Y2navWoY;6daAL0`lxxdh6%6Je z*W6kv9W_;a^Cf!zP7QKhCR&f2dB`G6NCsCtT;sJa@}+=H;^u%uaBjWpwy)KO?T=Xz zv$MP@5qw&>Q;^F7d{{8vc-GhXhD zZ1&(+9ev{G0aw5dgKA>SKb{f!T*aEx5?lw5BFL#2x@2Lb=4d9f2h8e!F5pEVvqL{( z{J==q(ko@~Uc?k9;K*YT zSTuZvC|1Xof1nb*2cK38h8XybHfN))ZlHz9U)qGMUWN=;MU0FU*qQP}Om6Q-G_Vlt z%(*(juN*m^Wh-i-cww$qZOo7+AKIQopq7&Ab0YR;-r<_|7t>_Oiprn%r#ahnq@a7i z3n4fxa(bl#!0%yJ3(_DA0XN!I{S1L7yIn!VV)NG?&l)UNqyid965f1k0-OnfXO;7Nx~7eYH@KEd zms*xi9GLq_l_5UZBFt||Q@lHBn8Z)++wak@?l-u0-P~yzQ*KtB?5vy$l%0vl^h`O# zw(a?TYV#Lgm>zG>x>vGc zn;^`$#0XN!M5QdnO|M{Y6CFMZ3?-lEEM?d}4G}DIW~9s`2=AUju&mc280a-j;A3h8 ziq;jK8$=HRJfRLTS=}f3e|Pj-)_c^h#8ksT%L;u-{uQ0~?-11`&MGDvme0Lf)HBzB zCR`uitGmrQY8z!nC2JdqcPbG%w`T~W4oA3V%Yr2LdHO>_Q#D1>?>MpAMlqsJp!nxU z`EysgLc4**-OQw@)D&F#s(QUPZs5M6-0AK9k}hYscFrZUW(Q1(1oVfavg8^gcdZB0 zb}13hCwy9wMW*bWQfa~3=fzw19?mO1_T3Zx{88uz82mai<+2O0fU;Lg%wt6kuXkM6PlO{Xu>hXmC+yPp`IZOb=qIUyn2cD?5$k5ZKn zyp(}lyFMaC%{cx^w3t5MA+wACa1$ZyURD$j}a2kbQ986ZNyce(ELISryA$k` zV6ivbiXWjjImoZ<+6#E;TXmPatqv|3KjBl(L-IXKdAPPj|KRA!Q)+_>2aHDly}nn) zTpg=3SjAAZVkPnQ897I}v$Q`pOr#?{BK;58QBX8%q5)#;XRD8&)t7Zqi98G@C@jzQ z-TQ#VOF+$Esp4TeY`6ua>lx&W4!J@pLu(YS6;(F+JbY7V*JC0vpq@2)2$FoKNl-V` zy4e=@X~U2C^U(f4d2jU8>D4hQ=aDFV)s(`!*uokDX5N^KkI#+|yAm za1tjqVch&K)G^#(?Cke#M#p*Vq3ir==ARj$aT01suz?2Wp<{apte0^)^bi~*8tF!; zI}c6yb)MWZ0ceQGMHHvC4;IrGK1daO{d1HYI{}nA#Py5DseKN=HPG_)&siin+UDi= zY!Tz$(ZjWAgNjZe5> zgY*p*Qep|taDbe`aqdru!zU(G)g^PI&L+{jJP#S4X-^0F66JePe(^*HTn^nYZNAb| zB8wZ;LGP7n*}k%M$OtmA%pLlBWQX0liG{;LpdH^ZRexj}|5$&&Jht=cd9XKlKDODD zH-jE|ew{35JnIJqQFt`gVbw+%s|a+wj{QjY?gOw?reQQ*D%{`?nMb8E0_GpoE=f%h z=NqB|s2wM*ED`b6N2XSBwh-$(576KL)%780jWoMo+VZz*DNApa21yASazx+#FtOZP zjI~1tr~A?h2h?p>nz+{NKQ~OC0LnhA9g@bCWnO77UV)H0jUaB z$5#Qu zt*~oZtj+t+i0{u(zPn3$f?+_NB`c|^n{s}1FZTZMV42mbp(*RU@Sk6~(n3xj)9d!U z47$W2`OThLt!sVkn~{XBGgasQH*}VqqfQx3>NsQ(j#6CFsPe%A@5RP5!}bpe-s$=K%aG2GnnF2<;FTFjgpEPxez`(*5 zo&V6XTLZiiz|=mUW!4$NX*DZcLSwfeQ@OF|OJ&&9zWGNV;9#dd+n(rq4AW5y zhgXx1+&CQ+b;GmkMz*&y-bJ0WSkZBnH$LF4r1#eR0^(%aENJ!jn9#7ieIi6TufpST zqMDr>`J-u&HHx^^aN6@XP0UbAuN~q$zkhs z()rRH55cI<8O^ae$`TmkDB!~w*Esgy!1hw#(f)Fr?j~YG?@c^|yc6(_P%qGgDKo%h za9ZB^5_(4Q@18T#it&c`O_Pk^Dr7`($%?m!Ytf7d4lEP zjmHVu`-xYI-#2}FL&UJdKs72cBz47pGN$eR$|S3&b)4zV*Ts=wCwOJLyKDqGO?(y@ z_L+ISPrOWx;zdJO;ZY^iD)lDxwBR=#-*Gg$Dwel&ycAg7-m%u~WA#${d#a)(d|<10 zumWRkg__aM!8%(Fm4dcPuXP3O54=)ztJA}LdsGTZoNBp2-gw>IpLaj_fI>UJQwIY* z-L6Xo@26N4i)DYL{daEM*-}^Qa&$wl0(}Q{)p441&%kH=*y$BM&y8%uL&AeE5OA0g zT7xsrB)bcrw}Gbi;Gd^OvV!B}&bRIElRp;32!7SCxBB$9etnzV2rYf2?{(6r>~?7{ zV<&}Yk(?k|VPFCt#w2(`GY_iC<`&2oo8p~HGl$L(R;vG+e&fdZy~C*a(WNi&zStNW z1Pej?lxWpTRB$A;{U@yf#rHIb`>s&+U1%?PvSkifdj%E+fy-&%$M6s6CxjNh|%k5_r4_>v}T#+8k9VA%;OcA`@J!g#b%fE zd6LDHfJSlrnR8(i?IDk&w32@KwUJ-npNOx3XDHF(vT<)S`oKecE7ik-sdDl7K<_Em zsl3^qHU*XE-Q*6R+&@(91s@Kw+D2rlIBKA6fb^xTKVJ)mNo3`4BRW@~f}Nx>#LMun zRK+JTQPW>9?erB*gX@`z7=oJ-j1U%?ZVqXcZ5w48hSB z@Acyvwf8rB;0*d%6fzw6+sVyA(h**x5wBQ)p8oA`$m@D*W+nH3i1)H&q|@tvpCB8M zj^{59moy&WYKx(y4q(8Hyfyu;H#&`Sn96bl6@z|7sWtVcu~4+ff77cwf|-(2AukpE}t( zefIcv>?KB`HP-iW)0W!0N9(rFt%YS5{+d+Pm=dIi2$^KjS<{Pgp6P{qfAeu5Uz0Hu z_W#cT*d^EV+wIIzC5((i;JiB6!;Upx37XHT`(_wFVGzXx*$)=ae@|lYRf#fx`Wl9k z?J!aCk6YAJtx&g&`F&UY=kTtSy@kA)ccrlHtSCQuf)I*cFA3ly^wSNx_I*2g(^5!h z%ebz-g(FA-l8Y8sHb!TPdqu;o-BwEB*zs-8?ypDBIh%~SbIpl*34{u5c$jZQE8_PQ zGkHaQhU77;K?J`KAS(OIk-zt6c7Q9en1?xYe&3R{TTPh|?|*EVrZn}s5!lWvERsK| zzdmyOu>@JFusQ-9?_xVOv{;a<+kZpG?N=^yvYHEU;JF)!Y=oitxXtXcWzV~;@?YY$ z0#hO>UD~ZQ{Amb=0EWK#r1JfDgy$@@T9L6r^xZA3yKaHG%kW>YXr-iXB^e-K3AVrQ;VY=-AZq3($*OC5IV& zv9Z$aKk2b2V67?_WO!FcAS_EYc0u)QUVE{vcDo2}vvIDm-n+lrt(1C?aPbG1LesTR z#^iFUoy0%6|7J79{V{M^;*6Yp|NQJmaw&4|@$UWm`wz3W$Bww8oW9XwUNy{J9GI`~ixZ{iTi;fxH;U7O{(Jza<@9;t$;_ z`i!&RCPVx(P1agCr|7Io2f2F>b>cg{U;)LLkhf`2yH^>BraIdcFv z2g~iSC$sv~0f05h&97XDIS)<;VnV7cMge>^r3StR=Y- zl#CZ28ggy$L;SE{*8u)`UPCWA{ptG)%NuDNp1W6s(+xk3D%4N5wimkI-l?WwZ2ol9 zltb%C4(+Y=H}~S`!2)leVFu$Eo`z1RB+0IBab#I#`1(su(5pU5?SYXlD!BZPOdTg^ zFb}r95pifl$Ie>1deP*nyK8ahF`-r?&}-SD*=41Pkg|F;ax(KpskGUmf(lnE@s=u0 zxn&ydO^o;(y4M0h8W2E%nxt{Rc0XdiiQzWl1mhGf)z$p1dfe~ z7Op==Lkv#n1Ierc#Np*CezUzK<^_CH(#@SMA=I2Pp=$OOp$oD`vKpo$==W@$=TZju zpw&GZT1FxCJOWo$ zZI-8IKQel%rdj%Ib$rXOm)o>T^K<8KI_zCm&7!1U_L|XO+(M0pt0zWW9NFm=db+LC z@&Eah_J&fI((5 zZV>Zs64kCPcW59@KE4E|YX#eejO+Zi5Uxp$yI=>jKJWV&Q?YOP8M$2~nOMnU<~hC8 z_fh9zt`c~08Z3y~ZcY@Hi!3Nsw=r@4*UtUR`!;(+%jLzQ1}~Fdiy7n8B*Y2PFpVQ%D;3I&4HG>Nwqp zb7G@qDOcw=Yk^t$E%!6mb2p5kAO8I%H52Ajw2&BD#tdXbXMdo=o#OSD{ixjEifBnM z2k@jlnbrCq<`qjo7r{F`peoI?N@4V&}T9kS`H4Yz{)mABzTSShE(z>jtGX%^UdZ=;0DaVpi3>K zr`xk8<+%eMW%GF8_>OXQ@1*)|=$ZFp;%MMp%v*k$YZzo1Jw@N+R-{96(6M#3Q_RDn zDlh}0mP4@sL^D}pN0bLHt@nbk%Qlg8f!E80oz(78ILI6e$HpExmb$dMQfE`kzWe~# zhj6jM(NALz5Y;M@aYEXSO{m{F_t>c2t#}P#-TiC+!i&R;EoVSy#wqZnS(5rzsP6J> zxq#+=gQ@>!$vAt&7RT<@UZSSS$#rS#Q3cNmN#i2`FHO&uez#`f<(GTMTCVZ0O{VC0 zJGCJAn-cG2PP^m$h--djpKjx@WVyie=Q)TDRXu`cy5-7S9L4;Ygxh4=K0%?}fMY-o zX9+P}`#+h-g^cF=T z&@j&Y>HAxb*!rY|cl5MWr}JMx{eR= zBw{s(;#CVY<=hO#rtev{!yLP4+w_J2=E+~k7!z{?u0pT`y6;{KBW~YB+=(#E{=Ah( zb%#wg_8V(yFGIzHnY$_e6S5iWEaEmEh zr1?FSWx5of6>O#`tgb;r2>@Al14>$mZ~FUW^PJR6y%4GYh&I3WpVjF{=a8){A;DCu z1FZ|EAo+`{hc3Xp_fYa~b|f;3Vu^^(g%-X}kDW{f(2ZCc1s^qBnvAE8T^=cEOio}K zW-}D-ZHkLY+Q;}4UPv36JzB1&byrD-U>MfA=muGm2Y$V0Hy%k2O^wsye};Z~A8+u% zK}Yrzw46stIE<%s<|hx+%>HXRz3S)*d)Eq1-#mej-~0EV3NiDTr?WP9PcjG4hn@H0 zQ`b~^o|_D=3uN~D^j5iywkP1iJ$zcEQ*W@-IAYu45N@m#E0!i~&(iTqA%{p8|##|2m0<4XU{<_96In^#z*(j%8R- zB<896yrg%3`g4(JSQ9>sn9Bpc`FA-e&ks%x?!}%>m)tG%la3(F!WU;mOn5qg1zw_$ zp7cV{zD?Io_ws!#U|9-1Fdif)+C=w%i}B92%a~Glg_Y4$s=s8Oq3m6?kS+%-;F1`8 z$fw0H#PwObYtn*&*q>T}p@L}GF250j2y$ zA;UFTI=0roVeT3FhH>`ZD}7}#m{GTNr2SrKflRb+!UL3bLZ?(xG-Odr_z2u8-(UpX zLAUTDHR1t5*Ze%N8>FPeJ;&>w*3eKE^Y5mPIz!U2@6B7p)|oSgM3{HiSUf}JT2q+QLP%qDQG z*=Wyc1SUdlgknEQ88RxM+v)TTQRD3Y;?QTBd zc3PN+Q&K5CMV_-Z-^60VotDBCX$z1L0$$2kKc<%2C1=^V{Tj-pUY4dpH1{!VpzX)%gdw`(%Mf+a zn0yn%3kf8eQ=j8pHSXzJxnjF+|a?s+rW2+NEC$Le-tY(AdjoKTjP+ zj%ZmiPg@}5(?iwju4vBMYGN&11A>dc+*^EN`C_}w}#O0ibF=}IagC$c?3V5L9 z_k7hkHg2vD{C^TbpQ#E-rI97dP}E1A{~0og){FCrgbys`NVg}38Ub);Dfy9F$(iff z06Sq+A-^{#uOo!W62&0@QV4?$k^^AG+Y%aJF=Y^V&S`#n`F=Xm(fSjD~&G^6k-1v zF{Q4G#*Ul4^S}Wrfwr+?{a-5b6Io&Z2dT?Bk)7=Yqi*ivtm(rC^gL{KyCs-LY;*yw z%UgiFONYs(Zx(wMLOi>W=~w#|_F2}P_Y>!@6)E*sqJdI=VX!l=x;BDCpZk2*pt+y& zlzAC-=QU_Ujq#Gj?q@=g)%*<5ktTI2@eU!_ixbQ9OZf3Vru$L(Z z$Ci;^(A*bx0)OoOg6S&3u#BIRUE~9tZd*>j^&3Y29M`0C!bTEq0k5VQYjyCw^zoN9 z@LLow;t6RjB9(th`rjp1lD$f|KB~NbGx*U8EoQHSLYz!D&r?P(9Jap+o5wds?Y?;W z3W!R|6`+?)p8r$tPDU`o#1I(zKn`H|8-Vj;K@nb;1T&1F1dMVXR@z1eGpvkT*#QeD z_|FNC1Ok?dqM337KHy23&18kCN~K>l^OA!S(4_s747=RQ@BFw^fW%iLg-5FC$BeVu zeyAXSY$Z^&OQI6XoAY;yCAw4vPVnoCuyA0-07!f9O`g$>d{L&hgD2YCvRo$M2iUv~ zu2w)D+%KTT4r&l}=!FML4*XpSv5cxT=gX3{KK$;s^-YUnH0-dqDpRt~_K9in|<~5z!cHfS)qd3tV5-tD-(~{YykpXTHFN=Qfwu zGewfd?z|$~iP?UC*(~&KuJLQb1|Q%Kb@zM+XQU}JQ2^$Z<<`0*wF26mdF%rl-FK=VCpSweG?!c z+hF~XRK5>+Bs`415s=eXqRJ;Q?EuO>JrMf=mR0G4Z<;7U9bQ-$n$T;8wei#$GKvU* zvo53n7+#2UgC}V=6^WN~(Ed0G?GQezR%^g* zWjCWQU9vr$ci!`|CQP%*qRYj#^M&qL_nviqZ<3a{AMZ}oCc0Pu=9N%EuU00G@c1o1 z^OYCqEH{m4T>Ly5SuA-9$hl3ToN+2Qp?d=l+h6LE?2=Z(+dSTHO%DI3{y&&ggIUG5 zl{rhhL){7v%MDmWPxrWfAWc-?V@G$t33Q?L`!`Ry(g#_O-R$~)2u?q?55n{*liB|q zG87dy;v;^&iVcF=P8Q%@Bm>98BnzK^LFD7E+&ww9XE+Db1z?(AOfzrozBr64Ap`_n zK2L=@IyMn}WW=$(+%8aye@+M42^yRZRQ*wuO;m>u9X!BFF0a$~?=#dEv!li2xtmZ? zXvb=4v-|fXnQz1CGIQ59sc6N0pmnbTGh^e*CBw%*YB4Xr;LrTWi*48}K~Igv%s$Q? zLTB%SCk~0i2H3+x{O`W1L%poXm0mc{?OrAU=+eQF|9yDUTa3MH|4 z&|6)p;-yLJk%0g3xV)5sP|-DT3KiyKtgN`K&JM;TAd|s#2N$P&)*+FxBbHZiLO8n1 zkXW;RCjEgytV3`_o9AJlycWM!8=rVn$uBZ0@(GU%2Cf&x?W~w}57X@5nzuKN} zES}71uUuvx{PujL6y z&?M0fSOcG+MxNX03w0rEv=>YCthc$Oig)efAFngBKCf1Fde&K3^K-uZMj7i4Fc#X} zS-n-39|8f}%@*kTcl1_$Z(l`-=K4^9ciyzNENI=$kFUW!CJ`{xyXM__Ds4E6Mi(8z$ccu#?95e?9R7J00 zsOj1~5ozJHuEQ>A{XpRwGB*5xjpMTXEdgS1V>F5dC+run; z3Hy#yIqJ_A&GOT4a0i01nxYch^%GJo74%+;^P9Mkc`<*ej(oogSVSW%Kpa;)be^nb zf$kQY)y409Z(*ID(ZykyPr|GRi0480oi97iuP!>N(WYxZ5H z=fO)yrel`yx zUXL1milLpxL|}$$_$TjX2%tuVf#6H>!uC3=eVeZkg3qGn=bOq*>Pj%cvRARF=xgt! zj-J~d6xOf^5LF3K*ZLfl`wVu54RUUu0w_A2rs0OS7(=dwA#o@D`jR8|V@W)*`7wvS zpS}wywx)f!^Zhm!1TH^9-;C@5R;BK~Sn>?~6&|5bo zE(HM_(*Z~Lnpqa}(VeK?kG2a_iNUBLz+7gjup4bk8!=4VgE9ViN>3QZmX3V8k5I5t zLJ2^%=$|cFt-rysi-~94ROL6&C+j`gCO|&r{->?gF|zix6Cc67T`K$3 zG(CL$nc>INtzw{sXv6%|veHW6w0Fus%L(uH5;MYXS%)Oc|03L-MxLSS?c&tGdY1Z8g6Pk@#}07Wo&;ye#7) zTdY@OYc>-e?0g^E&lSq0nH|kT+$8oZ-2VKu`ob;Nv5fH3iU-!I+un@y6rcw)6^0+S z)4;kFs%cZ1S1o?K%HkzAZ1e6UHD=QnbNK$mmh)wa0w58@Q^XA?VuFMT(IGbWr$&(< zxc@m$2|+wz$hePZ>*`N_^>Hrg9gE4y{>D8ir^tOK+CWjNA}9TM!qU*wPEa%T2IFn= zzwE>i4e(yj;!YprR`aQ+G}>q5$JagQ@7N4QYPO01!)34Dul^0ylBYi~7gmT62XPN_ zWE_;IwgM)6!vK1eAt!Df#`#ir;>KJ>9ldrMuz!%pb_$EfMP4SARV1dJyKUb8ToBk} z=C54Z5n$dCS0yH|YR9GDZ#2jjYgH=$IaW73#Fh{pZt)j36ooej^efApCE{Mh5A+Gu zUY_2P_Y(rZl>&~zjOm1qc+}`cyXFK9OLsRuprJH{;4elP9wQ=k_wN}7U3(K??u*$% z6JW#C;C%^wRb{Go{-?hxIAKchMgMe|6PK&{7Wb~Je{-|9)>E(`3_Gr|7xq&wXv4mQ zY8~Ph9!*YgyKIiFtB1taSRQ)s|C=i)fgu}O#`vlggpNfax&84NNax{+2HyzSk~z#c zb;>1tNOSPZ1&I#>U_KW1y1}UeZ6!PUuaCPkn4U8X-u0y zITqmYG>iWoQ7S1J^pF1O)l@B;(i2cPk`UB;#YUD&>EjCj>cYN~2EL&jFBPnN$OsxF zeMl>l<%c#Y(Cj`XH#m+boC1eL1qa!`#o(NbV zUvt9QW<5dj8MAE&PgMgjh|eXJNbU>ti}JfS7pi2?T&6>O=5$vEm?#*r%y&_nH6|&ziiSqjmZ=~NDDC}r$~%m zpuABq9szj!*T*c_Op&eB<26rn!x zU?QTfs4%H81IdLdJxr`M4HLoI5kY?lKd<8E2`#EjEn3Q!$5dgJn zp9kaWZ^|;o5s<}f;u}&RGnW!gUU#dh>6lkdFiNAZW$5c;SG$}V@F``_EdILB4P~qW ztt4MFgFP)8b7=7RR6#YIF?#!erR;@q1e!K02Jzv&E%`F%*~i7lth;*UHu3KzrtNWq z<%^4L3_u>Uj>AT}{^jpOHW8nJhD3jZ(x&fodsl2W|2%@w=SDRpbYGz0Wv@va5`l4R zT=zvh7F#hLvhM7T7f*!{jj-Zj#hg7@rX!m=Y`GE6eKZ<7ec)wOT6bpe5v5FH)PMBp z^6ffJWE8QP89NO5p&%_%G7EtgUQvPs$ty0qw;4(QeHNs08XcNn!+mkT zjB6Jc;wulz^CY9@4tS#XM=J;H!CJk);e*T;f)|pm9 zZ|5LoR+Q@x`*%a+JUye!w%@FXAgL}-7Z3letpsiEabz+oj@G1LN0h0OnT2aJ(LqjN z5o!pE$0Zf6f3`)6x)Pw(6#N*!J*pQlWfr$pnbxKW;_=xoirIRsqYJR|?I$DNCKYJ0 z&ps4iIw4GhC$=2NWcp_6H%3jFN{cO(jLJ!W`ms(LJNx~OG%kt>`JleS{>AG4`&URK zNnYov;$S?$+tiLGBFw0J;Kv2|rlB+EIveo>S-pDw6XrSp)RPY;&tF72rHwH<!&Lr6jS3^jgSd($le{tbzS&yh#PEix-hs+9OsxL_Pxdi9hv{U4{f1;UE zhAnO@q$Azs(u(N+_2B9JrJ7P!lOzO>Rl%R5?hOg)DYGt#Wd#9Z86o{wH`jY=k&lzUlF?da0mY7o+VZhMTqdDOoD zW_ux}mlaVqDfe;rH$Zbo9fJ-V*--T1G;r(jEt^$MsAA+3@nwDvkkPDYl64OvicBHL zzZ&>J&$e;+Yj!%JI^^yJZ^$wnX^1T1FHu9_NwVNqu{%H4682)W^HTi$@*79y&rdpZ z3w+Pra_YR8H=K!b`KcLXg>pV9UFSGpQK`iyJ_gnC*FlW*1O2tR?d zs4Cw97I>Pf!@nFj6|OHZX-_eZh$&SmBkE6Bb56Vsa2f`0!eQS&KJ|3_eH3HCm|zii zy16Vd&>G)>yCAgLI4$t)@;?E3n}p!3&@f|H3oK9@h2oa*vy`mbHL{2}_Y z3)v?(b`<=>curf4L;{$s;kxczIiY{up**9#rrG{gf31 zz09%|(}6E=Wb`KlWr_-M)|8l^XhME4(HNXqM^x+(voNg%DQP~1U$9}ZgvoD+4?BTg6- zk#<>3`cE|3px3$WG(Sup|0XBCIx9l&$Aiy+f+Xi!)uUB|Zc=ix(`1*;0#}O@84I;d z-N2r+;=g397{5tfPOj@RMNTSEy;n~e5$-Xk@}I0vGF5P35TzX!) zguObyop&&(pZKu#y!obC+;O3e-Z&92Oe4%2=fe|GZ89w<;Ky$ws*%hiB5|#5Q!qJ4 zv1bWpY>LJXi}rn$dCP?bqvvu5EDX+{&0}2o@NzEr2r6ln_o=Q2QQV+`-hA z*s39GjNJ9v4~a=7l|5@l$m(jUM-O z5x@2C?u?|3Kg*WH5~CYwrpgorzv-Z_&aTX>(Dom_@Yg}a2)bjd{iwUG}JmHHO`-u&L`6=uz}lyP6QtV2*ND?coqAvFW#SKe);pmb^x-4o%%se zO5KaqEvxQy6Hl0Mwb&|`E%P5pf5?-hKn#6$e5=*qIg`Ju@(NU|Dg0L^ODJkY|+)?5Qs@YnyLYm3;riXT zz^yImL9o%U+9N-1shN9@1~@V#-~3m#8^KD_#;E6UL6#RPIq!A{=Y!VVop8%WOiN!!n|-}hq)HN z*rUholqL4`-GvNgml1X8U6wX1Q1CnCn}w<|LM;nWJ0B)hgQ&J4&C7j^<*$7?=@Kp! zN()6}sx^)grk$m!l83!(483|w)n7zAr9L#f3*SR`Z!W_2WPUyajYp(1Ghl-b+JmmY z{Txmo>&cfO`_P~~U;ciumnYH{mTK!>9|!rd13xjh-Rh__2X#^f6lz*vHQVEQE?!d* zV0@MWguRN@zUOKCQl}Vphkat;w9y`9ughQRy9Cx zoN7S0V&ayr?L+Y`c?F9taCn4b(r_n(E~CD05&P!(aHt-o^i(g46)u=`i(EQg0C~f| z^p7zL@Rh=v+!F3c51MuIs&#V zR;ufYN{Ym(4ntekoaR~ELYdkqgP0JT19uzf;p4`t*8n@Biho1;t5@7Ii^ zJh4qFkA=MfF8M%eYY6!O@#`Og?uig|Ch)^}sN_w8NhZFNY4!#!C zKeJiP9a|eZQ*(B_=*l?FQ9{5Fr(}b$a0GhDV*}gAX8aydu#J9?NPA7-#?L|NDkypg zko&i&tExk{0JOioum-3<{86dq#Hc^4wBmMburNBI2vs~8G|R&yL@0#W2|3#B7YXnV!IKBc z6goltHo_U_O1QySYArdW7$LdJNHq`}lG>Px?BzIRe9(J`f)8+8TVmSvm*-4o|FyzCn5rsG9V~FHIjQE= zA%FkWBkrwp&`kYtkF^Te`)-6DQn;o^2ZDj-=uqrRV>XoRz&%pYPX@sDXN9KpE77eH zjmI9n71tTvZCljVExAeQ|JEad0Rp(zpRA{TGWZ2G++0s1{0MMo){N5Cbn>GeRfOd2 z1#!&M3f_ih2q1*ULgsZM0mTZMqePH49AH=Q!IIg)AN)^iz|53Y(bvFSZ^T?V9QGC8 z(65Kxg{qh*@%NKQfi(fA?NaX>J;5@S=TTL?PP*OWe;%^2?n_g*qJyw5f78}|8KNl) zBUFN+5E{*_3x_acc11Vll~+6@z5iY@F2tJ(NH}$i!zasV4kT)*w9mRyc%p~J8v0v2G_uiYFxmQ6fT37IU3ayJ<{<)DG zEa3L$9Kjp}r~$dU_+>Nq?GL~r#du@Qn8d-u%89T{B-lij4Wiqz%{UIbeZ7~;*~s!<@Wc}H##^Z*k^wlypewIcG+*bl%KM9ZIuk!(cLSJ9FJaPXiL-;a1B zG01@{7rsT6MP&4ciASaODgC}SzQkzZYrmB*!FZta$1eoQ@#{LK9p#0z{P`>nZby`~qghj+oOT32lMBsq--dZHpkkVt?ns0atG zWsstq=`&KT7783z;4TAHhs*SUpDOM@>4Adp3JHH}oz&=&@i_FaR9uWp0eadVle-%` zjHu*<~0PAR#yjQ&?k`UJ*ZTw@h0P;a^eve!hkgcFSN(yOv3bbfC@??HsMM~Lz#_Juq>z$qp56cWazgmlXZg;Dl)0xYoUGEB`%l~6wtU&*6L zvC5PnuM~S;_v$s9tLy-Xzo+)Dd<{dk7+|JGc5!ZAAnO$*1pGNH-n`J35JK=Q%Z!2_i&9l?b|LLx|s@iuLHnTSV$i z=}Xo7qMN9jZ@Vx8GxbE_`c82YT0U`44lZDP=i2{Uap@I=vr<_|oFMbLTn2F==6a#1zKW9^$q0Y#yZJMf)lzFUY~S zz0g@{yK;6j5Fkc~Ov!57;PYEFp)$^&mon~qjYG9iH@JN2O(bFAcHZ7hf)W&CTdGd{ zXedyYGLw+pH!*WxJ%?E+mBHqRxiLmj@bzYj0R%-`@r8ANWcec45U3B0Q$TOlB3(G5 zfDv_x`f-C%U^6Zb7#`IB1JdV^6(xi_RC(igQWTZ)ggEAPeDhb;i2fa4l)0c4 zk26_gj@^3Lfm?4joTVtO#nlTg38UQ6k;vPTWQ$N>po1V>@noz3@D;nFEuOzVfLn)} z8a;X*DInK}k|umZ-rp)vRx5o5$xW+1#3NT&m~yzTH-aVoo?mSuhl(M`g&4inLtw$kN2uEJ5a2OFl#Nq(lInAW;i@{c=KUOwL!O%tzRdAjp z#OGI1Lse=&`^mabAurqv4w^+MZ$dUxJYwTh6EeYT)rL;2mX($XKhFko6nix+O0eA z!U9|Mi4i>w+miFF$dhQ1FJm(OOPDlSzkiQ$zY8~e8>x|E#pGjuw!1ar%PDKa^H7uf zeS{H>3kDb|sPtio7gitM!9aOR$PCUP$=E~tl_PcZA`I9+pcYuZkzxwj#6HDMcI6Is zNfKsH>M#k`kBv{Fdwwa}uUhkTjpyhoj+w1goTVy7;rSsBJ)pYJxP}hqjRCqFFfUnP zx_t-fz(t*Xcw)e2q=K?_di9Ks9t3Zate&x-l@w%dwzO2BEu(OMqoJx&%wvqZ)|*#L zpric{4F9!NNPNP|>8k&$Hd-ApQ*Xnzrg?>>HA0JHdQ6DsG14ZC+tDvZs<)@~gjX4HRr4#l&bp zPr7jRVyKssG4vZhXSWjO9Y_`cy@SHfF|mObtwRsa3zuPNM=SfGMqg8?TLFYQ4)L=h z;4fCbUqlSq3??c=t!Asg)BN2VW%=xWq$UNOyR$8^ocqkTvTi{}Ry{TvQ*{ZnoE*sR zp@EwGLs0-(V>nH^a#I0+y}%*{jhhD9dCL^;!dKAW9Q6(xfsDsV{yHx(0k{ZQUx@30 zMglTN@-6uzKcW*hy$kjGk1N+~QS*B7dP$CxqvsVA|GWz1k*4ZoW}-oU;wKbBOF4`Z zh|nJwO^Zd~00MddSnT-I#R>z8-PfOSVcMKd46;}vPhHt04dm3{B7Y22JlE3wp_tK9rY{4yYI9nv-R6}LZ_#?SD@Y0& z4~XA*5{@vUN7;C7);TRxh40+IbUPt);4 zllS?14xiW0qBSDby!<7UlU{c0Uv4AKv|%Wu`q#4Ouq%QUEe?@Pc5hnb45+`EIJ*-Oe$7mAkjhuE$8kWjpSj3@w3 zzx=!Ga0DEkl2-5l8GMcwO5+~vkT~S&*mLrD*cah7owfj`sDrh{Uy_y^S4auHfVCKJ zP?ZuyUyL?-U?q4u>}SF#lVttIaMY#m_F=CSerR~qyOF-**kYjRY2*{2BW?{}1>N{L z>?rP+a6`gaxVv^=WMgYvD5^UH$DKS&tR|OnI@((k6TT4>Q@rp195lmd zX;TCcYBXB(0M0N2DDnTYG;doP`3!irbB$0u9f*hJ-j5_A9~Y2#b4@gw^Ls~Ys<26! z=1(U!p$8Tm|8mS;_R)l(@~H^_krIG3C+V;7duaayIz*BsOZYy~jq}5f_OX+!hPp5d ziva6lTz=)Cr9BS3sz&^a^VkAiCNw0k^iLc3A!~PB5T~P0-nT`+t1qKoPUzT+D&-l* z)d3T81kH?>hXb^E$uicP)(RYnnZ-gvFR}o#fE#C71!@@tCXhysChC`XmIp6#PHd}b z&$#r(O4GnUkj&PjPQI^UH2do$(f^ehWu*@{3R;*EDgCTU%x75NJJb1Gb1t6dyUj@o z7lN^YWaDp18!>?RXfM}8m%>FBGLgd9+USfxO;}fL{DR8(g(QtJ2JOGMC0J9X$A!dl zyJ9qMod?~_NrnXxBm~jWc)1$h&v7!=&AkDmmUdEM%SGY7*;=d3=so%G*+}Nh=gX!W z_ktbOUkCD#UxI@`h^QK!LPL5aXX?tp;G|2`1X%!a#6(4`Tn>(RbKu!vN;riDP8u#H zX?F{Fc~0#&AWJG=7Qh#!2PJ|85CJWu0wiHGd^R&R6ILCNrB!qQN92x%JuG&Iru$D; zTx*hfC&bD+7l4;3V2>UjQ<6l&Khh`Z$}y)O`%oN}8&DGjC@4tatPF`_5ACQ_{cF2z zh`}HPjek#N`GgHJp+~WAc1OFcsnJmZQT?wLhkHE+!NUIUz^|uSo`VXrUSDv3n-HqA z?iE()s$u}emB%J-XFxNO{cU=StU4NwAP+1JfvV6~6Pi|_uXO0tA_%(6l2qc+xdVZ> zK$*YNzljCHobv&0+(6<5V%|*tnG=gQ3}7)^2HRieokSM$KNx1WP>ggve;&S~nUve~ zyQ|gsfZUL!plb%fiW>s$XDgq~2$nxP@XV!OI^aKHB0$pQ3J{pU9Wl@dzejww#13%b z^7ASy-sB5%q;WKisZz}LeJS--S3aX#6lM(}#SA^opAyR_{x1XJj`4l*+}Wrn0U&N$ zPwoLaLSS+r0uG0~^6}ot4W1iZMzdEyrun;fFX*))Za(vvFQ!Jr!V;@BJIsV@)X;w9ghs zGE_v+ll7JSkd>!PN$b<>ndCFDG6Zn|ltI8}(T>7RRs@vZq{#2NX)ZH1{0AI(i$EG~ zu;I5=gt<*QAvuhkzn)8Kd!TP}=yl`4`OrAdU+uS`AKNc3_ZljG!&3WtN!g&T1!#>! zoo3`96veNj2SxW)0Ey8wxV6E0t9v+}AE>S;TDsP!Ziu4%?}5*NL~?xdvOObNbqYk8 zkk7)B%)WzbWU1}Rf(zJpXPEud&h?UG$h$YGmITjO?rPR9&1qqDkV1TB9ep^YULI)_ zZ!tLB4Ek#HVXeuV!+{f-iswEJP1~kuXd^Y}cv~ZtWgj zX(Z`){-D$S=0-%nR;WuDJS_jRP`m`0{keeq!i!Up7R&5z!GvNNqcu(RO z$kQ-Rg+hHS79c&8BfYQ63YJd7P(rSh8mm5c&ojExER(NK5T@8FWyI&+ch>i%&Ea5# zix`cyGBo33(R`f{tvt59&*BC{0I!Mpmn6@ghSUa!_G97x z2i+-U(U-2|KV3%4j|-!s5=V>pi3YyJuR?o43k@M( z5#qH1`FMThq$jTAL*L`6amI!F4iFat18!@E&AIRr_lkUCI8@CH(1{#01ZfP`28z zkYt#Uia>liW9%(GA(3hqSIPZ9y#N|xE1zjPgxh6p=>g`vxD1hW<9TQhaP9ELCFn^c zxJ~byV|nb6|Lg^|_bJr(luQbfk>oE2KutU0RlK7DXcZQwC{M3Ji~IpY9Nkcyu%@$D z#2bC@6ZKY|lA{B`+iyQU`Bhfp{4l}X;k&JJ_i^T6#5KhThG-s+?5Br$(}N_Mtb9i& z?&(4p5m8)Ec~y%^-(Gp9+264zNKVuRJ6}`fW`k>9S`i?3QbdpK83An39D5XEDHu_w z3l#<75~jG>t9=WK@z`G9uZ&c{#esZLfa32Oql6GB6dg-P-y>(~fx1UMU;ho1?@+rfl`gP1z;c79YtT<4VwV}$dk#&5)d4)nzndF7Xx)AvttPFW~o0F z%}5A*v?k(86+pDb=)w?Ui|ZURR#xy8UYv!^ZF5L2rj`9A`{<)OG&s}M?9%pq)t%v< z9(_k2VAO5}z@vUiMVvG#uK5#r)2miR7<-(#n|Hd}A5kLlHotq&Ps*S09J`W4*@Ov! zGQ@53q$c^qka^x z^*3K6&b|Fl%%+3@W#|adIK_dM?D{ry$FFdci6wt33`{1?)KpviLP(;->y1TZhajz6 zSOPnsWAx7xQM)qf1k6SF8)d%a3WB&|5ARP@9yB4d6_2QFOfBip=x~je%1@IRCgvay zzzdzs@)B)o^NskAsUhi-W6?TX52w60F&Q=y{s9UopIMjXCa9=-If2>is?I2Ty)Tl& zVTQXR58(fb(_mj_CVEE06T4*B!RebWc?ZKcHAxh?UyW}nQKC&_QIUS>%uGqTNwT7J z1{-wR4Avea0P&RZa|d99vj2n3YqPz7=R#@!IlWR z`KN9-&25uZ$!5%KaXlV9G1G^7kFEnA+@~oMJRi zjH{w32ZMydJgh^cLeRqUIg1|J!`0BUn2zTNb~N}4Jl7ixNc0e%+Ide4>Wb}Xd|$KN z!lssTr9S)>=D_bx&YK9~$#twsmDs8>oSVUE5I5t83bOl~3M5v9;4B*U|K$oG+^z4x zyz%Ei6FiCbPdRksAV?K)(a_s3#Z8^A*foWc>l8UVaf{L4E_X%^h~^#GbG1b&OTT|J zfKUygyk}O}xNdUlp>)Puw7Qp;ho5O@IqSlLzP@vGq`1&GfRDg4^B~)$!!4f5zX4Bt zz0cwFfI)3^r!D0cXdzW^-zt` z%5!8j>XLqAHWwBLZ(oC+zK!>3L`w7h!qG%`b~iIyF~UgKxBjxchiV5BMgq$IK2yR1 zg(GnPS3f-M4+a#N;=lF9p`KSp39_CxJ30TkFnrhJ@HhQK)ayS_fL1^)pR8^!bPQv}_(Jvupl zW4As^7@lny$#89OcPfeZx5%cW30zJfn=nofTPUM}vwq#D%2n5wf~F>&QrE zMl?{A(NrlHIx>q-TtufU6f&~P`n{>&`2PIueXrN+@tm*6^Z9zcHl$+A$fZR~78)-5 zkYtUn{8lw&2o7>~DF0>DNO{ulAwtJ@hF(fy`;!a5-?{p(nk!XxUncq-NbD7PeH`;! zf@oEtUTK%FCJ(i7M^s_IlUlG0J>inWY5kMGRS~a3_g{@ctvc4GXmnoHCVz34gA=gw z`kTph<0ggDKV3dLhH_{7%o zW@G88rSs71_C+sD4G$ujgs$h~YDkYbApHiVK)}R~BLLF3UTpU1yze^^s_o;WsohVx z5zqTMy~O?}0coA#XoxkD_{rg{NrRjNiFpncvOiz`NwS=L;|&W@hi&V3$0dVM5bvGL z_@?fWvmjKjV&j2vaPy~4V76Oz$I`?)*bU#_VfqHP4Hp*}&l~-rcn_?5-hgSC z4NI`_Koy+3@bhPqO@h99*0ffTs!YHs-lBQ()u>M43}m`7W1s3;qYYE=qU2JKs!xa8 z!IeOexm?q$yqQUOX9ZvGdlnfiH|>LYgrt6K+b1#txe_QcR5#jvzy9D+_guTzk`U(u zOdC`O(h6$k)LTv(P`&=3t&X1?eqrN!F8D$SvvQ;RIhtGuZY!}PH|kTp&xsB6DXLbk zl%3)tAztD=LDHrr=^$l)YjlNC{xW11Br$y`V z1vwzd2@LJzUgQjW9A(h$s(AD1p3Z=LnSdVvx490IJ@>hXJ=(bo*YM4J?k#%=q5c3r zUGn2#@`qu*{Dk9A)m@$@laF5~D%`teXK`D8AE;fY5XO377)k;jt@7mxAfd1nKtu9n zT#^aM?|y6|HxM{MQ6W>)cWOWSE#{sdVN9gG?s(Q4uuV%H##M$UGzE>@zNa0{{`CeQ zSoHi-xob%3XKhCw?AVkNMo7N?>rcTN{*8mVdtRhG^XV=_ zYSJ`pI&bJXeWt2D z`IV(il(~aKEQ1`Kf3puz#K^ftDf@q^oJU1y2L0DI2=4oKzR#}Zp+U@m@Z2K5);MJ!);1m^niUywRyB_w$J>#OH@ahBB_B4+R^V{otDO5GRTw< zmzpkQG7jKu?B#?4$9~Vqaf)|wnwlzSJUo{?icyO261yFT|HHtaLqJNhJ*lJb6mk3; zWjFNGJUVu|P>p+}x23PzFQP_WvLr;)<=VplL72ZAC9AIQ!27ezA1`N*L@-U!C-hs2 z`-t9UJ030kYA+>=B9Be!@|=j@EI2I#9&^;tk6PQmY>GS)!^wU)_Q0`DJZ?Aa@l;?z z<{2HDMpK8r$<0!`Z3U7Q2Hm3~wGD#x{hswjxE0Nn2o;O$`O+ldPNB$Id+*QjM|qU{ z)*_?P67q2Vejhy-%XGj`cZS9%a>>Z42M|QlFw~z>N(=`&xf>+0x2c~VEr3jZyeEu` z`q1iVY_;1bqUvMq^WRa%LbskI{qkjPZ(bGv%qy-(dUQ32$<)(ZiY|PhU5()j!g7n} z^qsA{xp)0up$B#qV5p%A>ir_{KT=@)-uOo0x*%KzJKV@&C!IK|S)J28>>tw6LXzRw zgni7DK}=zBgDOjVx{SYrL&@=2*_j!mdXav3c;#Aj<@)2jhI7(C@F_Uo3b ziMJu4#x@|YxOQLu4_M$PGf&iVGMhtGsL#%6*fF0{dKW_42WWExZT`(FHGw*{gC{Op z8Cn0-dMCY0#OJ1(hIW?hp${bzkfb*^GemdkD9v0Lh}(5;`fZGX9g^J8d1qV!83KW3 z4{j^;!_DIX-cr%C0uWh?>$0~e`u+FmTXkPQYAjQ&Kv98}3%iGQKC22PdpW|%?`y2B z;BG(GV;y0&7G%qYxGR^~%NENyj;w_y@9lydBODm*7RBV~0??t$Apc$`5IfB~qFAF* zd|y>_HXRwIGxTW0uA+Q?Ffa-#^ib`o6Z1Q25?Ki$b%~+6 zGbNFAzewys-GC&)Lf6Y>d2I>D&peJ|yuSWrB=Y6DcY$G?C199t5R%=HY+Ws1$scGV zkvJRkFs`9Am0fYsZt>d)hY(|}jU6-Jl&d#(r6!fL zTHLBE!zD%3x3hL$BS}e^p?|%4IM>>na!WZq2yPx&uSaiA;k_2vG$S$J9NHt%y}!a7 z+`n#Bpy4z{__Ai+qVcWb?JP?|hwYwMi_!6UP9;}g6tMd4IU1Hvqq)IX9=bH*Db8=1 zB%th!FrPhf(q*W@dXK~(AbepXIU3NEQ|H&TE)~OtgRhShA4qf!3&V;LV6Xi3ePcP-!C_W zpD*DTnhP6>f$=M}d@0?4H}?3?B@4K^H>Iz6Es;!S{T_=$rX_308Ku#ww?}`*5H+B8 zp0D|KpkZNnpG$PV;Tf}@+SotQ-*HlBfPO$vEaf5!cRYtDA@t9$Dd@3{VW*Ah&iJPT zCi^Z*>^;aID{FRj{k7XC?FR@u^baG4;%ZY~^1L`m=k$TbYUNL1JqAK;YSuNL4PQFP zYUp8WW!}%Ocxqj2h~PC4j79$JYm9s*nET-To!-&FPwm^mQ%$7R(=BnuOFnN{@e1Cv z#j)2BSCC}?240H@ut)~RNinNuC%Vp9G(UlL7SHL_DrTC-dt$|kaZKp`#ZuYdAz zq$x{a7Y6?U{9#L2ei@qV3BLIad0Y|O{^Zzl;(Lf43`~IOyvHp-P7e=}8H~>N&2hra zbhUO-<8m3lVai|EHBLSCtS_EzJ-pi`4u6#IENOFp<8~HSrW-jUD7UDM*mF9SysrX| zyL49A*jD3o$=fmvRjt?xzYo-GGb|_jSGs3`AEHh;&k-}`rh19nq$R^)0G=Ei`&Pu?qrzV`96kQ z7wFJg{zfQ=!~x?b-a!dq3Ur%HHF?De|LR53a)C7dq-2rVjVacso4oceD@qdPDsSF_ zkG9NJ21;RbG*6SL*OD@*_fQYZUW4^4StX|@*n}m&C$r4P3vA;%yRTrVrbQRupTvw~ zpd#+Ui_$Whu0jF^SG10vUdR_8R~I!zh-sM;gA=NLV_-(8AS0Q~DcS<=)vg723z!yTWREMeO={$vUdUM1mtGk!QW6avlb5=algjYVHraJgTCr`vFF^<>r3A*duEwmLb%V^anXf^dv+7;5ZSw)gM zv7eh^x(_r39NUSetPYMD%K#dLgYOv*x9NhFTt^CO

0HSWCyvWr6B-lL=!WFwQ(N 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 Y6>fI-*oI9n0>D2T%YznGW)%AW0xra9sQ>@~ From 66ebb0be54ac01c9f5c5c2e773454f46af817d41 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 18:06:11 +0530 Subject: [PATCH 291/864] chore: move linux installer to distribution folder --- {src-build => docs/installer}/linux/installer.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {src-build => docs/installer}/linux/installer.sh (100%) diff --git a/src-build/linux/installer.sh b/docs/installer/linux/installer.sh similarity index 100% rename from src-build/linux/installer.sh rename to docs/installer/linux/installer.sh From 79a992a51dab2cde8cb640883847bb9931b8a509 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 18:19:18 +0530 Subject: [PATCH 292/864] chore: cleanup code to prevent deep nesting --- docs/installer/{linux => }/installer.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/installer/{linux => }/installer.sh (100%) diff --git a/docs/installer/linux/installer.sh b/docs/installer/installer.sh similarity index 100% rename from docs/installer/linux/installer.sh rename to docs/installer/installer.sh From 1669ac78ad02abc26478b050114261f8f11634ad Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 18:25:14 +0530 Subject: [PATCH 293/864] chore: code clean up --- docs/{installer => linux}/installer.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/{installer => linux}/installer.sh (100%) diff --git a/docs/installer/installer.sh b/docs/linux/installer.sh similarity index 100% rename from docs/installer/installer.sh rename to docs/linux/installer.sh From e435a27f06190ea5981bec0a7d5a906251debf5b Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 19:50:12 +0530 Subject: [PATCH 294/864] chore: add error handling for install linux script --- docs/linux/installer.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 01c70d36..f4375601 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,4 +1,5 @@ #!/bin/bash +set -e # Exit immediately if a command exits with a non-zero status. # Define common variables APPIMAGE_DIR=$HOME/.local/bin DESKTOP_DIR=$HOME/.local/share/applications @@ -11,10 +12,10 @@ ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" install() { # Fetch the latest release data from GitHub echo "Fetching latest release from $GITHUB_REPO..." - wget -qO- $API_URL > latest_release.json + wget -qO- $API_URL > latest_release.json || { echo "Failed to fetch latest release info"; exit 1; } # Extract the download URL for the AppImage - APPIMAGE_URL=$(grep -oP '"browser_download_url": "\K(.*phoenix-desktop.*\.AppImage)(?=")' latest_release.json) + APPIMAGE_URL=$(grep -oP '"browser_download_url": "\K(.*phoenix-desktop.*\.AppImage)(?=")' latest_release.json) || { echo "Failed to extract AppImage URL"; exit 1; } # If no AppImage URL is found, exit the script if [ -z "$APPIMAGE_URL" ]; then @@ -25,8 +26,8 @@ install() { # Download the AppImage echo "Downloading AppImage from $APPIMAGE_URL..." - wget --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL - wget --show-progress -qO $ICON $ICON_URL + wget --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL || { echo "Failed to download AppImage"; exit 1; } + wget --show-progress -qO $ICON $ICON_URL || { echo "Failed to download Icon"; exit 1; } # Remove the temporary JSON file rm latest_release.json From 30a87ced2461599179a9c7421005f677d749bda0 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 21:35:05 +0530 Subject: [PATCH 295/864] chore: add retry to wget --- docs/linux/installer.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index f4375601..ab84f218 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -26,8 +26,8 @@ install() { # Download the AppImage echo "Downloading AppImage from $APPIMAGE_URL..." - wget --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL || { echo "Failed to download AppImage"; exit 1; } - wget --show-progress -qO $ICON $ICON_URL || { echo "Failed to download Icon"; exit 1; } + wget --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL || { echo "Failed to download AppImage"; exit 1; } + wget --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $ICON $ICON_URL || { echo "Failed to download Icon"; exit 1; } # Remove the temporary JSON file rm latest_release.json From 1e9e6c088f546bd40d1c08196896585696bbc146 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 1 Feb 2024 21:58:32 +0530 Subject: [PATCH 296/864] chore: adding partial retry while downloading binary --- docs/linux/installer.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index ab84f218..8d3f3731 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -3,7 +3,7 @@ set -e # Exit immediately if a command exits with a non-zero status. # Define common variables APPIMAGE_DIR=$HOME/.local/bin DESKTOP_DIR=$HOME/.local/share/applications -NEW_APPIMAGE=phcode.AppImage +NEW_APPIMAGE=phcode ICON=phoenix_icon.png GITHUB_REPO="charlypa/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" @@ -26,8 +26,8 @@ install() { # Download the AppImage echo "Downloading AppImage from $APPIMAGE_URL..." - wget --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL || { echo "Failed to download AppImage"; exit 1; } - wget --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $ICON $ICON_URL || { echo "Failed to download Icon"; exit 1; } + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL || { echo "Failed to download AppImage"; exit 1; } + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $ICON $ICON_URL || { echo "Failed to download Icon"; exit 1; } # Remove the temporary JSON file rm latest_release.json From 39ac6f59d3715e63ab246ab473ad9c07ccf0486f Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 3 Feb 2024 08:19:18 +0000 Subject: [PATCH 297/864] ci: update phcode version to 3.2.24 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 17dd4cb4..b034b883 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.23", + "version": "3.2.24", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "49bef69a5d28135b380b416a5155472461f0b77c" + "commit": "e3f1eec12b02bea9d5bcd44155340e7907cba2cd" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b94f7069..47b1f357 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.23" +version = "3.2.24" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c9c5b06f..021e4c02 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.23" + "version": "3.2.24" }, "tauri": { "allowlist": { From dde26f47ad0ca050ba81e87c7712975b1613ac48 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 3 Feb 2024 14:18:21 +0530 Subject: [PATCH 298/864] chore: add hidden window that handles health data due to phtauri custom protocol --- src-build/createDistReleaseConfig.js | 36 +++++++++++++++++++++++++++- src-tauri/Cargo.lock | 2 +- src-tauri/src/main.rs | 3 ++- src-tauri/tauri.conf.json | 14 +++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index 57444e3b..f7cee06b 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -9,14 +9,42 @@ import os from "os"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); +const METRIC_URL_FOR_STAGE = { + "dev": "https://dev.phcode.dev/desktop-metrics.html", + "stage": "https://staging.phcode.dev/desktop-metrics.html", + "production": "https://phcode.dev/desktop-metrics.html" +}; + +function _patchTauriConfigWithMetricsHTML(tauriConf, metricsHTMLPageURL) { + const window = tauriConf.tauri.windows[1]; + if(!window.label === "healthData"){ + throw new Error("Expected tauriConf.json- tauri.windows[1].label to be 'healthData'"); + } + window.url = metricsHTMLPageURL; + const metricsPageURL = new URL(metricsHTMLPageURL) + const dangerousRemoteDomainIpcAccess = tauriConf.tauri.security.dangerousRemoteDomainIpcAccess; + for(let ipc of dangerousRemoteDomainIpcAccess) { + if(ipc.windows.includes("healthData")){ + ipc.scheme = "https"; + ipc.domain = metricsPageURL.host; + } + } +} + async function createDistReleaseConfig() { const platform = getPlatformDetails().platform; const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` : `${__dirname}/../src-tauri/tauri.conf.json`; + const phoenixConfigPath = (platform === "win") ? `${__dirname}\\...\\..\\phoenix\\dist\\config.json` + : `${__dirname}/../../phoenix/dist/config.json`; const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` : `${__dirname}/../src-tauri/tauri-local.conf.json`; - console.log("Reading config file: ", tauriConfigPath); + console.log("Reading Tauri config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + console.log("Reading Phoenix config file: ", phoenixConfigPath); + let phoenixConfigJson = JSON.parse(fs.readFileSync(phoenixConfigPath)); + const phoenixStageInDist = phoenixConfigJson.config.environment; + console.log("Phoenix stage in dist folder is: ", phoenixStageInDist); console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist/'; @@ -26,8 +54,14 @@ async function createDistReleaseConfig() { } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } + const metricsURLToUse = METRIC_URL_FOR_STAGE[phoenixStageInDist]; + if(!metricsURLToUse){ + throw new Error("Unknown Phoenix stage(config.environment) in file " + phoenixConfigPath); + } + _patchTauriConfigWithMetricsHTML(configJson, metricsURLToUse); console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); + console.log("Window Metrics url ", configJson.tauri.windows[1].url); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f1ee3416..8675ee01 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2742,7 +2742,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.21" +version = "3.2.24" dependencies = [ "clipboard-files", "fix-path-env", diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 8f7acb0b..dceb0bbd 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -32,6 +32,7 @@ mod utilities; mod boot_config; mod platform; +use tauri_plugin_window_state::StateFlags; #[derive(Clone, serde::Serialize)] struct Payload { @@ -277,7 +278,7 @@ fn main() { Ok(response) }) .plugin(tauri_plugin_fs_extra::init()) - .plugin(tauri_plugin_window_state::Builder::default().build()) + .plugin(tauri_plugin_window_state::Builder::default().with_state_flags(StateFlags::all() & !StateFlags::VISIBLE).build()) .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { println!("{}, {argv:?}, {cwd}", app.package_info().name); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 021e4c02..c2b7f3cc 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -364,6 +364,14 @@ "extn-29", "extn-30" ] + }, + { + "scheme": "http", + "domain": "localhost:8000", + "enableTauriAPI": true, + "windows": [ + "healthData" + ] } ] }, @@ -389,6 +397,12 @@ "minWidth": 800, "acceptFirstMouse": true, "fileDropEnabled": false + }, + { + "label": "healthData", + "title": "Health data window", + "url": "http://localhost:8000/src/desktop-metrics.html", + "visible": false } ] } From ffb3672eff63b32ffdaa5d6698dc78fed230ee96 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 3 Feb 2024 14:36:11 +0530 Subject: [PATCH 299/864] ci: scripts to inject metric urls for ga --- src-build/ci-createDistReleaseConfig.js | 6 +++- src-build/createDistReleaseConfig.js | 37 ++----------------- src-build/utils.js | 47 +++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index e155d021..a784be9b 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -9,6 +9,7 @@ import { import { EOL } from "os"; import os from "os"; import fs from 'fs'; +import {patchTauriConfigWithMetricsHTML} from "./utils.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -98,8 +99,11 @@ async function ciCreateDistReleaseConfig() { const bundleIdentifier = BUNDLE_IDENTIFIER_FOR_STAGE[phoenixStage] || "io.phcode.unknown.stage"; console.log("Product Bundle Identifier is: ", bundleIdentifier); configJson.tauri.bundle.identifier = bundleIdentifier; + + patchTauriConfigWithMetricsHTML(configJson); + console.log("Product update endpoints are: ", configJson.tauri.updater.endpoints); - console.log("Writing new dist config json ", tauriConfigPath); + console.log("Writing new dist config json ", tauriConfigPath, configJson); fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); // patch info.plist for mac diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index f7cee06b..c22c278d 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -3,48 +3,20 @@ import {dirname} from "path"; import fs from 'fs'; import chalk from 'chalk'; -import {getPlatformDetails} from "./utils.js"; +import {getPlatformDetails, patchTauriConfigWithMetricsHTML} from "./utils.js"; import os from "os"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); -const METRIC_URL_FOR_STAGE = { - "dev": "https://dev.phcode.dev/desktop-metrics.html", - "stage": "https://staging.phcode.dev/desktop-metrics.html", - "production": "https://phcode.dev/desktop-metrics.html" -}; - -function _patchTauriConfigWithMetricsHTML(tauriConf, metricsHTMLPageURL) { - const window = tauriConf.tauri.windows[1]; - if(!window.label === "healthData"){ - throw new Error("Expected tauriConf.json- tauri.windows[1].label to be 'healthData'"); - } - window.url = metricsHTMLPageURL; - const metricsPageURL = new URL(metricsHTMLPageURL) - const dangerousRemoteDomainIpcAccess = tauriConf.tauri.security.dangerousRemoteDomainIpcAccess; - for(let ipc of dangerousRemoteDomainIpcAccess) { - if(ipc.windows.includes("healthData")){ - ipc.scheme = "https"; - ipc.domain = metricsPageURL.host; - } - } -} - async function createDistReleaseConfig() { const platform = getPlatformDetails().platform; const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` : `${__dirname}/../src-tauri/tauri.conf.json`; - const phoenixConfigPath = (platform === "win") ? `${__dirname}\\...\\..\\phoenix\\dist\\config.json` - : `${__dirname}/../../phoenix/dist/config.json`; const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading Tauri config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log("Reading Phoenix config file: ", phoenixConfigPath); - let phoenixConfigJson = JSON.parse(fs.readFileSync(phoenixConfigPath)); - const phoenixStageInDist = phoenixConfigJson.config.environment; - console.log("Phoenix stage in dist folder is: ", phoenixStageInDist); console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist/'; @@ -54,14 +26,9 @@ async function createDistReleaseConfig() { } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } - const metricsURLToUse = METRIC_URL_FOR_STAGE[phoenixStageInDist]; - if(!metricsURLToUse){ - throw new Error("Unknown Phoenix stage(config.environment) in file " + phoenixConfigPath); - } - _patchTauriConfigWithMetricsHTML(configJson, metricsURLToUse); + patchTauriConfigWithMetricsHTML(configJson); console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); - console.log("Window Metrics url ", configJson.tauri.windows[1].url); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); } diff --git a/src-build/utils.js b/src-build/utils.js index 9a5a5f5b..693f28c6 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -1,7 +1,14 @@ import * as fsExtra from "fs-extra"; -import {promises as fs} from 'fs'; +import fs from 'fs'; +import {promises as fsPromises} from 'fs'; import * as path from "path"; import * as os from "os"; +import {fileURLToPath} from "url"; +import {dirname} from "path"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + /** * Asynchronously removes a specified directory if it exists. @@ -45,12 +52,12 @@ export async function removeDir(dirPath) { */ export async function listFilesAndFolders(startPath, filter) { - let files = await fs.readdir(startPath); + let files = await fsPromises.readdir(startPath); let folders = []; for (let file of files) { let fullPath = path.join(startPath, file); - await fs.stat(fullPath); + await fsPromises.stat(fullPath); if (file.startsWith(filter)) { folders.push(fullPath); } @@ -90,3 +97,37 @@ export function getSideCarBinName(platform, arch) { } throw new Error(`unsupported ${platform} ${arch}`); } + +const METRIC_URL_FOR_STAGE = { + "dev": "https://dev.phcode.dev/desktop-metrics.html", + "stage": "https://staging.phcode.dev/desktop-metrics.html", + "production": "https://phcode.dev/desktop-metrics.html" +}; + +export function patchTauriConfigWithMetricsHTML(tauriConf) { + const platform = getPlatformDetails().platform; + const phoenixConfigPath = (platform === "win") ? `${__dirname}\\...\\..\\phoenix\\dist\\config.json` + : `${__dirname}/../../phoenix/dist/config.json`; + console.log("Reading Phoenix config file: ", phoenixConfigPath); + let phoenixConfigJson = JSON.parse(fs.readFileSync(phoenixConfigPath)); + const phoenixStageInDist = phoenixConfigJson.config.environment; + console.log("Phoenix stage in dist folder is: ", phoenixStageInDist); + const metricsURLToUse = METRIC_URL_FOR_STAGE[phoenixStageInDist]; + if(!metricsURLToUse){ + throw new Error("Unknown Phoenix stage(config.environment) in file " + phoenixConfigPath); + } + const window = tauriConf.tauri.windows[1]; + if(!window.label === "healthData"){ + throw new Error("Expected tauriConf.json- tauri.windows[1].label to be 'healthData'"); + } + window.url = metricsURLToUse; + const metricsPageURL = new URL(metricsURLToUse) + const dangerousRemoteDomainIpcAccess = tauriConf.tauri.security.dangerousRemoteDomainIpcAccess; + for(let ipc of dangerousRemoteDomainIpcAccess) { + if(ipc.windows.includes("healthData")){ + ipc.scheme = "https"; + ipc.domain = metricsPageURL.host; + } + } + console.log("Window Metrics url ", tauriConf.tauri.windows[1].url); +} \ No newline at end of file From afff3ac6282f6a95fb339bef96206c39affc903b Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 3 Feb 2024 14:40:14 +0530 Subject: [PATCH 300/864] fix: sonar issues --- src-build/utils.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src-build/utils.js b/src-build/utils.js index 693f28c6..a0cd312f 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -1,6 +1,5 @@ import * as fsExtra from "fs-extra"; -import fs from 'fs'; -import {promises as fsPromises} from 'fs'; +import fs, {promises as fsPromises} from 'fs'; import * as path from "path"; import * as os from "os"; import {fileURLToPath} from "url"; @@ -117,7 +116,7 @@ export function patchTauriConfigWithMetricsHTML(tauriConf) { throw new Error("Unknown Phoenix stage(config.environment) in file " + phoenixConfigPath); } const window = tauriConf.tauri.windows[1]; - if(!window.label === "healthData"){ + if(window.label !== "healthData"){ throw new Error("Expected tauriConf.json- tauri.windows[1].label to be 'healthData'"); } window.url = metricsURLToUse; From 4f3a29bccf73124db1a7a456fa4f6202bf94f9e7 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 3 Feb 2024 15:24:11 +0530 Subject: [PATCH 301/864] fix: release gen fail --- src-build/utils.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src-build/utils.js b/src-build/utils.js index a0cd312f..f13c4b3d 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -103,10 +103,14 @@ const METRIC_URL_FOR_STAGE = { "production": "https://phcode.dev/desktop-metrics.html" }; -export function patchTauriConfigWithMetricsHTML(tauriConf) { +export function patchTauriConfigWithMetricsHTML(tauriConf, useClonedPhoenix) { const platform = getPlatformDetails().platform; - const phoenixConfigPath = (platform === "win") ? `${__dirname}\\...\\..\\phoenix\\dist\\config.json` + let phoenixConfigPath = (platform === "win") ? `${__dirname}\\..\\..\\phoenix\\dist\\config.json` : `${__dirname}/../../phoenix/dist/config.json`; + if(useClonedPhoenix){ + phoenixConfigPath = (platform === "win") ? `${__dirname}\\..\\phoenix\\dist\\config.json` + : `${__dirname}/../phoenix/dist/config.json`; + } console.log("Reading Phoenix config file: ", phoenixConfigPath); let phoenixConfigJson = JSON.parse(fs.readFileSync(phoenixConfigPath)); const phoenixStageInDist = phoenixConfigJson.config.environment; From 951a665544356a1a7c3b2ae49e96015d295eb456 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 3 Feb 2024 15:25:28 +0530 Subject: [PATCH 302/864] fix: release gen fail --- src-build/ci-createDistReleaseConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index a784be9b..59821a08 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -100,7 +100,7 @@ async function ciCreateDistReleaseConfig() { console.log("Product Bundle Identifier is: ", bundleIdentifier); configJson.tauri.bundle.identifier = bundleIdentifier; - patchTauriConfigWithMetricsHTML(configJson); + patchTauriConfigWithMetricsHTML(configJson, true); console.log("Product update endpoints are: ", configJson.tauri.updater.endpoints); console.log("Writing new dist config json ", tauriConfigPath, configJson); From 52da44b86c7d8fd879821b98744d658ff09bafe2 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 3 Feb 2024 18:09:41 +0530 Subject: [PATCH 303/864] chore: add get_current_working_dir tauri api --- src-tauri/src/main.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index dceb0bbd..1420809c 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -5,12 +5,11 @@ windows_subsystem = "windows" use std::env; use tauri::{Manager}; +use std::path::PathBuf; #[cfg(target_os = "linux")] use std::fs::metadata; #[cfg(target_os = "linux")] -use std::path::PathBuf; -#[cfg(target_os = "linux")] use gtk::{glib::ObjectExt, prelude::WidgetExt}; use std::process::Command; @@ -61,6 +60,10 @@ fn _get_commandline_args() -> Option> { Some(env::args().collect()) } +#[tauri::command] +fn get_current_working_dir() -> Result { + env::current_dir().map_err(|e| e.to_string()) +} #[tauri::command] fn _rename_path(old_path: &str, new_path: &str) -> Result<(), String> { @@ -287,7 +290,7 @@ fn main() { .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ get_mac_deep_link_requests, - toggle_devtools, console_log, console_error, _get_commandline_args, + toggle_devtools, console_log, console_error, _get_commandline_args, get_current_working_dir, _get_window_labels, _get_windows_drives, _rename_path, show_in_folder, zoom_window, _get_clipboard_files]) .setup(|app| { From e130b43a6df96e2f242a9bfab8cfdd4299e89fd3 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 9 Feb 2024 03:31:21 +0000 Subject: [PATCH 304/864] ci: update phcode version to 3.2.25 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b034b883..9baf711a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.24", + "version": "3.2.25", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "e3f1eec12b02bea9d5bcd44155340e7907cba2cd" + "commit": "c9a1195b5c93b39cf4dc3eb4be9bfdbea80636aa" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 47b1f357..44882402 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.24" +version = "3.2.25" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c2b7f3cc..87ada26c 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.24" + "version": "3.2.25" }, "tauri": { "allowlist": { From 1c352d97e563f3270d01002114e5050b8cbe29ee Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 10 Feb 2024 07:26:43 +0000 Subject: [PATCH 305/864] ci: tauri release update notification json --- docs/tauri/update-latest-stable-prod.json | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 docs/tauri/update-latest-stable-prod.json diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json new file mode 100644 index 00000000..ebdb3cde --- /dev/null +++ b/docs/tauri/update-latest-stable-prod.json @@ -0,0 +1,23 @@ +{ + "version": "3.2.25", + "notes": "First Beta release test.", + "pub_date": "2024-02-09T08:17:34.326Z", + "platforms": { + "linux-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxKS0x4Yk4rZ3R2Q1NucHJyM0xxMVA1cEZzQmRIaVM1VXArT0VMOHRQWDBmbFlybmpFR0tiQ3diclhtRkYvRWJURUExQ05xRXF4Qm5VMmI4cGdVUEE0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NDY0ODY2CWZpbGU6cGhvZW5peC1jb2RlXzMuMi4yNV9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKMStobVhoVHJKQkZ4eWs3RVJWQjZWRUsxeVgvd21qSVVidnBlR3NjZXRhNWE3bmxlNm13ak42Szk3bUlsMUtLVHJybnZsWXdndEZtSlRGeUxhQ1lOQlE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.2.25/phoenix-code_3.2.25_amd64.AppImage.tar.gz" + }, + "windows-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlFb1YvdllFeHlGZ2ZPc1hDKy90V1hDWnJQYWVRSlFSVnFzM05BZ0xwZ1VKQWczMWY0WnEwSjBqemUweHVhdnRjcVU0M0M5OFRyS1FaMVNXYVdlUlFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NDY0OTg1CWZpbGU6UGhvZW5peCBDb2RlXzMuMi4yNV94NjQtc2V0dXAubnNpcy56aXAKLzhRSDVhdlJhTTdwLzZWdmNISUM2eHdsemF0REZOeWsxZSt6OTJtZEhacnFnWlNxMmlxWU1veXFZdDRDOHY1QVArZmR1cjhONHF3VHNoaVI3RTVEQmc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.2.25/Phoenix.Code_3.2.25_x64-setup.nsis.zip" + }, + "darwin-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNQM1cvYzdyYXJJMXoxUlNteE4zQ1BzcjNhM0UyNG8zeVVqMm05U0ZqRFkwKy9sQXBpK2cyQVlkeCtwN0lQV0pNcHN0bnEyQmg4WXJVNlNpTjl5R3cwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NDY1ODI3CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKMHZRVnpXSi9xS1lyNHoxK24rTndjNE9yNDIyNklxdUhnamx2MnpjZHJWM0tGejU0Mk1aTVQ3b1lmek90MG1vWU9pZkNnT0FQM2IxZ0RnUlRTNFVHQkE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.2.25/Phoenix.Code_x64.app.tar.gz" + }, + "darwin-aarch64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1JY1dISHBTaGUzTGdGOEpORkpPTHRtakpyWUlkVVNLcFlwc25oUm50TzNqblVhRVA2QzA2R29ENGpycEZmcUdJdm9SZTF0Z1dxYzN4NEVoVG1oQ3c0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NDY2NjQ1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKaytxeThDTzNtMmU3WGlPZVpHNXFTR2VpRjNBd2FCT3hsdnphcTY0RXpwZ0crMGNpYUtRT2RlQjEvZjJYb1VOaHh2NXJDTjVUaEJhSEtWY0p2UVIwQVE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.2.25/Phoenix.Code_aarch64.app.tar.gz" + } + } +} \ No newline at end of file From 0c3cd2c1453d17168bec0284f77d00059023b957 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 10 Feb 2024 07:29:23 +0000 Subject: [PATCH 306/864] ci: update phcode version to 3.3.0 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9baf711a..c6a0dca1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.2.25", + "version": "3.3.0", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "c9a1195b5c93b39cf4dc3eb4be9bfdbea80636aa" + "commit": "5f5485d2d7f7e9e2aedc94e031632bcc56f15dc5" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 44882402..44e23d27 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.2.25" +version = "3.3.0" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 87ada26c..51cbf010 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.2.25" + "version": "3.3.0" }, "tauri": { "allowlist": { From 1256ff2b02fdec91bc0a1558535f1f2bf08e583a Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 10 Feb 2024 08:15:08 +0000 Subject: [PATCH 307/864] ci: tauri release update notification json --- docs/tauri/update-latest-stable-prod.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index ebdb3cde..a4d718dd 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,23 +1,23 @@ { - "version": "3.2.25", - "notes": "First Beta release test.", - "pub_date": "2024-02-09T08:17:34.326Z", + "version": "3.3.0", + "notes": "Testing update push", + "pub_date": "2024-02-10T08:12:41.560Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxKS0x4Yk4rZ3R2Q1NucHJyM0xxMVA1cEZzQmRIaVM1VXArT0VMOHRQWDBmbFlybmpFR0tiQ3diclhtRkYvRWJURUExQ05xRXF4Qm5VMmI4cGdVUEE0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NDY0ODY2CWZpbGU6cGhvZW5peC1jb2RlXzMuMi4yNV9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKMStobVhoVHJKQkZ4eWs3RVJWQjZWRUsxeVgvd21qSVVidnBlR3NjZXRhNWE3bmxlNm13ak42Szk3bUlsMUtLVHJybnZsWXdndEZtSlRGeUxhQ1lOQlE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.2.25/phoenix-code_3.2.25_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1aVVpWZVJ0RFAyN1BZbmRYKzhGUmM3bVZRZzJ6SnJycnlZc3VWUmlvWW1vR20vQzJOUWs1UnN6QS9MM2xrS2kzREYyczZEMERjSWRwZy9GdXB5ZXc4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTUxMDQwCWZpbGU6cGhvZW5peC1jb2RlXzMuMy4wX2FtZDY0LkFwcEltYWdlLnRhci5nego2b2wzeFdxZFFwOHFIY2VjZnZwTjBKSTQxM2FmclNNckowN1hsRnFQUjl1ZWovemNzbGRvVnk2WUFjV29vVmJKaHZjT2JKcXRvYkxoT3MxNTcwYnNEZz09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.0/phoenix-code_3.3.0_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlFb1YvdllFeHlGZ2ZPc1hDKy90V1hDWnJQYWVRSlFSVnFzM05BZ0xwZ1VKQWczMWY0WnEwSjBqemUweHVhdnRjcVU0M0M5OFRyS1FaMVNXYVdlUlFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NDY0OTg1CWZpbGU6UGhvZW5peCBDb2RlXzMuMi4yNV94NjQtc2V0dXAubnNpcy56aXAKLzhRSDVhdlJhTTdwLzZWdmNISUM2eHdsemF0REZOeWsxZSt6OTJtZEhacnFnWlNxMmlxWU1veXFZdDRDOHY1QVArZmR1cjhONHF3VHNoaVI3RTVEQmc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.2.25/Phoenix.Code_3.2.25_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVaVmNvbFBCdUh6QjhrYzFwNm5aYmRWSEdaNXRta1pWK1E2QWs1Qm9zNGtrVHFnSDVGSlNtb3lYV2ZwbEVOd1Z1TW5jWHhmejhWc1hVOWR0cmhyc1EwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTUxMjIxCWZpbGU6UGhvZW5peCBDb2RlXzMuMy4wX3g2NC1zZXR1cC5uc2lzLnppcApUOG16OVpWbjdkMys1bXhhTFpIOW10UG1LYWNFUVBkd0lpL2VES2EvdWViYTNhZHN4cTQzelhoSmxxTjFESnFOWGhXY3lYeFErUzNLaEdoU2JLWHFDdz09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.0/Phoenix.Code_3.3.0_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNQM1cvYzdyYXJJMXoxUlNteE4zQ1BzcjNhM0UyNG8zeVVqMm05U0ZqRFkwKy9sQXBpK2cyQVlkeCtwN0lQV0pNcHN0bnEyQmg4WXJVNlNpTjl5R3cwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NDY1ODI3CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKMHZRVnpXSi9xS1lyNHoxK24rTndjNE9yNDIyNklxdUhnamx2MnpjZHJWM0tGejU0Mk1aTVQ3b1lmek90MG1vWU9pZkNnT0FQM2IxZ0RnUlRTNFVHQkE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.2.25/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNGWk5ManFFZ3JkTXVVTk1ramlUOWhWYVI5SWRZUWpTOFhvSkUvd2tMNkFDSVg1LzhjVE0zSW5WejQzUk9pYU5JSmViVDBrQVErQ0hKVlptS3R1akFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTUxOTI5CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdHJEQUw1WTlaTHgwc1E4WUFlQXJ4aWVPZW50RVhLVkUwM096dnNrbms4WGZma2tDb0ZIY1hLMjArekhoQ3pKTUlVekFNUncwSHFIOExTQ2hPbERYQ2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.0/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1JY1dISHBTaGUzTGdGOEpORkpPTHRtakpyWUlkVVNLcFlwc25oUm50TzNqblVhRVA2QzA2R29ENGpycEZmcUdJdm9SZTF0Z1dxYzN4NEVoVG1oQ3c0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NDY2NjQ1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKaytxeThDTzNtMmU3WGlPZVpHNXFTR2VpRjNBd2FCT3hsdnphcTY0RXpwZ0crMGNpYUtRT2RlQjEvZjJYb1VOaHh2NXJDTjVUaEJhSEtWY0p2UVIwQVE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.2.25/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlkc0VKcEpQVmw2U2ZidXhrd0dvOVNGMjBTWVd6UWJiNUo5SFVubFJZQ0hSU0I1RlJCYkxqOVhTYzJQL3hMaUhJYzZQY2FnaTJxYVhhUW80SzhmaEFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTUyNzU1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKZFZMOStXTzdHWWlKbkRDUlo2TzBmcUJPdWZZZEZxRDJnUWpPdlpqMGxVZ1Z5TkZZN2FaOHFWTWRlTkd0Ujd5SEhCandhSTFuTjVjL21BTnpDZ2xOQlE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.0/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 244ce6e65726a2649a1daffeed870c47f77dda3e Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 10 Feb 2024 16:04:50 +0530 Subject: [PATCH 308/864] feat: disbale tauri update dialod in favor of custom updater --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 51cbf010..2cfa58ad 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -383,7 +383,7 @@ "endpoints": [ "https://updates.phcode.io/tauri/update-latest-experimental-build.json" ], - "dialog": true, + "dialog": false, "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDY2QTY2RjMxQUIzQkU0RDQKUldUVTVEdXJNVyttWmc2ODNSODlVcmZhS0dFRW1mYnBkaytvTDcrSDJXSlhYOHVrUWRyaXhHRjcK" }, "windows": [ From 63d2d15381d86cb588b4a091fbab77bf2b404812 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 10 Feb 2024 10:56:08 +0000 Subject: [PATCH 309/864] ci: update phcode version to 3.3.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index c6a0dca1..f568b0d7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.0", + "version": "3.3.1", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "5f5485d2d7f7e9e2aedc94e031632bcc56f15dc5" + "commit": "3a10aeac4b23b056336974dd19c4530d8ed90239" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 44e23d27..433a971f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.0" +version = "3.3.1" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2cfa58ad..c5ea32ba 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.0" + "version": "3.3.1" }, "tauri": { "allowlist": { From 8350f9b2f8d212b729c34ff1e99d7bd7c3d4a028 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 10 Feb 2024 14:18:49 +0000 Subject: [PATCH 310/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index ad161096..c1514be7 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.2.3", - "notes": "", - "pub_date": "2023-07-28T17:25:10.800Z", + "version": "3.3.0", + "notes": "test updates", + "pub_date": "2024-02-10T11:27:52.857Z", "platforms": { - "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnI3Z1dYREV4Yi9NNGpRVGdKTVdERXpwSlJCaEtOYUY2NSszRCszQUFMemVVVlJUZlNDUVRRMndlUm9FWE1td2xsMHBuQ0pUODdPWGo0UHBLUVlVNWdJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTY0Njg1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cko1WU5NbXA2M0Y0cCtNZmpwT05ZQjFNNmJFUTB0eUpoeGdhekIvN05Tb29TTDRGZjBDNldOWkJaMVBhNFNOaDJBcHBBOFZtalpHV0JvZktOOUMyQUJnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.3/Phoenix.Code.Experimental.Build_x64.app.tar.gz" - }, "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNjaTdSb1pOeXBNUnVEcFpydkJFRXJJbTVCQjlYYk1pUFd1dnl6N0d4cEdaaU1xT2tUencybytHa2hwTWlBdDJ0VC9TeFpIZFFIWWl6clFBSnRJRGc0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTY0NzA5CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjIuM19hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKblN1bHlSQkd1OHgwOHZEOStxOVVZMUQzU1ZXSVB4ZlJWaTZFbzVaR3k2c1Q1bDJwRnk1WC93cGw3ZFc3Tm00WUxsa3pUTG5LNldwYnVyaUVtdlkxRFE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.3/phoenix-code-experimental-build_3.2.3_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm05cTFWTWtBbk5zZFE4Mi85eTZzK2xOTW5DNW1TNW1vUmR2WmlWL2szcDRwYlhJK0o1RDFOUGYyQWFKd2t4QnBNajZsVEJEakw2U1RhVUsyY1BhUVE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzMTA1CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuMF9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKWjRYcEZQZGZWUW5wUTIrclprdDZ3VklWamFydU1lWHlNTmp2b2t5SGhQKytVZDV0eXpnNWZncWd2cS9QbXFXY1VmTkVpTWc0VVE4NExpU1MzVFBOREE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.0/phoenix-code-experimental-build_3.3.0_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmppRXlabWh5TkZVR29xa2p5c3hFYmxTclRmYXZGRFFicmdmaEprNE5Fem1pczgwVkx6aEVhL3dCWGQ1RTV1cDBtY0NFdlFWRStvZW5UOXJDVVhpYncwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTY0NzY0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjIuM194NjQtc2V0dXAubnNpcy56aXAKNGNjckI4TWtJM3NKV2YxMzdoaURwSzMrQ20xblVxZ2ZjMitCdzR2blJMREJ3ai94WkFaM3ZJNzNJcjVMM1dXWGV3VnViaEVWRForRGxYK3Mrb0Z3Q0E9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.3/Phoenix.Code.Experimental.Build_3.2.3_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm95VlRFRk9GM29BUkt6QzUxa3pmNEovVzE2NDhmanJ1S284OURSekRWbFRnQzQyaVJtY1BkSFNMWVZYbG5HeUhmMTRFN1NDcmlLSHZPZzhIYk1teWdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzMjA2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuMF94NjQtc2V0dXAubnNpcy56aXAKV1R5cFA1em1tSTcvWTZvbkcyNC9tUFZhS1FCN1o0OXA1U3ZWcWtoRWVwb2hhTVAxbzJJNGhjZzRaejIxZk9GMHpneEtWNE5obm9HVERhdmxOQjZpRHc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.0/Phoenix.Code.Experimental.Build_3.3.0_x64-setup.nsis.zip" + }, + "darwin-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlwbEc3a2laMUVWQlNzNTZvMDdWR0o5ZFdHMmlKbTRPUStyMHVKQ21HcWUreTNGZ1AvdHF1WFpmQWtiUlo4SHlnSE80UmtlK2ZZMDRpakRlRFNjdXc4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzODI3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnBjYXRQQ0hmbGJaVHNEUmdhdmY5UDV3Z0kyU3lSSUZRT1B0bldJOHRWSjBKNkliQ2QrbFJWTmRiNm9Yck80UDFxcFd0VlFSUUx0R1I2Q01ybm84dEJnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.0/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9uU3pxVEZsU3puWEJDMGphL1ZQQ3duVnEwdXFLcHZNVmE1YW5nVjlna1I5ays5M1VBdENIVWUreUZOdHFrRVBEclhYcXFzaS9YZXhBN0hsbGdKZkFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNjkwNTY1MTA1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CndSMnhwY1pNc09NdzBnRkFhRlNBRFRRcmV2bHRNVFNCeGVjbWRvZGpSbG9qRGw1K2lVODZoRElpa2JNdmp4MUVFUTR0Q3psQkw4NXhzTEtBNjFCaUJBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.2.3/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZ6WUVXTmlvY3JTVmk3c2Y1aWFDMnMvZExweStIZzZCRnlWL2ZjdFJtWDk2V0svR0NKSVZmd1FWOFdIaG9tV2xjUkFQM3NqY2diZTBnOWozL3hNM2cwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTY0NDY4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnZqczdlRlJmT25lckEzMHkxMXR5M1B5OVlLTTgyUUIyeThYUUJtRVE5L3ZjTndkMjZ1NXBwN2wvQnFNV1RRa1BtbjVRNFR3Z294cVVCTlBUTW0zNkJRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.0/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 8a11f124c2db1bd2a279706833fae82c4b01b0ac Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 10 Feb 2024 14:20:57 +0000 Subject: [PATCH 311/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index c1514be7..30c3217e 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.3.0", + "version": "3.3.1", "notes": "test updates", - "pub_date": "2024-02-10T11:27:52.857Z", + "pub_date": "2024-02-10T11:39:07.257Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm05cTFWTWtBbk5zZFE4Mi85eTZzK2xOTW5DNW1TNW1vUmR2WmlWL2szcDRwYlhJK0o1RDFOUGYyQWFKd2t4QnBNajZsVEJEakw2U1RhVUsyY1BhUVE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzMTA1CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuMF9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKWjRYcEZQZGZWUW5wUTIrclprdDZ3VklWamFydU1lWHlNTmp2b2t5SGhQKytVZDV0eXpnNWZncWd2cS9QbXFXY1VmTkVpTWc0VVE4NExpU1MzVFBOREE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.0/phoenix-code-experimental-build_3.3.0_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtaS0FQTXNTMi9sa1l3VjdyUFkzTzFSbWxNN25YeXhkSUVGcnBLbXlncVFxejBPR0JiQy9Yem5Gbm9tNDVrYlcxS1FJQ09PZUVGQkZtVlhMMGR6bkF3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzMzk5CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuMV9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKdWVSSThjMU81T1pCMHRHaDNzYkF3eVRsZFpyamhTTitZejdTajVRajdqMXJ3NW0vUmluWVgxMFpjaDBtNXMycTdBcjAySjRPMkZlbDhzZllRQmZxQUE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.1/phoenix-code-experimental-build_3.3.1_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm95VlRFRk9GM29BUkt6QzUxa3pmNEovVzE2NDhmanJ1S284OURSekRWbFRnQzQyaVJtY1BkSFNMWVZYbG5HeUhmMTRFN1NDcmlLSHZPZzhIYk1teWdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzMjA2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuMF94NjQtc2V0dXAubnNpcy56aXAKV1R5cFA1em1tSTcvWTZvbkcyNC9tUFZhS1FCN1o0OXA1U3ZWcWtoRWVwb2hhTVAxbzJJNGhjZzRaejIxZk9GMHpneEtWNE5obm9HVERhdmxOQjZpRHc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.0/Phoenix.Code.Experimental.Build_3.3.0_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtsZ1RoeDdkTyttbTNrbmd4VzU1ZjJPNjNmMFVneWhGWC9UOFU5cWtIS1RMM0o2OVFWNmprQjQyR2FRYTB0OUd4OXRKZ3RPcDM5VXdtQjNDSXNNVUFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzNTAxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuMV94NjQtc2V0dXAubnNpcy56aXAKUlQ4bXpPeEgvczdjRXB4WTg1ZTBPWTh2ZnRLa01nYzBJNDZCOVFxYXo1NEs5UWZiM1ZCYllJSFAzbVlGZkFSRHFXZ0s1TVRMaFlWSVJZeTJTd1R6RHc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.1/Phoenix.Code.Experimental.Build_3.3.1_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlwbEc3a2laMUVWQlNzNTZvMDdWR0o5ZFdHMmlKbTRPUStyMHVKQ21HcWUreTNGZ1AvdHF1WFpmQWtiUlo4SHlnSE80UmtlK2ZZMDRpakRlRFNjdXc4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzODI3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnBjYXRQQ0hmbGJaVHNEUmdhdmY5UDV3Z0kyU3lSSUZRT1B0bldJOHRWSjBKNkliQ2QrbFJWTmRiNm9Yck80UDFxcFd0VlFSUUx0R1I2Q01ybm84dEJnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.0/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNmTld4RTFmRTIxVDZlMnR2d2JZYXdZd0RzSmtNcEtsZzhKbml4akxlY2RBbHVnY3dEbDhDcXZ5UXVORm1vSGQ3dTFHem5wWElKc0lnaC9jQVUyUndJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTY0MzA4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmIrcnJoL2UrcEZYS3RjeXFkR3JsMTUyS1JubEtkVHkvK00yNmxmaWJMNGtyZjNuYkRReFB5Y0hiVUZnL3RndkJVOXllZTZYaDV6WGJtb01Scy9LSEJ3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZ6WUVXTmlvY3JTVmk3c2Y1aWFDMnMvZExweStIZzZCRnlWL2ZjdFJtWDk2V0svR0NKSVZmd1FWOFdIaG9tV2xjUkFQM3NqY2diZTBnOWozL3hNM2cwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTY0NDY4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnZqczdlRlJmT25lckEzMHkxMXR5M1B5OVlLTTgyUUIyeThYUUJtRVE5L3ZjTndkMjZ1NXBwN2wvQnFNV1RRa1BtbjVRNFR3Z294cVVCTlBUTW0zNkJRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.0/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5rWmw2MWJjemFuenkrcFNoNXFxZUlablhxb3dPODVPWlhiUGZtSk5iaVN2V1VIYmNtTDZlTGpnN05Dd2hLczN5elRnRFJ3Q3dlcmV4SDN1T0crS2dBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTY1MTQyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClhGMGNqVnVmSXdqYWJHVXIwK2pqVlNMSEppRkRYK1d4RVlTTzhWVkZjNFpiT1ZQamhSTk5UWmZ1aFpuQXhRMkZjNVl1bytwanhTc3B6SnNLTUY5eEF3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 91a0dc9c86226911e95906d6f1c2d8abd91b8385 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 10 Feb 2024 20:40:21 +0530 Subject: [PATCH 312/864] chore:pointing to prod build in linux --- docs/linux/installer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 8d3f3731..ef3934ed 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -5,7 +5,7 @@ APPIMAGE_DIR=$HOME/.local/bin DESKTOP_DIR=$HOME/.local/share/applications NEW_APPIMAGE=phcode ICON=phoenix_icon.png -GITHUB_REPO="charlypa/phoenix-desktop" +GITHUB_REPO="phcode-dev/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" From cd2409f6aa47bf8eba44848261a8213f5037c27a Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 10 Feb 2024 21:26:54 +0530 Subject: [PATCH 313/864] fix: open in default browser with external crate --- src-tauri/Cargo.lock | 47 +++++++++++++++++++++++++++++++++++++++++-- src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 14 ++++++++++++- 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 8675ee01..60dd4ae3 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1642,6 +1642,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "html5ever" version = "0.25.2" @@ -1946,6 +1955,22 @@ dependencies = [ "walkdir", ] +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "jni-sys" version = "0.3.0" @@ -2742,7 +2767,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.2.24" +version = "3.3.1" dependencies = [ "clipboard-files", "fix-path-env", @@ -2760,6 +2785,7 @@ dependencies = [ "tauri-plugin-fs-extra", "tauri-plugin-single-instance", "tauri-plugin-window-state", + "webbrowser", "webkit2gtk", "winapi", ] @@ -3734,7 +3760,7 @@ dependencies = [ "gtk", "image", "instant", - "jni", + "jni 0.20.0", "lazy_static", "libc", "log", @@ -4655,6 +4681,23 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b2391658b02c27719fc5a0a73d6e696285138e8b12fba9d4baa70451023c71" +dependencies = [ + "core-foundation", + "home", + "jni 0.21.1", + "log", + "ndk-context", + "objc", + "raw-window-handle", + "url", + "web-sys", +] + [[package]] name = "webkit2gtk" version = "0.18.2" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 433a971f..6a8a36ea 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,6 +19,7 @@ once_cell = "1.19.0" percent-encoding = "2.3" regex = "1.10.3" clipboard-files = "0.1.1" +webbrowser = "0.8.12" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.4", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1420809c..e992e1c7 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,6 +4,8 @@ windows_subsystem = "windows" )] use std::env; +use webbrowser; + use tauri::{Manager}; use std::path::PathBuf; @@ -179,6 +181,16 @@ fn zoom_window(window: tauri::Window, scale_factor: f64) { }); } +#[tauri::command] +fn open_url_in_browser(url: String) -> Result<(), String> { + // Attempt to open the URL in the default web browser + if webbrowser::open(&url).is_ok() { + Ok(()) + } else { + Err("Failed to open URL in the browser".into()) + } +} + fn process_window_event(event: &GlobalWindowEvent) { if let tauri::WindowEvent::CloseRequested { .. } = event.event() { // this does nothing and is here if in future you need to persist something on window close. @@ -291,7 +303,7 @@ fn main() { .invoke_handler(tauri::generate_handler![ get_mac_deep_link_requests, toggle_devtools, console_log, console_error, _get_commandline_args, get_current_working_dir, - _get_window_labels, + _get_window_labels, open_url_in_browser, _get_windows_drives, _rename_path, show_in_folder, zoom_window, _get_clipboard_files]) .setup(|app| { init::init_app(app); From 1c077055d1b20c1e5ec2f5ac746efd911a88bc55 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 10 Feb 2024 17:18:13 +0000 Subject: [PATCH 314/864] ci: update phcode version to 3.3.2 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index f568b0d7..2badfb6b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.1", + "version": "3.3.2", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "3a10aeac4b23b056336974dd19c4530d8ed90239" + "commit": "414462ee753b53e59c835cc75bb7481693d6c54e" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6a8a36ea..c59912a5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.1" +version = "3.3.2" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c5ea32ba..f9a22e24 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.1" + "version": "3.3.2" }, "tauri": { "allowlist": { From 23f5e4cfe62873fd3b3880954098294fc0bb827f Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 11 Feb 2024 00:01:09 +0530 Subject: [PATCH 315/864] fix: linux open url with firefox usind xdmg --- src-tauri/Cargo.lock | 2 +- src-tauri/src/main.rs | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 60dd4ae3..59c1eb38 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2767,7 +2767,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.3.1" +version = "3.3.2" dependencies = [ "clipboard-files", "fix-path-env", diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index e992e1c7..c438d046 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,6 +4,7 @@ windows_subsystem = "windows" )] use std::env; +#[cfg(not(target_os = "linux"))] use webbrowser; use tauri::{Manager}; @@ -183,12 +184,23 @@ fn zoom_window(window: tauri::Window, scale_factor: f64) { #[tauri::command] fn open_url_in_browser(url: String) -> Result<(), String> { - // Attempt to open the URL in the default web browser - if webbrowser::open(&url).is_ok() { - Ok(()) - } else { - Err("Failed to open URL in the browser".into()) + #[cfg(target_os = "linux")] + { + // Use xdg-open for Linux + Command::new("xdg-open") + .arg(&url) + .spawn() + .map_err(|err| format!("Failed to open URL on Linux: {}", err))?; } + + #[cfg(any(target_os = "windows", target_os = "macos"))] + { + // Use the webbrowser crate for Windows and Mac + webbrowser::open(&url) + .map_err(|err| format!("Failed to open URL in the browser: {}", err))?; + } + + Ok(()) } fn process_window_event(event: &GlobalWindowEvent) { From 82f177e5a79fbd04d546b547d19e57d576324299 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 11 Feb 2024 00:44:13 +0530 Subject: [PATCH 316/864] fix: maybe cannot open path of the current working directory: Permission denied --- src-tauri/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c438d046..1edc932b 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -189,6 +189,7 @@ fn open_url_in_browser(url: String) -> Result<(), String> { // Use xdg-open for Linux Command::new("xdg-open") .arg(&url) + .current_dir("/tmp") .spawn() .map_err(|err| format!("Failed to open URL on Linux: {}", err))?; } From 62eed8efa930fc0b0cc1bf8917184265a8d4e57f Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 11 Feb 2024 12:20:18 +0530 Subject: [PATCH 317/864] build: releaseDistBundle command to build bundles --- README.md | 27 +++++++++++++--- package.json | 6 ++-- src-build/createDistBundleReleaseConfig.js | 36 ++++++++++++++++++++++ src-build/createDistReleaseConfig.js | 2 +- src-build/createSrcReleaseConfig.js | 2 +- src-tauri/Cargo.lock | 21 ------------- src-tauri/Cargo.toml | 2 +- 7 files changed, 65 insertions(+), 31 deletions(-) create mode 100644 src-build/createDistBundleReleaseConfig.js diff --git a/README.md b/README.md index 823b313f..5630cb3f 100644 --- a/README.md +++ b/README.md @@ -70,8 +70,8 @@ If you want to generate the release builds locally directly while you are editin ```bash cd phoenix-desktop # To generate debug builds: -npm run releaseSrcDebug -# OR to generate release builds, just run `npm run releaseSrc` +npm run releaseSrc +# OR to generate debug builds, just run `npm run releaseSrcDebug` ``` This is the easiest way to quickly debug issues directly from the phoenix source folder. @@ -86,12 +86,29 @@ npm run build npm run release:prod # Other release options are `npm run release:dev` and `npm run release:staging` -# Now generate the tauri debug builds: +# Now generate the tauri release builds: cd ../phoenix-desktop -npm run releaseDistDebug -# OR to generate release builds, just run `npm run releaseDist` +npm run releaseDist +# OR to debug, just run `npm run releaseDistDebug` ``` +#### Generating installers/AppImage and DMGs locally from `phoenix/dist` folder +To generate the installers, use the commands +```bash +# You should first build the appropriate release build in `phoenix`. +cd phoenix +npm install +npm run build +npm run release:prod +# Other release options are `npm run release:dev` and `npm run release:staging` + +# Now generate the bundles +cd ../phoenix-desktop +npm run releaseDistBundle +# will generate appimages/DMGs or nsix windows installers in target/release/bundle +``` + + ## Building release binaries and installers in GitHub actions The npm commands that begin with `_ci-*` are exclusively designed to execute in a GitHub Actions environment. These commands are not typically executed on your local machine unless you're actively working on the GitHub diff --git a/package.json b/package.json index 2badfb6b..06e2569b 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,15 @@ "tauriBuildDemoApp": "node src-build/createDemoReleaseConfig.js && tauri build --config ./src-tauri/tauri-local.conf.json", "_createSrcReleaseConfig": "node src-build/createSrcReleaseConfig.js", "_createDistReleaseConfig": "node src-build/createDistReleaseConfig.js", + "_createDistBundleReleaseConfig": "node src-build/createDistBundleReleaseConfig.js", "_createDistTestReleaseConfig": "node src-build/createDistTestReleaseConfig.js", "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", "releaseSrc": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseSrcDebug": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseSrcDebug": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug --verbose", "releaseDist": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseDistDebug": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseDistBundle": "npm run _make_src-node && npm run _createDistBundleReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --verbose", + "releaseDistDebug": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug --verbose", "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "_src-node_npm_install": "cd src-tauri/src-node && npm ci --production && cd ../../ && npm run _src-node_remove_unsupported_bin", diff --git a/src-build/createDistBundleReleaseConfig.js b/src-build/createDistBundleReleaseConfig.js new file mode 100644 index 00000000..c88572b3 --- /dev/null +++ b/src-build/createDistBundleReleaseConfig.js @@ -0,0 +1,36 @@ +import {fileURLToPath} from "url"; +import {dirname} from "path"; +import fs from 'fs'; +import chalk from 'chalk'; + +import {getPlatformDetails, patchTauriConfigWithMetricsHTML} from "./utils.js"; +import os from "os"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +async function createDistReleaseConfig() { + const platform = getPlatformDetails().platform; + const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` + : `${__dirname}/../src-tauri/tauri.conf.json`; + const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` + : `${__dirname}/../src-tauri/tauri-local.conf.json`; + console.log("Reading Tauri config file: ", tauriConfigPath); + let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + console.log(chalk.cyan("\n!Updates and signing is disabled while creating msi, appimage and dmg installers. If you want to sign, use tauri build commands directly.\n")); + configJson.tauri.bundle.active = true; + configJson.tauri.updater.active = false; + configJson.build.distDir = '../../phoenix/dist/'; + const phoenixVersion = configJson.package.version; + if(os.platform() === 'win32'){ + configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; + } else { + configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; + } + patchTauriConfigWithMetricsHTML(configJson); + console.log("Window Boot url is: ", configJson.tauri.windows[0].url); + console.log("Writing new local config json ", tauriLocalConfigPath); + fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); +} + +await createDistReleaseConfig(); diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index c22c278d..5942311b 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -17,7 +17,7 @@ async function createDistReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading Tauri config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); + console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run releaseDistBundle\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/dist/'; const phoenixVersion = configJson.package.version; diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index 97f4b12d..582fb3da 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -17,7 +17,7 @@ async function createSrcReleaseConfig() { : `${__dirname}/../src-tauri/tauri-local.conf.json`; console.log("Reading config file: ", tauriConfigPath); let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); + console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run releaseDistBundle\n")); configJson.tauri.bundle.active = false; configJson.build.distDir = '../../phoenix/src/' const phoenixVersion = configJson.package.version; diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 59c1eb38..9b060a9e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2205,12 +2205,6 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" -[[package]] -name = "minisign-verify" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -3817,7 +3811,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd27c04b9543776a972c86ccf70660b517ecabbeced9fb58d8b961a13ad129af" dependencies = [ "anyhow", - "base64 0.21.5", "bytes", "clap", "cocoa", @@ -3832,7 +3825,6 @@ dependencies = [ "heck 0.4.1", "http", "ignore", - "minisign-verify", "notify-rust", "objc", "once_cell", @@ -3860,14 +3852,12 @@ dependencies = [ "tauri-utils", "tempfile", "thiserror", - "time", "tokio", "url", "uuid", "webkit2gtk", "webview2-com", "windows 0.39.0", - "zip", ] [[package]] @@ -5393,17 +5383,6 @@ dependencies = [ "zvariant", ] -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "byteorder", - "crc32fast", - "crossbeam-utils", -] - [[package]] name = "zvariant" version = "3.15.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c59912a5..d7c619d8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -21,7 +21,7 @@ regex = "1.10.3" clipboard-files = "0.1.1" webbrowser = "0.8.12" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.5.4", features = [ "cli", "api-all", "updater", "devtools", "linux-protocol-headers"] } +tauri = { version = "1.5.4", features = [ "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From 4b0730c59101b1aa81827741e849a4a54dd849cf Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 11 Feb 2024 12:23:59 +0530 Subject: [PATCH 318/864] build: include updater in cargo --- src-tauri/Cargo.lock | 21 +++++++++++++++++++++ src-tauri/Cargo.toml | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9b060a9e..59c1eb38 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2205,6 +2205,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minisign-verify" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -3811,6 +3817,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd27c04b9543776a972c86ccf70660b517ecabbeced9fb58d8b961a13ad129af" dependencies = [ "anyhow", + "base64 0.21.5", "bytes", "clap", "cocoa", @@ -3825,6 +3832,7 @@ dependencies = [ "heck 0.4.1", "http", "ignore", + "minisign-verify", "notify-rust", "objc", "once_cell", @@ -3852,12 +3860,14 @@ dependencies = [ "tauri-utils", "tempfile", "thiserror", + "time", "tokio", "url", "uuid", "webkit2gtk", "webview2-com", "windows 0.39.0", + "zip", ] [[package]] @@ -5383,6 +5393,17 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zip" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" +dependencies = [ + "byteorder", + "crc32fast", + "crossbeam-utils", +] + [[package]] name = "zvariant" version = "3.15.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d7c619d8..f5dcb5f1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -21,7 +21,7 @@ regex = "1.10.3" clipboard-files = "0.1.1" webbrowser = "0.8.12" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.5.4", features = [ "cli", "api-all", "devtools", "linux-protocol-headers"] } +tauri = { version = "1.5.4", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From 5ddd3aebf2ca42615a3628508146ac22fa47afe7 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sun, 11 Feb 2024 16:08:00 +0000 Subject: [PATCH 319/864] ci: update phcode version to 3.3.3 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 06e2569b..056fc6ec 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.2", + "version": "3.3.3", "type": "module", "scripts": { "tauri": "tauri", @@ -52,6 +52,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "414462ee753b53e59c835cc75bb7481693d6c54e" + "commit": "5821ec685394a1f050af4679b597e4eab532b34c" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f5dcb5f1..8ed13967 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.2" +version = "3.3.3" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f9a22e24..195b996b 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.2" + "version": "3.3.3" }, "tauri": { "allowlist": { From ceb980891c649e137e55689866ffdf3e39cb5093 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 11 Feb 2024 16:49:48 +0000 Subject: [PATCH 320/864] ci: tauri release update notification json --- docs/tauri/update-latest-stable-prod.json | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index a4d718dd..24bfdc4f 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,23 +1,19 @@ { - "version": "3.3.0", - "notes": "Testing update push", - "pub_date": "2024-02-10T08:12:41.560Z", + "version": "3.3.3", + "notes": "test release", + "pub_date": "2024-02-11T16:44:35.859Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1aVVpWZVJ0RFAyN1BZbmRYKzhGUmM3bVZRZzJ6SnJycnlZc3VWUmlvWW1vR20vQzJOUWs1UnN6QS9MM2xrS2kzREYyczZEMERjSWRwZy9GdXB5ZXc4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTUxMDQwCWZpbGU6cGhvZW5peC1jb2RlXzMuMy4wX2FtZDY0LkFwcEltYWdlLnRhci5nego2b2wzeFdxZFFwOHFIY2VjZnZwTjBKSTQxM2FmclNNckowN1hsRnFQUjl1ZWovemNzbGRvVnk2WUFjV29vVmJKaHZjT2JKcXRvYkxoT3MxNTcwYnNEZz09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.0/phoenix-code_3.3.0_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5CVUsvT0FTdzdaaGpMc1VybXdsQldEYmhraHVRTjhpa1RsTEV2Y25tMDFBYnlxUW1LVHRHWDRZMkI5UUwxc04vclFJVEtIT3M1bVhVQjMrSUxEZlFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5NDUwCWZpbGU6cGhvZW5peC1jb2RlXzMuMy4zX2FtZDY0LkFwcEltYWdlLnRhci5negp5OGRiQzU1eUgwMk53RjJkWVk1L1lUNGtUVXRtV3FsOExKUlZDQVdHYWtBTlRpRGZsb0hGN3hlS3J6bTVESmFmR1ZLdmhmL0xxclVuWlB4RUpEd29DUT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/phoenix-code_3.3.3_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVaVmNvbFBCdUh6QjhrYzFwNm5aYmRWSEdaNXRta1pWK1E2QWs1Qm9zNGtrVHFnSDVGSlNtb3lYV2ZwbEVOd1Z1TW5jWHhmejhWc1hVOWR0cmhyc1EwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTUxMjIxCWZpbGU6UGhvZW5peCBDb2RlXzMuMy4wX3g2NC1zZXR1cC5uc2lzLnppcApUOG16OVpWbjdkMys1bXhhTFpIOW10UG1LYWNFUVBkd0lpL2VES2EvdWViYTNhZHN4cTQzelhoSmxxTjFESnFOWGhXY3lYeFErUzNLaEdoU2JLWHFDdz09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.0/Phoenix.Code_3.3.0_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWml3SXNZeTNDd0gyR2ttZjNaK3NOL0NXckJ5YkpBYVRRYmIyVjd6V2JmZERaVU9lUjdPQmUvV2NZKzFhejRlK1JUT3pyWms5ZlhkcGIrMGRuNmRkQVFBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5NTMyCWZpbGU6UGhvZW5peCBDb2RlXzMuMy4zX3g2NC1zZXR1cC5uc2lzLnppcApWM1FsUTNxMXcxdWpDeForendMZS9YRHNyY1lCUHN4ZXBqc3BmMVRJanpUT0hLRHlqTjBJZExJMWwyb2xYaFZoeDJZODVwaVZaTVV4VVovVzF5NmpEQT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNGWk5ManFFZ3JkTXVVTk1ramlUOWhWYVI5SWRZUWpTOFhvSkUvd2tMNkFDSVg1LzhjVE0zSW5WejQzUk9pYU5JSmViVDBrQVErQ0hKVlptS3R1akFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTUxOTI5CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdHJEQUw1WTlaTHgwc1E4WUFlQXJ4aWVPZW50RVhLVkUwM096dnNrbms4WGZma2tDb0ZIY1hLMjArekhoQ3pKTUlVekFNUncwSHFIOExTQ2hPbERYQ2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.0/Phoenix.Code_x64.app.tar.gz" - }, - "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlkc0VKcEpQVmw2U2ZidXhrd0dvOVNGMjBTWVd6UWJiNUo5SFVubFJZQ0hSU0I1RlJCYkxqOVhTYzJQL3hMaUhJYzZQY2FnaTJxYVhhUW80SzhmaEFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTUyNzU1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKZFZMOStXTzdHWWlKbkRDUlo2TzBmcUJPdWZZZEZxRDJnUWpPdlpqMGxVZ1Z5TkZZN2FaOHFWTWRlTkd0Ujd5SEhCandhSTFuTjVjL21BTnpDZ2xOQlE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.0/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnMwT04xZ1lRNzE5SStpNUVNdTY4N3h4cmRvTWFEcDRFRkEyTjVoa0lSSG1NaDRsQXBGdEVtcEx2eXlHQUFaN0dXejRHZ3NINGNqLzl2S2V4KzN6RXdFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5ODY2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKL1pudFI0NWlBcUpkQU9JS1g4RDd4eE9EeWZsdG5PSWVvRDFzTDVrYmk5b2kwaTNNbzYrU1IzdGg2elUveS9OTkU1cHQzUEdLMllGM0U4bExvTi9lRGc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_x64.app.tar.gz" } } } \ No newline at end of file From 45b67996eca64973d6d425b8b2ac47eca4bf4a43 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 12 Feb 2024 12:58:12 +0530 Subject: [PATCH 321/864] fix: lowe updates releases should not trigger update notification --- .github/workflows/updateNotification.js | 45 +++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js index a2dc0952..a8db9a54 100644 --- a/.github/workflows/updateNotification.js +++ b/.github/workflows/updateNotification.js @@ -80,6 +80,41 @@ function _extractSmallReleaseNotes(releaseNotes, releaseTitle) { return releaseTitle; } +function getCurrentVersion(latestJsonPath) { + try{ + return JSON.parse(fs.readFileSync(latestJsonPath, 'utf8')).version || '0.0.0'; + } catch (e) { + console.error("Error getting current version from path: ", latestJsonPath, e); + return '0.0.0'; + } +} + +/** + * Checks if new version is higher or equal than the current version + * @param currentVersion + * @param newVersion + * @return {boolean} + */ +function isHigherOrEqualVersion(currentVersion, newVersion) { + if(currentVersion === newVersion){ + return true; + } + const currentParts = currentVersion.split('.').map(Number); + const newParts = newVersion.split('.').map(Number); + + for (let i = 0; i < currentParts.length; i++) { + if (newParts[i] > currentParts[i]) { + return true; // New version is higher + } else if (newParts[i] < currentParts[i]) { + return false; // New version is not higher + } + // If they are equal, move to the next part + } + + // If all parts are equal, the versions are the same, so return false + return false; +} + export default async function printStuff({github, context, githubWorkspaceRoot}) { console.log(github, context, "yo"); const fullRepoName = context.payload.repository.full_name; @@ -110,6 +145,12 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) const latestJSON = JSON.parse(await _getLatestJson(releaseAssets)); latestJSON.notes = _extractSmallReleaseNotes(releaseNotes, releaseTitle); const latestJsonPath = `${githubWorkspaceRoot}/docs/${_identifyUpdateJSONPath(releaseAssets)}`; - console.log("writing latest json to path: ", latestJsonPath, " contents: ", latestJSON) - fs.writeFileSync(latestJsonPath, JSON.stringify(latestJSON, null, 4)); + const currentVersion = getCurrentVersion(latestJsonPath); + const latestVersion = latestJSON.version; + if(isHigherOrEqualVersion(currentVersion, latestVersion)){ + console.log("writing latest json to path: ", latestJsonPath, " contents: ", latestJSON) + fs.writeFileSync(latestJsonPath, JSON.stringify(latestJSON, null, 4)); + } else { + console.warn("Current version: ", currentVersion, " is higher than the new release version ", latestVersion, " . Ignoring this release update!"); + } } \ No newline at end of file From 11251b24b674851c1a1f6c0ac362327a83d8f17e Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 12 Feb 2024 07:33:22 +0000 Subject: [PATCH 322/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 30c3217e..178966f5 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.3.1", - "notes": "test updates", - "pub_date": "2024-02-10T11:39:07.257Z", + "version": "3.3.3", + "notes": "test release", + "pub_date": "2024-02-11T16:49:29.809Z", "platforms": { - "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtaS0FQTXNTMi9sa1l3VjdyUFkzTzFSbWxNN25YeXhkSUVGcnBLbXlncVFxejBPR0JiQy9Yem5Gbm9tNDVrYlcxS1FJQ09PZUVGQkZtVlhMMGR6bkF3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzMzk5CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuMV9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKdWVSSThjMU81T1pCMHRHaDNzYkF3eVRsZFpyamhTTitZejdTajVRajdqMXJ3NW0vUmluWVgxMFpjaDBtNXMycTdBcjAySjRPMkZlbDhzZllRQmZxQUE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.1/phoenix-code-experimental-build_3.3.1_amd64.AppImage.tar.gz" - }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtsZ1RoeDdkTyttbTNrbmd4VzU1ZjJPNjNmMFVneWhGWC9UOFU5cWtIS1RMM0o2OVFWNmprQjQyR2FRYTB0OUd4OXRKZ3RPcDM5VXdtQjNDSXNNVUFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTYzNTAxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuMV94NjQtc2V0dXAubnNpcy56aXAKUlQ4bXpPeEgvczdjRXB4WTg1ZTBPWTh2ZnRLa01nYzBJNDZCOVFxYXo1NEs5UWZiM1ZCYllJSFAzbVlGZkFSRHFXZ0s1TVRMaFlWSVJZeTJTd1R6RHc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.1/Phoenix.Code.Experimental.Build_3.3.1_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmk5amY0UEh6TGdQdFo5MDl2TFNoVlhETlU5U1VGa0pNdVBrVDY0dFhWU0Vvbit1Q2JnekFGeWxDL3J4ZnVkMUovdThPa0s3ajZGOExneWlVY1B4bUFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5MzEyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuM194NjQtc2V0dXAubnNpcy56aXAKK0FBZkc1K0pMZUF0ejIzTEpXNkFKQjdJNGZiUURnUWRtWXdXR0crTEVqVDdwZVMrbjdLQ2JVVmRLYTRwczEvd0wyekVZVG5vU21ZaWo4dk5ZNTlmRHc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.3/Phoenix.Code.Experimental.Build_3.3.3_x64-setup.nsis.zip" + }, + "linux-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmcwOWpvSGk4K0svRzhXaXAzc2ZBcmZIQy9YRng4dEllNHJaOXYzRzdlaWdlRnplazd5aUhyTnZZcTlORzBXSTc5ajk0UGN6N3ZRczc1eXJZNzRhK2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5MzQ2CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuM19hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKVDFBZzFTL2ZNVHVzTTVJbi80a0NLeTV6bFA5NDZRUTA1aUR0Rll4YkFpaDVoWnh0YWt6aUtLTTc3NTVPVm83aGsreDBySFM1VDVxaVZaYzlzZFN5REE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.3/phoenix-code-experimental-build_3.3.3_amd64.AppImage.tar.gz" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNmTld4RTFmRTIxVDZlMnR2d2JZYXdZd0RzSmtNcEtsZzhKbml4akxlY2RBbHVnY3dEbDhDcXZ5UXVORm1vSGQ3dTFHem5wWElKc0lnaC9jQVUyUndJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTY0MzA4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmIrcnJoL2UrcEZYS3RjeXFkR3JsMTUyS1JubEtkVHkvK00yNmxmaWJMNGtyZjNuYkRReFB5Y0hiVUZnL3RndkJVOXllZTZYaDV6WGJtb01Scy9LSEJ3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9JL01UaTN3VDdSY1Q1ZGZVNG00YjRKWUoxZitITXROVUxTZGxoZnlwbXdNV0tBcEwvbUJUeURQTnBLbGJhdktUQXR0YlUydWd3UldoR3J3OXdrK0FrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5NjQzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnRxTFVuM1V0cnYxT0FHYnBwY0IzYTcvRWsxMjcwcTlyUlUvOUY5NDNEWWZhS3JadWM5MFd5Z1VXRWVJUjNybThnOUZ6a0YwQ3o2KzJ2NHhyNmVZRkRBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.3/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5rWmw2MWJjemFuenkrcFNoNXFxZUlablhxb3dPODVPWlhiUGZtSk5iaVN2V1VIYmNtTDZlTGpnN05Dd2hLczN5elRnRFJ3Q3dlcmV4SDN1T0crS2dBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NTY1MTQyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClhGMGNqVnVmSXdqYWJHVXIwK2pqVlNMSEppRkRYK1d4RVlTTzhWVkZjNFpiT1ZQamhSTk5UWmZ1aFpuQXhRMkZjNVl1bytwanhTc3B6SnNLTUY5eEF3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1MZksyditmcWR2TVNCbmVrQk9Hd2gxMHI0UDE4aHRtaVdJdytOVGlkb0N6dkFXcE1Rd0J5YnJ1NFJ1UzZwN3NDTFptTDJnQWJ6TUt5MG9NVlVTZHdnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjcwMTYwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Clc2bks5WTNMRVgvZkc1YWV5Tnc1UURHMlRLa3I5Zm11Y29TWXkyZ291RitGOTlrN3JTUjlCRW5vazZCRFBKaDJFc0t5K1UwSWwrMkIxbElqbzVnRkNnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.3/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 1098bfd389a6e327e264826bbcb65e9f62e9be54 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 12 Feb 2024 07:40:39 +0000 Subject: [PATCH 323/864] ci: tauri release update notification json --- docs/tauri/update-latest-stable-prod.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 24bfdc4f..d8756ab6 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,7 +1,7 @@ { "version": "3.3.3", - "notes": "test release", - "pub_date": "2024-02-11T16:44:35.859Z", + "notes": "Beta release 1", + "pub_date": "2024-02-11T16:53:25.316Z", "platforms": { "linux-x86_64": { "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5CVUsvT0FTdzdaaGpMc1VybXdsQldEYmhraHVRTjhpa1RsTEV2Y25tMDFBYnlxUW1LVHRHWDRZMkI5UUwxc04vclFJVEtIT3M1bVhVQjMrSUxEZlFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5NDUwCWZpbGU6cGhvZW5peC1jb2RlXzMuMy4zX2FtZDY0LkFwcEltYWdlLnRhci5negp5OGRiQzU1eUgwMk53RjJkWVk1L1lUNGtUVXRtV3FsOExKUlZDQVdHYWtBTlRpRGZsb0hGN3hlS3J6bTVESmFmR1ZLdmhmL0xxclVuWlB4RUpEd29DUT09Cg==", @@ -14,6 +14,10 @@ "darwin-x86_64": { "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnMwT04xZ1lRNzE5SStpNUVNdTY4N3h4cmRvTWFEcDRFRkEyTjVoa0lSSG1NaDRsQXBGdEVtcEx2eXlHQUFaN0dXejRHZ3NINGNqLzl2S2V4KzN6RXdFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5ODY2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKL1pudFI0NWlBcUpkQU9JS1g4RDd4eE9EeWZsdG5PSWVvRDFzTDVrYmk5b2kwaTNNbzYrU1IzdGg2elUveS9OTkU1cHQzUEdLMllGM0U4bExvTi9lRGc9PQo=", "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_x64.app.tar.gz" + }, + "darwin-aarch64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlZOXpJMDlscVdQS0s5VGhsRWV4YWZKTWdkQ3k0bmFPd2lvRDY5Z2hUZ0d4L25pMFExKzc1ZTZEdTZjWXNkUlcrcVdFY1hVcE1ieWZkNEx0dWd4SndvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjcwMzk1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKYkRPaFRGYTl5REg3V0puSVZjRkd3ZVdncG03ZjlUNkJjS1lzTjVnSXIwVG5veTIwMFRwUkhBalF0aFJub0ZvTzNVUGhHcUorRHBaUVpOVFBwZ2djQXc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 81eac3ece9e4a2c52abd3b8faf73950daf345350 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 12 Feb 2024 14:05:23 +0530 Subject: [PATCH 324/864] feat: intal support for deb --- src-tauri/tauri.conf.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 195b996b..dcafbe11 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -103,7 +103,10 @@ "category": "DeveloperTool", "copyright": "Copyright (c) 2022 - present Core.ai", "deb": { - "depends": [] + "depends": [ + "libwebkit2gtk-4.0-37", + "libgtk-3-0" + ] }, "appimage": { "bundleMediaFramework": true @@ -133,6 +136,7 @@ ], "shortDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", "targets": [ + "deb", "appimage", "nsis", "app", @@ -406,4 +410,4 @@ } ] } -} \ No newline at end of file +} From 93b5333ddbdc85a827f1f8ae8e71356fee2e456d Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 12 Feb 2024 14:06:41 +0530 Subject: [PATCH 325/864] fix: libfuse not installed in ubuntu 23.10 --- docs/linux/installer.sh | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index ef3934ed..0b3bff0b 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -8,8 +8,46 @@ ICON=phoenix_icon.png GITHUB_REPO="phcode-dev/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" +check_and_install_libfuse() { + # Identify the Linux distribution + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO=$ID + else + echo "Cannot identify the operating system." + exit 1 + fi + + echo "Checking for FUSE library..." + + if [ "$DISTRO" = "ubuntu" ]; then + # Check and install libfuse2 on Ubuntu + if ! dpkg -s libfuse2 &> /dev/null; then + echo "libfuse2 not found, installing..." + sudo apt-get update && sudo apt-get install -y libfuse2 || { echo "Failed to install libfuse2"; exit 1; } + else + echo "libfuse2 is already installed." + fi + elif [ "$DISTRO" = "fedora" ]; then + # Check and install fuse-libs on Fedora + if [ "$DISTRO" = "fedora" ]; then + # Check and install fuse-libs on Fedora + if ! rpm -q fuse-libs &> /dev/null; then + echo "fuse-libs not found, installing..." + sudo dnf install -y fuse-libs || { echo "Failed to install fuse-libs"; exit 1; } + else + echo "fuse-libs is already installed." + fi + fi + + else + echo "Unsupported distribution: $DISTRO" + exit 1 + fi +} install() { + check_and_install_libfuse # Fetch the latest release data from GitHub echo "Fetching latest release from $GITHUB_REPO..." wget -qO- $API_URL > latest_release.json || { echo "Failed to fetch latest release info"; exit 1; } From 9b90f330fb548e22b94bb26da71152735f51df27 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 12 Feb 2024 11:26:03 +0000 Subject: [PATCH 326/864] ci: update phcode version to 3.3.4 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 056fc6ec..f853f4eb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.3", + "version": "3.3.4", "type": "module", "scripts": { "tauri": "tauri", @@ -52,6 +52,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "5821ec685394a1f050af4679b597e4eab532b34c" + "commit": "3745c2a913e800c5626f9332b3c0c449cca20dfb" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8ed13967..1dda0685 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.3" +version = "3.3.4" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index dcafbe11..75b69617 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.3" + "version": "3.3.4" }, "tauri": { "allowlist": { @@ -104,8 +104,8 @@ "copyright": "Copyright (c) 2022 - present Core.ai", "deb": { "depends": [ - "libwebkit2gtk-4.0-37", - "libgtk-3-0" + "libwebkit2gtk-4.0-37", + "libgtk-3-0" ] }, "appimage": { @@ -410,4 +410,4 @@ } ] } -} +} \ No newline at end of file From b63624fc8d6f0bce3ebb8dcad872e5b5a45a6245 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 12 Feb 2024 19:40:27 +0530 Subject: [PATCH 327/864] chore: fixing mimie type for desktop --- src-tauri/src/bundle/linux/deb/main.desktop.download | 11 +++++++++++ src-tauri/tauri.conf.json | 5 ++--- 2 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 src-tauri/src/bundle/linux/deb/main.desktop.download diff --git a/src-tauri/src/bundle/linux/deb/main.desktop.download b/src-tauri/src/bundle/linux/deb/main.desktop.download new file mode 100644 index 00000000..b6d143c9 --- /dev/null +++ b/src-tauri/src/bundle/linux/deb/main.desktop.download @@ -0,0 +1,11 @@ +[Desktop Entry] +Categories={{categories}} +{{#if comment}} +Comment={{comment}} +{{/if}} +Exec={{exec}} +Icon={{icon}} +Name={{name}} +Terminal=false +Type=Application +MimeType=text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;inode/directory; diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 75b69617..111a3172 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -103,9 +103,8 @@ "category": "DeveloperTool", "copyright": "Copyright (c) 2022 - present Core.ai", "deb": { + "desktopTemplate" : "./src/bundle/linux/deb/main.desktop.download", "depends": [ - "libwebkit2gtk-4.0-37", - "libgtk-3-0" ] }, "appimage": { @@ -410,4 +409,4 @@ } ] } -} \ No newline at end of file +} From 502d2066ec5fc5410c44c12d25fb7b730807a8ed Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 13 Feb 2024 14:20:33 +0530 Subject: [PATCH 328/864] chore: change dev build machine to ubuntu-20.04 --- .github/workflows/tauri-build-dev.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index b0df61d5..7e7e7fef 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -8,7 +8,7 @@ jobs: create-release: permissions: contents: write - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 outputs: release_id: ${{ steps.create-release.outputs.result }} @@ -76,7 +76,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-latest, windows-latest ] + platform: [ macos-latest, ubuntu-20.04, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -99,7 +99,7 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-latest' + if: matrix.platform == 'ubuntu-20.04' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev @@ -260,7 +260,7 @@ jobs: permissions: contents: write timeout-minutes: 15 - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 needs: [ create-release, build-tauri ] steps: From d522b02ab7f28353917e6af06b441519dd2c95f1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Feb 2024 08:51:27 +0000 Subject: [PATCH 329/864] chore(deps): update dependency ubuntu to v22 --- .github/workflows/tauri-build-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 7e7e7fef..c473b149 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -8,7 +8,7 @@ jobs: create-release: permissions: contents: write - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 outputs: release_id: ${{ steps.create-release.outputs.result }} @@ -260,7 +260,7 @@ jobs: permissions: contents: write timeout-minutes: 15 - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: [ create-release, build-tauri ] steps: From dc6d30d6f6a6b6b246d663d80c5ad79b06e4279d Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 09:26:45 +0530 Subject: [PATCH 330/864] build: add --runVerify cli command to see if app load success --- src-tauri/Cargo.lock | 2 +- src-tauri/src/main.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 59c1eb38..458e2b3a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2767,7 +2767,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.3.2" +version = "3.3.4" dependencies = [ "clipboard-files", "fix-path-env", diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1edc932b..b9cf9303 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -245,6 +245,11 @@ fn get_mac_deep_link_requests() -> Vec { } fn main() { + let args: Vec = env::args().collect(); + if args.contains(&"--runVerify".to_string()) { + // Mainly used by linux installer to see if the app loaded successfully with all libs + std::process::exit(0); + } #[cfg(target_os = "macos")]{ tauri_plugin_deep_link::prepare("io.phcode"); From a0cc499803324f3b239e217a23649d04b463a654 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 14:26:26 +0530 Subject: [PATCH 331/864] build: add npm run _ci-disableBundleConfig to build bundle less exes --- package.json | 1 + src-build/ci-disableBundleConfig.js | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 src-build/ci-disableBundleConfig.js diff --git a/package.json b/package.json index f853f4eb..e77e683f 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "_createDistBundleReleaseConfig": "node src-build/createDistBundleReleaseConfig.js", "_createDistTestReleaseConfig": "node src-build/createDistTestReleaseConfig.js", "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", + "_ci-disableBundleConfig": "node src-build/ci-disableBundleConfig.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", "releaseSrc": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseSrcDebug": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug --verbose", diff --git a/src-build/ci-disableBundleConfig.js b/src-build/ci-disableBundleConfig.js new file mode 100644 index 00000000..dce1fe53 --- /dev/null +++ b/src-build/ci-disableBundleConfig.js @@ -0,0 +1,18 @@ +import {dirname, join} from "path"; +import fs from "fs"; +import {fileURLToPath} from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +async function ciCreateDistReleaseConfig() { + const tauriConfigPath = join(__dirname, '..', 'src-tauri', 'tauri.conf.json'); + + console.log("remove bundle config in tauri.conf.json", tauriConfigPath); + const configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + configJson.tauri.bundle.active = false; + configJson.tauri.updater.active = false; + console.log("Product name is: ", configJson.package.productName); + fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); +} + +await ciCreateDistReleaseConfig(); From 12a0d268136826426986cbdee79d84d08e07a892 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 14:33:53 +0530 Subject: [PATCH 332/864] ci: move to ubuntu 22.04 for appimage builds --- .github/workflows/tauri-build-dev.yml | 6 +++--- .github/workflows/tauri-build-prod.yml | 6 +++--- .github/workflows/tauri-build-staging.yml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index c473b149..833597b2 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -8,7 +8,7 @@ jobs: create-release: permissions: contents: write - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest outputs: release_id: ${{ steps.create-release.outputs.result }} @@ -76,7 +76,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-20.04, windows-latest ] + platform: [ macos-latest, ubuntu-22.04, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -99,7 +99,7 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-20.04' + if: matrix.platform == 'ubuntu-22.04' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 8bc43f50..7056c6d7 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -76,7 +76,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-latest, windows-latest ] + platform: [ macos-latest, ubuntu-22.04, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -99,7 +99,7 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-latest' + if: matrix.platform == 'ubuntu-22.04' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev @@ -260,7 +260,7 @@ jobs: publish-release: permissions: contents: write - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [ create-release, build-tauri ] steps: diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index e95275fe..9c74c282 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -76,7 +76,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-latest, windows-latest ] + platform: [ macos-latest, ubuntu-22.04, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -99,7 +99,7 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-latest' + if: matrix.platform == 'ubuntu-22.04' run: | sudo apt-get update sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev @@ -260,7 +260,7 @@ jobs: permissions: contents: write timeout-minutes: 15 - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [ create-release, build-tauri ] steps: From 95fb154966a61adce5228cf3e04e1cb18c74e337 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 15:29:04 +0530 Subject: [PATCH 333/864] ci: linux native builds --- .github/workflows/tauri-build-dev.yml | 53 ++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 833597b2..965e627e 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -256,12 +256,63 @@ jobs: args: --target aarch64-apple-darwin tagName: ${{ env.GIT_TAG_NAME }} + build-linux-bins: + needs: [ create-release ] + permissions: + contents: write + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + platform: [ ubuntu-20.04, ubuntu-22.04] + + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v4 + - name: get Git Tag + shell: bash + run: echo "GIT_TAG_NAME=dev-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: GLIBC version + run: | + ldd --version + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + - name: install dependencies (ubuntu only) + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev + sudo apt-get install -y libwebrtc-audio-processing-dev + sudo apt-get install -y libunwind-dev + sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio + - name: install frontend dependencies + run: | + npm ci + npm run _ci-release:dev + npm run _ci-disableBundleConfig + npm run tauri build + ls -alh ./src-tauri/target/release + mkdir ./src-tauri/target/release/binDist + cp ./src-tauri/target/release/phoenix-code-experimental-build ./src-tauri/target/release/binDist + cp ./src-tauri/target/release/phnode ./src-tauri/target/release/binDist + cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/binDist + ls -alh ./src-tauri/target/release/binDist + tar -cvzf binDist.tar.gz -C ./src-tauri/target/release binDist + ls -alh binDist.tar.gz + GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') + mv binDist.tar.gz "binDist-needGLIBC-${GLIBC_VER}.tar.gz" + ls + publish-release: permissions: contents: write timeout-minutes: 15 runs-on: ubuntu-22.04 - needs: [ create-release, build-tauri ] + needs: [ create-release, build-tauri, build-linux-bins ] steps: - uses: actions/checkout@v4 From 417ccc9f169b889edd6a0f997a2f1cf06b5a20a6 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 18:07:30 +0530 Subject: [PATCH 334/864] ci: linux bin artifact gen --- .github/workflows/tauri-build-dev.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 965e627e..6912874f 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -11,6 +11,7 @@ jobs: runs-on: ubuntu-latest outputs: release_id: ${{ steps.create-release.outputs.result }} + upload_url: ${{ steps.create-release.outputs.upload_url }} steps: - uses: actions/checkout@v4 @@ -27,6 +28,11 @@ jobs: uses: actions/github-script@v7 with: script: | + function setOutput(key, value) { + // Temporary hack until core actions library catches up with github new recommendations + const output = process.env['GITHUB_OUTPUT'] + fs.appendFileSync(output, `${key}=${value}${os.EOL}`) + } const { data } = await github.rest.repos.createRelease({ owner: context.repo.owner, repo: context.repo.repo, @@ -37,6 +43,7 @@ jobs: draft: true, prerelease: true }) + setOutput('upload_url', data.upload_url); return data.id build-mac-m1-node-modules: @@ -304,8 +311,20 @@ jobs: tar -cvzf binDist.tar.gz -C ./src-tauri/target/release binDist ls -alh binDist.tar.gz GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') - mv binDist.tar.gz "binDist-needGLIBC-${GLIBC_VER}.tar.gz" + OUTPUT_FILENAME="binDist-needGLIBC-${GLIBC_VER}.tar.gz" + mv binDist.tar.gz "$OUTPUT_FILENAME" + echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV ls + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create-release.outputs.upload_url }} + asset_path: ${{ env.OUTPUT_FILENAME }} + asset_name: ${{ env.OUTPUT_FILENAME }} + asset_content_type: application/gzip publish-release: permissions: From ae16b4665394856f0d0308018f4a20394d507c6f Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 18:10:28 +0530 Subject: [PATCH 335/864] fix: build break --- .github/workflows/tauri-build-dev.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 6912874f..51e21459 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -28,6 +28,8 @@ jobs: uses: actions/github-script@v7 with: script: | + const os = require("os") + const fs = require("fs") function setOutput(key, value) { // Temporary hack until core actions library catches up with github new recommendations const output = process.env['GITHUB_OUTPUT'] From 9d95789c9a7bdcfc872473ca9995af9ef4543353 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 18:39:28 +0530 Subject: [PATCH 336/864] ci: linux bin upload using supported action --- .github/workflows/tauri-build-dev.yml | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 51e21459..0a823450 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -11,7 +11,6 @@ jobs: runs-on: ubuntu-latest outputs: release_id: ${{ steps.create-release.outputs.result }} - upload_url: ${{ steps.create-release.outputs.upload_url }} steps: - uses: actions/checkout@v4 @@ -45,7 +44,6 @@ jobs: draft: true, prerelease: true }) - setOutput('upload_url', data.upload_url); return data.id build-mac-m1-node-modules: @@ -318,15 +316,13 @@ jobs: echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV ls - name: Upload Release Asset - id: upload-release-asset - uses: actions/upload-release-asset@v1 + uses: softprops/action-gh-release@v1 + with: + files: ${{ env.OUTPUT_FILENAME }} + tag_name: ${{ env.GIT_TAG_NAME }} + draft: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - asset_path: ${{ env.OUTPUT_FILENAME }} - asset_name: ${{ env.OUTPUT_FILENAME }} - asset_content_type: application/gzip publish-release: permissions: From 583bef6dbe68e983fbd32b58b7a92132357eb921 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 18:40:20 +0530 Subject: [PATCH 337/864] ci: linux bin upload using supported action --- .github/workflows/tauri-build-dev.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 0a823450..ca0fb28f 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -27,13 +27,6 @@ jobs: uses: actions/github-script@v7 with: script: | - const os = require("os") - const fs = require("fs") - function setOutput(key, value) { - // Temporary hack until core actions library catches up with github new recommendations - const output = process.env['GITHUB_OUTPUT'] - fs.appendFileSync(output, `${key}=${value}${os.EOL}`) - } const { data } = await github.rest.repos.createRelease({ owner: context.repo.owner, repo: context.repo.repo, From 8c36d3a2b1bc8d95f5d76e2e4a8df026579dec42 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 14 Feb 2024 13:24:02 +0000 Subject: [PATCH 338/864] ci: update phcode version to 3.3.5 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 9 ++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index e77e683f..64fcbf97 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.4", + "version": "3.3.5", "type": "module", "scripts": { "tauri": "tauri", @@ -53,6 +53,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "3745c2a913e800c5626f9332b3c0c449cca20dfb" + "commit": "05da456e0db5755ba87118f313c929d18aa9bfff" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1dda0685..ed7549f0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.4" +version = "3.3.5" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 111a3172..76755efd 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.4" + "version": "3.3.5" }, "tauri": { "allowlist": { @@ -103,9 +103,8 @@ "category": "DeveloperTool", "copyright": "Copyright (c) 2022 - present Core.ai", "deb": { - "desktopTemplate" : "./src/bundle/linux/deb/main.desktop.download", - "depends": [ - ] + "desktopTemplate": "./src/bundle/linux/deb/main.desktop.download", + "depends": [] }, "appimage": { "bundleMediaFramework": true @@ -409,4 +408,4 @@ } ] } -} +} \ No newline at end of file From d20542b6b47611e8b071dfc99c258fd1251843b8 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 18:55:13 +0530 Subject: [PATCH 339/864] ci: release artifact linux bin file name change --- .github/workflows/tauri-build-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index ca0fb28f..47378ba7 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -304,7 +304,7 @@ jobs: tar -cvzf binDist.tar.gz -C ./src-tauri/target/release binDist ls -alh binDist.tar.gz GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') - OUTPUT_FILENAME="binDist-needGLIBC-${GLIBC_VER}.tar.gz" + OUTPUT_FILENAME="phoenix-code-experimental-build_$(node -p "require('./package.json').version")_amd64_linux_bin-GLIBC-${GLIBC_VER}.tar.gz" mv binDist.tar.gz "$OUTPUT_FILENAME" echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV ls From 91e68256d99332689fb2bea7686216489a2ac1d0 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 19:34:29 +0530 Subject: [PATCH 340/864] ci: staging create linux bins --- .github/workflows/tauri-build-staging.yml | 62 ++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 9c74c282..c9f072a0 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -256,12 +256,72 @@ jobs: args: --target aarch64-apple-darwin tagName: ${{ env.GIT_TAG_NAME }} + build-linux-bins: + needs: [ create-release ] + permissions: + contents: write + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + platform: [ ubuntu-20.04, ubuntu-22.04] + + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v4 + - name: get Git Tag + run: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: GLIBC version + run: | + ldd --version + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + - name: install dependencies (ubuntu only) + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev + sudo apt-get install -y libwebrtc-audio-processing-dev + sudo apt-get install -y libunwind-dev + sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio + - name: install frontend dependencies + run: | + npm ci + npm run _ci-release:staging + npm run _ci-disableBundleConfig + npm run tauri build + ls -alh ./src-tauri/target/release + mkdir ./src-tauri/target/release/binDist + cp ./src-tauri/target/release/phoenix-code-pre-release ./src-tauri/target/release/binDist + cp ./src-tauri/target/release/phnode ./src-tauri/target/release/binDist + cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/binDist + ls -alh ./src-tauri/target/release/binDist + tar -cvzf binDist.tar.gz -C ./src-tauri/target/release binDist + ls -alh binDist.tar.gz + GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') + OUTPUT_FILENAME="phoenix-code-pre-release_$(node -p "require('./package.json').version")_amd64_linux_bin-GLIBC-${GLIBC_VER}.tar.gz" + mv binDist.tar.gz "$OUTPUT_FILENAME" + echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV + ls + - name: Upload Release Asset + uses: softprops/action-gh-release@v1 + with: + files: ${{ env.OUTPUT_FILENAME }} + tag_name: ${{ env.GIT_TAG_NAME }} + draft: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + publish-release: permissions: contents: write timeout-minutes: 15 runs-on: ubuntu-22.04 - needs: [ create-release, build-tauri ] + needs: [ create-release, build-tauri, build-linux-bins ] steps: - uses: actions/checkout@v4 From 379007f052b246db0dcbf86e44684bb80597b1ed Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 19:49:40 +0530 Subject: [PATCH 341/864] ci: prod create linux bins --- .github/workflows/tauri-build-prod.yml | 62 +++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 7056c6d7..f436d333 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -257,11 +257,71 @@ jobs: args: --target aarch64-apple-darwin tagName: ${{ env.GIT_TAG_NAME }} + build-linux-bins: + needs: [ create-release ] + permissions: + contents: write + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + platform: [ ubuntu-20.04, ubuntu-22.04] + + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v4 + - name: get Git Tag + run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV + - name: setup node + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: GLIBC version + run: | + ldd --version + - name: install Rust stable + uses: dtolnay/rust-toolchain@stable + - name: install dependencies (ubuntu only) + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev + sudo apt-get install -y libwebrtc-audio-processing-dev + sudo apt-get install -y libunwind-dev + sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio + - name: install frontend dependencies + run: | + npm ci + npm run _ci-release:prod + npm run _ci-disableBundleConfig + npm run tauri build + ls -alh ./src-tauri/target/release + mkdir ./src-tauri/target/release/binDist + cp ./src-tauri/target/release/phoenix-code ./src-tauri/target/release/binDist + cp ./src-tauri/target/release/phnode ./src-tauri/target/release/binDist + cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/binDist + ls -alh ./src-tauri/target/release/binDist + tar -cvzf binDist.tar.gz -C ./src-tauri/target/release binDist + ls -alh binDist.tar.gz + GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') + OUTPUT_FILENAME="phoenix-code_$(node -p "require('./package.json').version")_amd64_linux_bin-GLIBC-${GLIBC_VER}.tar.gz" + mv binDist.tar.gz "$OUTPUT_FILENAME" + echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV + ls + - name: Upload Release Asset + uses: softprops/action-gh-release@v1 + with: + files: ${{ env.OUTPUT_FILENAME }} + tag_name: ${{ env.GIT_TAG_NAME }} + draft: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + publish-release: permissions: contents: write runs-on: ubuntu-22.04 - needs: [ create-release, build-tauri ] + needs: [ create-release, build-tauri, build-linux-bins ] steps: - uses: actions/checkout@v4 From afa5980e1c7e58e94ce33d79a5fadb031a6fb57a Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Feb 2024 21:26:32 +0530 Subject: [PATCH 342/864] build: change linux bin name to phoenix-code from binDist --- .github/workflows/tauri-build-dev.yml | 16 ++++++++-------- .github/workflows/tauri-build-prod.yml | 8 +++++--- .github/workflows/tauri-build-staging.yml | 16 ++++++++-------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 47378ba7..4409f46a 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -296,16 +296,16 @@ jobs: npm run _ci-disableBundleConfig npm run tauri build ls -alh ./src-tauri/target/release - mkdir ./src-tauri/target/release/binDist - cp ./src-tauri/target/release/phoenix-code-experimental-build ./src-tauri/target/release/binDist - cp ./src-tauri/target/release/phnode ./src-tauri/target/release/binDist - cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/binDist - ls -alh ./src-tauri/target/release/binDist - tar -cvzf binDist.tar.gz -C ./src-tauri/target/release binDist - ls -alh binDist.tar.gz + mkdir ./src-tauri/target/release/phoenix-code + cp ./src-tauri/target/release/phoenix-code-experimental-build ./src-tauri/target/release/phoenix-code + cp ./src-tauri/target/release/phnode ./src-tauri/target/release/phoenix-code + cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/phoenix-code + ls -alh ./src-tauri/target/release/phoenix-code + tar -cvzf phoenix-code.tar.gz -C ./src-tauri/target/release phoenix-code + ls -alh phoenix-code.tar.gz GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') OUTPUT_FILENAME="phoenix-code-experimental-build_$(node -p "require('./package.json').version")_amd64_linux_bin-GLIBC-${GLIBC_VER}.tar.gz" - mv binDist.tar.gz "$OUTPUT_FILENAME" + mv phoenix-code.tar.gz "$OUTPUT_FILENAME" echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV ls - name: Upload Release Asset diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index f436d333..d7616535 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -301,11 +301,13 @@ jobs: cp ./src-tauri/target/release/phnode ./src-tauri/target/release/binDist cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/binDist ls -alh ./src-tauri/target/release/binDist - tar -cvzf binDist.tar.gz -C ./src-tauri/target/release binDist - ls -alh binDist.tar.gz + mv ./src-tauri/target/release/phoenix-code ./src-tauri/target/release/phoenix-code-backup + mv ./src-tauri/target/release/binDist ./src-tauri/target/release/phoenix-code + tar -cvzf phoenix-code.tar.gz -C ./src-tauri/target/release phoenix-code + ls -alh phoenix-code.tar.gz GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') OUTPUT_FILENAME="phoenix-code_$(node -p "require('./package.json').version")_amd64_linux_bin-GLIBC-${GLIBC_VER}.tar.gz" - mv binDist.tar.gz "$OUTPUT_FILENAME" + mv phoenix-code.tar.gz "$OUTPUT_FILENAME" echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV ls - name: Upload Release Asset diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index c9f072a0..ce235e2b 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -295,16 +295,16 @@ jobs: npm run _ci-disableBundleConfig npm run tauri build ls -alh ./src-tauri/target/release - mkdir ./src-tauri/target/release/binDist - cp ./src-tauri/target/release/phoenix-code-pre-release ./src-tauri/target/release/binDist - cp ./src-tauri/target/release/phnode ./src-tauri/target/release/binDist - cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/binDist - ls -alh ./src-tauri/target/release/binDist - tar -cvzf binDist.tar.gz -C ./src-tauri/target/release binDist - ls -alh binDist.tar.gz + mkdir ./src-tauri/target/release/phoenix-code + cp ./src-tauri/target/release/phoenix-code-pre-release ./src-tauri/target/release/phoenix-code + cp ./src-tauri/target/release/phnode ./src-tauri/target/release/phoenix-code + cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/phoenix-code + ls -alh ./src-tauri/target/release/phoenix-code + tar -cvzf phoenix-code.tar.gz -C ./src-tauri/target/release phoenix-code + ls -alh phoenix-code.tar.gz GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') OUTPUT_FILENAME="phoenix-code-pre-release_$(node -p "require('./package.json').version")_amd64_linux_bin-GLIBC-${GLIBC_VER}.tar.gz" - mv binDist.tar.gz "$OUTPUT_FILENAME" + mv phoenix-code.tar.gz "$OUTPUT_FILENAME" echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV ls - name: Upload Release Asset From f6b15df0f01157b5a912ccb494ac12339f722d26 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 15 Feb 2024 11:10:30 +0530 Subject: [PATCH 343/864] ci: verbatim release notes injection --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- .github/workflows/updateNotification.js | 11 +---------- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 4409f46a..dc628d14 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -33,7 +33,7 @@ jobs: tag_name: `${process.env.GIT_TAG_NAME}`, target_commitish: 'dev', name: `Phoenix Code Experimental build v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', + body: `**Phoenix Code Release Notes**\n\nPlease include detailed release notes here, highlighting new features, bug fixes, and improvements. Ensure to make these notes informative and clear for end-users.\n\n**For Maintainers:**\nTo distribute these release notes through the desktop application:\n1. Wait for a pull request with the updated release notes.\n3. Once the pull request is merged, merge to the update-notifications branch and the release notes will be automatically shown in the desktop builds.`, draft: true, prerelease: true }) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index d7616535..3b85e9f2 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -33,7 +33,7 @@ jobs: tag_name: `${process.env.GIT_TAG_NAME}`, target_commitish: 'prod', name: `Phoenix Code Stable Release v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', + body: `**Phoenix Code Release Notes**\n\nPlease include detailed release notes here, highlighting new features, bug fixes, and improvements. Ensure to make these notes informative and clear for end-users.\n\n**For Maintainers:**\nTo distribute these release notes through the desktop application:\n1. Wait for a pull request with the updated release notes.\n3. Once the pull request is merged, merge to the update-notifications branch and the release notes will be automatically shown in the desktop builds.`, draft: true, prerelease: false }) diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index ce235e2b..0c18fc23 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -33,7 +33,7 @@ jobs: tag_name: `${process.env.GIT_TAG_NAME}`, target_commitish: 'staging', name: `Phoenix Code Pre-release v${process.env.PACKAGE_VERSION}`, - body: 'Take a look at the assets to download and install Phoenix Code For your platform.\n\n>UpdateNotification: ', + body: `**Phoenix Code Release Notes**\n\nPlease include detailed release notes here, highlighting new features, bug fixes, and improvements. Ensure to make these notes informative and clear for end-users.\n\n**For Maintainers:**\nTo distribute these release notes through the desktop application:\n1. Wait for a pull request with the updated release notes.\n3. Once the pull request is merged, merge to the update-notifications branch and the release notes will be automatically shown in the desktop builds.`, draft: true, prerelease: true }) diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js index a8db9a54..9c39da6e 100644 --- a/.github/workflows/updateNotification.js +++ b/.github/workflows/updateNotification.js @@ -71,15 +71,6 @@ async function _getLatestJson(releaseAssets) { throw new Error(`Could not locate ${LATEST_JSON_GITHUB_RELEASE} file in github releases.`); } -function _extractSmallReleaseNotes(releaseNotes, releaseTitle) { - for(let line of releaseNotes.split("\n")){ - if(line.startsWith(">UpdateNotification: ")){ - return line.replace(">UpdateNotification: ", ""); - } - } - return releaseTitle; -} - function getCurrentVersion(latestJsonPath) { try{ return JSON.parse(fs.readFileSync(latestJsonPath, 'utf8')).version || '0.0.0'; @@ -143,7 +134,7 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) // write to the docs folder here. all changes made here to the docs folder will be part of the pull request console.log("Updating tauri update JSON file: ", _identifyUpdateJSONPath(releaseAssets)); const latestJSON = JSON.parse(await _getLatestJson(releaseAssets)); - latestJSON.notes = _extractSmallReleaseNotes(releaseNotes, releaseTitle); + latestJSON.notes = releaseNotes; const latestJsonPath = `${githubWorkspaceRoot}/docs/${_identifyUpdateJSONPath(releaseAssets)}`; const currentVersion = getCurrentVersion(latestJsonPath); const latestVersion = latestJSON.version; From 0dae890c68dd2c156ccc53c93f7b655bac6ab732 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 15 Feb 2024 06:19:07 +0000 Subject: [PATCH 344/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 178966f5..2c243a5a 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.3.3", - "notes": "test release", - "pub_date": "2024-02-11T16:49:29.809Z", + "version": "3.3.4", + "notes": "Take a look at the assets to download and install Phoenix Code For your platform.\r\n\r\n## A heading\r\n\r\nThis is a title.\r\n![An image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/d8b3c5b9-ec5b-41d0-8283-0dc318a450ec)\r\n", + "pub_date": "2024-02-13T09:52:05.845Z", "platforms": { - "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmk5amY0UEh6TGdQdFo5MDl2TFNoVlhETlU5U1VGa0pNdVBrVDY0dFhWU0Vvbit1Q2JnekFGeWxDL3J4ZnVkMUovdThPa0s3ajZGOExneWlVY1B4bUFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5MzEyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuM194NjQtc2V0dXAubnNpcy56aXAKK0FBZkc1K0pMZUF0ejIzTEpXNkFKQjdJNGZiUURnUWRtWXdXR0crTEVqVDdwZVMrbjdLQ2JVVmRLYTRwczEvd0wyekVZVG5vU21ZaWo4dk5ZNTlmRHc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.3/Phoenix.Code.Experimental.Build_3.3.3_x64-setup.nsis.zip" - }, "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmcwOWpvSGk4K0svRzhXaXAzc2ZBcmZIQy9YRng4dEllNHJaOXYzRzdlaWdlRnplazd5aUhyTnZZcTlORzBXSTc5ajk0UGN6N3ZRczc1eXJZNzRhK2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5MzQ2CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuM19hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKVDFBZzFTL2ZNVHVzTTVJbi80a0NLeTV6bFA5NDZRUTA1aUR0Rll4YkFpaDVoWnh0YWt6aUtLTTc3NTVPVm83aGsreDBySFM1VDVxaVZaYzlzZFN5REE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.3/phoenix-code-experimental-build_3.3.3_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZaTmZOQjBXRStCYVBrVnFORWI2S1czU2dMM29sWDEvamZlZHBHZm9PSHlEdk5HSW4zTkRVTEdGakZreGhhdkJDTG9mc0dCbzNLdlhHTG1RNFRrTkFJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3ODE0OTk3CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuNF9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKNXQwYXlHMWJlZWRhNmI5VDNuK1drWjNKUUFSL0FhU2dRTW5SZWR0RVIzaXIrMXBSbmd2MEVGT0ZmQWkyTXVGbTdXMllETEs1TnF3U1l1WGRQR3BNQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.4/phoenix-code-experimental-build_3.3.4_amd64.AppImage.tar.gz" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9JL01UaTN3VDdSY1Q1ZGZVNG00YjRKWUoxZitITXROVUxTZGxoZnlwbXdNV0tBcEwvbUJUeURQTnBLbGJhdktUQXR0YlUydWd3UldoR3J3OXdrK0FrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5NjQzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnRxTFVuM1V0cnYxT0FHYnBwY0IzYTcvRWsxMjcwcTlyUlUvOUY5NDNEWWZhS3JadWM5MFd5Z1VXRWVJUjNybThnOUZ6a0YwQ3o2KzJ2NHhyNmVZRkRBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.3/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnM5aE9CRGVKUmJwTE1zbERqS0IvZjJNWGJheXlYaHZlOEhJazRWdVhSdnRBQStlQjZtREZubmtmR1AxZE5hYm1HenNQUjZPR0JnZTV3WlV6UWlPb0F3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3ODE1OTEzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClB3TTQ4UFhIZHFiNlk3WDNrSGZXVVBFRERLRld1ZVNIYkZuWGMwNDV2YmdNRzUrYVBNdzZMYnk4U3ByTldXek54THNMcjNnaWVpdm5iOFB2ZmF1dENnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.4/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1MZksyditmcWR2TVNCbmVrQk9Hd2gxMHI0UDE4aHRtaVdJdytOVGlkb0N6dkFXcE1Rd0J5YnJ1NFJ1UzZwN3NDTFptTDJnQWJ6TUt5MG9NVlVTZHdnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjcwMTYwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Clc2bks5WTNMRVgvZkc1YWV5Tnc1UURHMlRLa3I5Zm11Y29TWXkyZ291RitGOTlrN3JTUjlCRW5vazZCRFBKaDJFc0t5K1UwSWwrMkIxbElqbzVnRkNnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.3/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmpQcGlvUWgrOWVWVEJXVlMxQ2VsNzBVODVzWXJRZTArVzVWd1dKNStIdmpXSHNsaFBUS3p5Wk9rVlRpRnYwUHp6aTBXa3NQU25SZUsvck43cUZvZ1FzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3ODE2NzY5CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjRqWGpnWFZ1R1ZoK09pSXhJVVVKQ2N3a3orUUVVUEtpdVhHSjhjaExzcEJYeFV2bmFyRXNROEErY1YyTkxxL3FVNFpucVphR1g3Z1hEckUxSngwTERnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.4/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + }, + "windows-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhzSWg2Wnk0QTJXd1o3Y1FvZE1RL2hOd0hncGNHbTNEWC82a3dObmdsOGRBTXB2RHZBbXZoZTRPRnNLakVyU2FRc1hZdVFkNVE2Znl6QzRDbnRWRndNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3ODE3OTIxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuNF94NjQtc2V0dXAubnNpcy56aXAKVTBxaGozVTNnNzJmMmJoa21MYjVrekxVNWd5K2ZFdHJ3R0oyUnVIdUpGbWg3b2VOVWlwOXVnTGJYaFJQdmJEZ3o5bmwzRHlsWjFLQk9OR0h4MUt0QkE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.4/Phoenix.Code.Experimental.Build_3.3.4_x64-setup.nsis.zip" } } } \ No newline at end of file From 113af0225d017686192da7ea0ab567760fa6a215 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 15 Feb 2024 12:46:50 +0530 Subject: [PATCH 345/864] ci: add readme.txt for linux binary distributions --- .github/workflows/tauri-build-dev.yml | 1 + .github/workflows/tauri-build-prod.yml | 1 + .github/workflows/tauri-build-staging.yml | 1 + src-build/linux/install-readme.txt | 71 +++++++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 src-build/linux/install-readme.txt diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index dc628d14..4bcc2dc0 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -298,6 +298,7 @@ jobs: ls -alh ./src-tauri/target/release mkdir ./src-tauri/target/release/phoenix-code cp ./src-tauri/target/release/phoenix-code-experimental-build ./src-tauri/target/release/phoenix-code + cp ./src-build/linux/install-readme.txt ./src-tauri/target/release/phoenix-code/readme.txt cp ./src-tauri/target/release/phnode ./src-tauri/target/release/phoenix-code cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/phoenix-code ls -alh ./src-tauri/target/release/phoenix-code diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 3b85e9f2..01b471e9 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -298,6 +298,7 @@ jobs: ls -alh ./src-tauri/target/release mkdir ./src-tauri/target/release/binDist cp ./src-tauri/target/release/phoenix-code ./src-tauri/target/release/binDist + cp ./src-build/linux/install-readme.txt ./src-tauri/target/release/binDist/readme.txt cp ./src-tauri/target/release/phnode ./src-tauri/target/release/binDist cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/binDist ls -alh ./src-tauri/target/release/binDist diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 0c18fc23..bf4fa52b 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -297,6 +297,7 @@ jobs: ls -alh ./src-tauri/target/release mkdir ./src-tauri/target/release/phoenix-code cp ./src-tauri/target/release/phoenix-code-pre-release ./src-tauri/target/release/phoenix-code + cp ./src-build/linux/install-readme.txt ./src-tauri/target/release/phoenix-code/readme.txt cp ./src-tauri/target/release/phnode ./src-tauri/target/release/phoenix-code cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/phoenix-code ls -alh ./src-tauri/target/release/phoenix-code diff --git a/src-build/linux/install-readme.txt b/src-build/linux/install-readme.txt new file mode 100644 index 00000000..cb3efa1a --- /dev/null +++ b/src-build/linux/install-readme.txt @@ -0,0 +1,71 @@ +Phoenix Code Installation Guide +================================ + +Before installing Phoenix Code, ensure you have the correct binary for the GLIBC version present in your system. + Determine your system's GLIBC version with the following command: + +$ ldd --version + +Example output: ldd (Ubuntu GLIBC 2.35-0ubuntu3.6) 2.35 + +Choosing the Correct Binary: +--------------------------------- +If your GLIBC version is 2.35 or higher, download the binary compiled for GLIBC 2.35. For GLIBC versions lower than + 2.35, use the binary compiled for GLIBC 2.31. This ensures compatibility with your system's library version. + +If your GLIBC version does not match the Phoenix Code binary you have +--------------------------------------------------------------------- +download the appropriate version from our releases page: + +https://github.com/phcode-dev/phoenix-desktop/releases + +Available binaries: +- phoenix-code_3.3.5_amd64_linux_bin-GLIBC-2.31.tar.gz +- phoenix-code_3.3.5_amd64_linux_bin-GLIBC-2.35.tar.gz + +Download the binary that matches or exceeds your system's GLIBC version for optimal compatibility. + +Installation Prerequisites +========================== + +Ubuntu/Debian Based Distributions +--------------------------------- +1. Update your package list: + $ sudo apt update + +2. Install WebKitGTK and GTK: + $ sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 + Note: In Ubuntu 22+ versions, WebKitGTK may be pre-installed. + +3. Install GStreamer plugins for media playback: + $ sudo apt install gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-tools gstreamer1.0-libav + +Fedora/Red Hat +-------------- +1. Update your package list: + $ sudo dnf update + +2. Install WebKitGTK and GTK: + $ sudo dnf install webkit2gtk3 gtk3 + +3. Install GStreamer plugins for media playback: + $ sudo dnf install gstreamer1-plugins-base gstreamer1-plugins-good gstreamer1-plugins-bad-free gstreamer1-plugins-bad-freeworld gstreamer1-plugins-ugly gstreamer1-libav + +Arch Linux +---------- +1. Ensure your system is up to date: + $ sudo pacman -Syu + +2. Install WebKitGTK and GTK: + $ sudo pacman -S webkit2gtk gtk3 + +3. Install GStreamer plugins for media playback: + $ sudo pacman -S gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav + +After installing the prerequisites for your respective distribution, you can just launch the binary in this folder +$ ./phoenix-code + +For any issues or further assistance, please refer to our support forum or contact us directly at: +https://github.com/orgs/phcode-dev/discussions + +Thank you for choosing Phoenix Code. From abc37e0d8b263461397804a600fbcb665ec93209 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 15 Feb 2024 10:44:08 +0000 Subject: [PATCH 346/864] ci: tauri release update notification json --- docs/tauri/update-latest-experimental-build.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 2c243a5a..152f8717 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,6 +1,6 @@ { "version": "3.3.4", - "notes": "Take a look at the assets to download and install Phoenix Code For your platform.\r\n\r\n## A heading\r\n\r\nThis is a title.\r\n![An image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/d8b3c5b9-ec5b-41d0-8283-0dc318a450ec)\r\n", + "notes": "Take a look at the assets to download and install Phoenix Code For your platform.\r\n\r\n## A heading\r\n\r\nThis is a title.\r\n![An image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/d8b3c5b9-ec5b-41d0-8283-0dc318a450ec)\r\n\r\nplease share your thoughts and feedback @ [GitHub issues page](https://github.com/phcode-dev/phoenix/issues/new/choose).\r\n\r\n## 🚀 Mac (Intel/M1) DMGs 🚀\r\nM1/Apple silicon macs: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_aarch64.dmg\r\nIntel Macs: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_x64.dmg\r\n\r\n## 🚀 Windows Installers 🚀\r\nWindows installers will be avilable soon...\r\n\r\n## 🚀 Exciting News: Our First Linux Beta Build! 🚀\r\n\r\n**🔧 Installation Instructions**\r\nTo dive into the Linux beta version, simply execute the following command in your terminal:\r\n```bash\r\n# install libfuse2 in ubuntu, else ignore this step\r\nsudo apt-get install libfuse2\r\n\r\nwget -qO- https://updates.phcode.io/linux/installer.sh | bash\r\n```\r\n\r\n**🗑️ Uninstallation**\r\nIf you need to uninstall the beta version, please use the following command:\r\n```bash\r\nwget -qO- https://updates.phcode.io/linux/installer.sh | bash -s -- --uninstall\r\n```\r\n", "pub_date": "2024-02-13T09:52:05.845Z", "platforms": { "linux-x86_64": { From 8f68c9384eb25e2bdde4c681d11fc9602ff6d5a8 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 15 Feb 2024 17:20:41 +0530 Subject: [PATCH 347/864] build: add a -v and --version cli --- src-tauri/Cargo.lock | 2 +- src-tauri/src/main.rs | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 458e2b3a..c2edd183 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2767,7 +2767,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.3.4" +version = "3.3.5" dependencies = [ "clipboard-files", "fix-path-env", diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index b9cf9303..7cdd1663 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -250,7 +250,12 @@ fn main() { // Mainly used by linux installer to see if the app loaded successfully with all libs std::process::exit(0); } - + let app_version = env!("CARGO_PKG_VERSION"); + if args.contains(&"--version".to_string()) || args.contains(&"-v".to_string()) { + // Display the version and exit + println!("{}", app_version); + std::process::exit(0); + } #[cfg(target_os = "macos")]{ tauri_plugin_deep_link::prepare("io.phcode"); } From 2b40324b28db73580a43846205d986f9ddcd5654 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 18 Feb 2024 20:00:22 +0530 Subject: [PATCH 348/864] refactor: remove unused open url in browser api --- src-tauri/Cargo.lock | 45 +------------------------------------------ src-tauri/Cargo.toml | 1 - src-tauri/src/main.rs | 27 +------------------------- 3 files changed, 2 insertions(+), 71 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index c2edd183..6ca15a5c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1642,15 +1642,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "html5ever" version = "0.25.2" @@ -1955,22 +1946,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - [[package]] name = "jni-sys" version = "0.3.0" @@ -2785,7 +2760,6 @@ dependencies = [ "tauri-plugin-fs-extra", "tauri-plugin-single-instance", "tauri-plugin-window-state", - "webbrowser", "webkit2gtk", "winapi", ] @@ -3760,7 +3734,7 @@ dependencies = [ "gtk", "image", "instant", - "jni 0.20.0", + "jni", "lazy_static", "libc", "log", @@ -4681,23 +4655,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webbrowser" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2391658b02c27719fc5a0a73d6e696285138e8b12fba9d4baa70451023c71" -dependencies = [ - "core-foundation", - "home", - "jni 0.21.1", - "log", - "ndk-context", - "objc", - "raw-window-handle", - "url", - "web-sys", -] - [[package]] name = "webkit2gtk" version = "0.18.2" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ed7549f0..3b2320f6 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,7 +19,6 @@ once_cell = "1.19.0" percent-encoding = "2.3" regex = "1.10.3" clipboard-files = "0.1.1" -webbrowser = "0.8.12" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.5.4", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 7cdd1663..83395a95 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,9 +4,6 @@ windows_subsystem = "windows" )] use std::env; -#[cfg(not(target_os = "linux"))] -use webbrowser; - use tauri::{Manager}; use std::path::PathBuf; @@ -182,28 +179,6 @@ fn zoom_window(window: tauri::Window, scale_factor: f64) { }); } -#[tauri::command] -fn open_url_in_browser(url: String) -> Result<(), String> { - #[cfg(target_os = "linux")] - { - // Use xdg-open for Linux - Command::new("xdg-open") - .arg(&url) - .current_dir("/tmp") - .spawn() - .map_err(|err| format!("Failed to open URL on Linux: {}", err))?; - } - - #[cfg(any(target_os = "windows", target_os = "macos"))] - { - // Use the webbrowser crate for Windows and Mac - webbrowser::open(&url) - .map_err(|err| format!("Failed to open URL in the browser: {}", err))?; - } - - Ok(()) -} - fn process_window_event(event: &GlobalWindowEvent) { if let tauri::WindowEvent::CloseRequested { .. } = event.event() { // this does nothing and is here if in future you need to persist something on window close. @@ -326,7 +301,7 @@ fn main() { .invoke_handler(tauri::generate_handler![ get_mac_deep_link_requests, toggle_devtools, console_log, console_error, _get_commandline_args, get_current_working_dir, - _get_window_labels, open_url_in_browser, + _get_window_labels, _get_windows_drives, _rename_path, show_in_folder, zoom_window, _get_clipboard_files]) .setup(|app| { init::init_app(app); From 5f01fd9bb5a4c352367831cbe2302180ea3b492f Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 15 Feb 2024 17:54:48 +0530 Subject: [PATCH 349/864] feat: adding support for multiple os --- docs/linux/installer.sh | 281 +++++++++++++++++++++++++++------------- 1 file changed, 193 insertions(+), 88 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 0b3bff0b..bc072384 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -5,143 +5,248 @@ APPIMAGE_DIR=$HOME/.local/bin DESKTOP_DIR=$HOME/.local/share/applications NEW_APPIMAGE=phcode ICON=phoenix_icon.png -GITHUB_REPO="phcode-dev/phoenix-desktop" +GITHUB_REPO="charlypa/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" -check_and_install_libfuse() { - # Identify the Linux distribution +INSTALL_DIR="$HOME/.phoenix-code" +LINK_DIR="$HOME/.local/bin" +DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries +DESKTOP_ENTRY="$DESKTOP_DIR/PhoenixCode.desktop" +SCRIPT_NAME="phoenix-code" # Name of the script to invoke the binary + +create_invocation_script() { + local binary_path="$1" + local script_name="$2" + local link_dir="$3" + + echo "Creating an invocation script for the binary..." + echo "#!/bin/bash" > "$binary_path/$script_name.sh" + echo "$binary_path/$script_name \"\$@\"" >> "$binary_path/$script_name.sh" + chmod +x "$binary_path/$script_name.sh" + + echo "Copying the invocation script to $link_dir..." + mkdir -p "$link_dir" # Ensure the directory exists + cp "$binary_path/$script_name.sh" "$link_dir/$script_name" +} +install_dependencies() { + echo "Attempting to install required dependencies..." + + # Attempt to identify the Linux distribution if [ -f /etc/os-release ]; then . /etc/os-release DISTRO=$ID else - echo "Cannot identify the operating system." + echo "Unable to identify the operating system." exit 1 fi - echo "Checking for FUSE library..." - - if [ "$DISTRO" = "ubuntu" ]; then - # Check and install libfuse2 on Ubuntu - if ! dpkg -s libfuse2 &> /dev/null; then - echo "libfuse2 not found, installing..." - sudo apt-get update && sudo apt-get install -y libfuse2 || { echo "Failed to install libfuse2"; exit 1; } - else - echo "libfuse2 is already installed." - fi - elif [ "$DISTRO" = "fedora" ]; then - # Check and install fuse-libs on Fedora - if [ "$DISTRO" = "fedora" ]; then - # Check and install fuse-libs on Fedora - if ! rpm -q fuse-libs &> /dev/null; then - echo "fuse-libs not found, installing..." - sudo dnf install -y fuse-libs || { echo "Failed to install fuse-libs"; exit 1; } - else - echo "fuse-libs is already installed." - fi - fi + # Install dependencies based on the distribution + case "$DISTRO" in + ubuntu|debian|linuxmint) + echo "Detected an Ubuntu/Debian based distribution." + sudo apt update + sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \ + gstreamer1.0-tools gstreamer1.0-libav + ;; + fedora|rhel|centos) + echo "Detected a Fedora/Red Hat based distribution." + sudo dnf update + sudo dnf install webkit2gtk3 gtk3 \ + gstreamer1-plugins-base gstreamer1-plugins-good \ + gstreamer1-plugins-bad-free gstreamer1-plugins-bad-freeworld \ + gstreamer1-plugins-ugly gstreamer1-libav + ;; + arch|manjaro) + echo "Detected an Arch Linux based distribution." + sudo pacman -Syu + sudo pacman -S webkit2gtk gtk3 \ + gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav + ;; + *) + echo "Unsupported distribution. Please manually install the required dependencies." + exit 1 + ;; + esac +} +verify_and_install_dependencies() { + # First attempt to verify the application launch + if ./phoenix-code --runVerify; then + echo "Application launch verification successful." + return 0 # Exit the function successfully if verification succeeds + else + echo "Initial verification failed. Attempting to install dependencies..." + install_dependencies # Function to install required dependencies + fi + # Second attempt to verify the application launch after installing dependencies + if ./phoenix-code --runVerify; then + echo "Application launch verification successful after installing dependencies." + return 0 # Exit the function successfully if verification succeeds else - echo "Unsupported distribution: $DISTRO" - exit 1 + echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." + return 1 # Return an error code to indicate failure fi } install() { - check_and_install_libfuse - # Fetch the latest release data from GitHub - echo "Fetching latest release from $GITHUB_REPO..." - wget -qO- $API_URL > latest_release.json || { echo "Failed to fetch latest release info"; exit 1; } - - # Extract the download URL for the AppImage - APPIMAGE_URL=$(grep -oP '"browser_download_url": "\K(.*phoenix-desktop.*\.AppImage)(?=")' latest_release.json) || { echo "Failed to extract AppImage URL"; exit 1; } - - # If no AppImage URL is found, exit the script - if [ -z "$APPIMAGE_URL" ]; then - echo "No AppImage URL found in the latest release." - rm latest_release.json + GITHUB_REPO="charlypa/phoenix-desktop" # Replace with your actual GitHub repository + API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" + INSTALL_DIR="$HOME/.phoenix-code" # Installation directory + + cleanup() { + echo "Cleaning up temporary files in $TMP_DIR" + rm -rf "$TMP_DIR" # This will delete the temporary directory and all its contents, including latest_release.json + } + + trap cleanup EXIT + + TMP_DIR=$(mktemp -d) + echo "Using temporary directory $TMP_DIR for processing" + + echo "Fetching the latest release information from $GITHUB_REPO..." + wget -qO "$TMP_DIR/latest_release.json" "$API_URL" || { + echo "Failed to fetch the latest release information. Please check your internet connection and try again." exit 1 - fi + } - # Download the AppImage - echo "Downloading AppImage from $APPIMAGE_URL..." - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL || { echo "Failed to download AppImage"; exit 1; } - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $ICON $ICON_URL || { echo "Failed to download Icon"; exit 1; } - # Remove the temporary JSON file - rm latest_release.json + CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') + echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" + BEST_MATCH_URL="" + BEST_MATCH_VERSION=0 + echo "Searching for a compatible binary..." - # Proceed with installation steps as before... - # Create necessary directories - mkdir -p $APPIMAGE_DIR - mkdir -p $DESKTOP_DIR + while read -r BINARY_URL; do + BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') + if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then + BEST_MATCH_URL="$BINARY_URL" + BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" + echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" + fi + done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") - # Copy and rename the AppImage, and copy the icon to the AppImage directory - echo "Installing Phoenix..." - mv $NEW_APPIMAGE $APPIMAGE_DIR/$NEW_APPIMAGE - mv "$ICON" $APPIMAGE_DIR # Ensure this icon file is in the current directory + if [ -z "$BEST_MATCH_URL" ]; then + echo "No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation." + exit 1 + fi - # Make the new AppImage executable - chmod +x $APPIMAGE_DIR/$NEW_APPIMAGE + echo "Downloading the compatible binary from $BEST_MATCH_URL..." + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { + echo "Failed to download the binary. Please check your internet connection and try again." + exit 1 + } + echo "Downloading the icon..." + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { + echo "Failed to download Icon"; + exit 1; + } + echo "Extracting the binary to $TMP_DIR..." + tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { + echo "Failed to extract the binary. The downloaded file might be corrupt." + exit 1 + } + cd "$TMP_DIR/phoenix-code" + # Verify binary execution and install dependencies if necessary + if ! verify_and_install_dependencies; then + echo "Unable to successfully verify application launch. Exiting installation." + exit 1 + fi + echo "Setting up the installation directory at $INSTALL_DIR..." + mkdir -p "$INSTALL_DIR" + mkdir -p "$DESKTOP_DIR" + + echo "Moving the necessary files to the installation directory..." + mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { + echo "Failed to move the files to the installation directory. Please check the permissions and try again." + exit 1 + } + # Move the icon to the installation directory + mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" + + echo "Setting the correct permissions for the executable..." + chmod +x "$INSTALL_DIR/phoenix-code" || { + echo "Failed to set executable permissions. Please check the file path and permissions." + exit 1 + } + + mkdir -p "$LINK_DIR" # Ensure the directory exists + # Call the function to create and copy the invocation script + create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" # Define MIME types for file extensions MIME_TYPES="text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;" - # Add directory association MIME_TYPES+="inode/directory;" - - # Create a desktop entry for the AppImage with MIME type associations -cat > $DESKTOP_DIR/PhoenixCode.desktop < "$DESKTOP_ENTRY" < /dev/null - then - update-desktop-database $DESKTOP_DIR + echo "Updating desktop database..." + if command -v update-desktop-database &> /dev/null; then + update-desktop-database "$DESKTOP_DIR" fi # Update the KDE desktop database if KDE is in use if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null - then + if command -v kbuildsycoca5 &> /dev/null; then kbuildsycoca5 fi fi - - echo "Phoenix Code installed successfully." + echo "Installation completed successfully. Phoenix Code is now installed." } uninstall() { - # Remove the AppImage and the icon - echo "Uninstalling Phoenix..." - rm -f $APPIMAGE_DIR/$NEW_APPIMAGE - rm -f $APPIMAGE_DIR/$ICON - - # Remove the desktop entry - rm -f $DESKTOP_DIR/PhoenixCode.desktop - - # Update the desktop database for GNOME, Unity, XFCE, etc. (if available) - if command -v update-desktop-database &> /dev/null - then - update-desktop-database $DESKTOP_DIR + echo "Starting uninstallation of Phoenix Code..." + + # Remove the invocation script from ~/.local/bin + if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then + echo "Removing invocation script from $LINK_DIR..." + rm "$LINK_DIR/$SCRIPT_NAME" + else + echo "Invocation script not found in $LINK_DIR. Skipping..." fi - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null - then - kbuildsycoca5 + # Delete the desktop entry + if [ -f "$DESKTOP_ENTRY" ]; then + echo "Removing desktop entry..." + rm "$DESKTOP_ENTRY" + + # Update the desktop database for GNOME, Unity, XFCE, etc. + echo "Updating desktop database..." + if command -v update-desktop-database &> /dev/null; then + update-desktop-database "$DESKTOP_DIR" fi + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi + fi + else + echo "Desktop entry not found. Skipping..." + fi + + # Remove the installation directory and its contents + if [ -d "$INSTALL_DIR" ]; then + echo "Removing installation directory and its contents..." + rm -rf "$INSTALL_DIR" + else + echo "Installation directory not found. Skipping..." fi - echo "Phoenix uninstalled successfully." + echo "Uninstallation of Phoenix Code completed." } # Check for command-line arguments From e03facc43eb3b777b993c66fd4fe8d3c1fcbef61 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 15 Feb 2024 18:22:25 +0530 Subject: [PATCH 350/864] chore: added propmt in linux installer --- docs/linux/installer.sh | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index bc072384..52602483 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -29,7 +29,15 @@ create_invocation_script() { cp "$binary_path/$script_name.sh" "$link_dir/$script_name" } install_dependencies() { - echo "Attempting to install required dependencies..." + echo "Attempting to install required dependencies..." + + # Inform the user that the next steps require administrative access + echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." + + # Check if the script can execute sudo commands without interaction + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed with the installation of dependencies." + fi # Attempt to identify the Linux distribution if [ -f /etc/os-release ]; then @@ -71,6 +79,9 @@ install_dependencies() { esac } verify_and_install_dependencies() { + cd "$TMP_DIR/phoenix-code" + # Ensure the binary is executable + chmod +x "./phoenix-code" # First attempt to verify the application launch if ./phoenix-code --runVerify; then echo "Application launch verification successful." @@ -88,18 +99,31 @@ verify_and_install_dependencies() { echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." return 1 # Return an error code to indicate failure fi + cd - } install() { - GITHUB_REPO="charlypa/phoenix-desktop" # Replace with your actual GitHub repository - API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" - INSTALL_DIR="$HOME/.phoenix-code" # Installation directory + # Check if the application is already installed + if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then + echo "Phoenix Code appears to be already installed." + # Prompt the user for input on whether to repair (reinstall) + read -p "Would you like to repair (reinstall) it? (y/N): " response + case "$response" in + [Yy]* ) + echo "Proceeding with the reinstallation..." + uninstall + ;; + * ) + echo "Installation aborted by the user." + exit 0 + ;; + esac + fi cleanup() { echo "Cleaning up temporary files in $TMP_DIR" rm -rf "$TMP_DIR" # This will delete the temporary directory and all its contents, including latest_release.json } - trap cleanup EXIT TMP_DIR=$(mktemp -d) @@ -148,7 +172,6 @@ install() { exit 1 } - cd "$TMP_DIR/phoenix-code" # Verify binary execution and install dependencies if necessary if ! verify_and_install_dependencies; then echo "Unable to successfully verify application launch. Exiting installation." From dbb1e38fad1484ebb7c6b69ff8704e29e43814f4 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 15 Feb 2024 18:45:29 +0530 Subject: [PATCH 351/864] chore: added colours for echo --- docs/linux/installer.sh | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 52602483..fa0fcae8 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -14,6 +14,12 @@ DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries DESKTOP_ENTRY="$DESKTOP_DIR/PhoenixCode.desktop" SCRIPT_NAME="phoenix-code" # Name of the script to invoke the binary +# Define color variables for easy reference +GREEN="\e[32m" +YELLOW="\e[33m" +RED="\e[31m" +RESET="\e[0m" + create_invocation_script() { local binary_path="$1" local script_name="$2" @@ -121,7 +127,6 @@ install() { esac fi cleanup() { - echo "Cleaning up temporary files in $TMP_DIR" rm -rf "$TMP_DIR" # This will delete the temporary directory and all its contents, including latest_release.json } trap cleanup EXIT @@ -129,9 +134,9 @@ install() { TMP_DIR=$(mktemp -d) echo "Using temporary directory $TMP_DIR for processing" - echo "Fetching the latest release information from $GITHUB_REPO..." + echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" wget -qO "$TMP_DIR/latest_release.json" "$API_URL" || { - echo "Failed to fetch the latest release information. Please check your internet connection and try again." + echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" exit 1 } @@ -152,29 +157,29 @@ install() { done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") if [ -z "$BEST_MATCH_URL" ]; then - echo "No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation." + echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" exit 1 fi - echo "Downloading the compatible binary from $BEST_MATCH_URL..." - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { - echo "Failed to download the binary. Please check your internet connection and try again." + echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { + echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" exit 1 } - echo "Downloading the icon..." + echo -e "${YELLOW}Downloading the icon...${RESET}" wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { - echo "Failed to download Icon"; + echo -e "${RED}Failed to download Icon${RESET}"; exit 1; } echo "Extracting the binary to $TMP_DIR..." tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { - echo "Failed to extract the binary. The downloaded file might be corrupt." + echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" exit 1 } # Verify binary execution and install dependencies if necessary if ! verify_and_install_dependencies; then - echo "Unable to successfully verify application launch. Exiting installation." + echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" exit 1 fi @@ -184,7 +189,7 @@ install() { echo "Moving the necessary files to the installation directory..." mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { - echo "Failed to move the files to the installation directory. Please check the permissions and try again." + echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" exit 1 } # Move the icon to the installation directory @@ -192,7 +197,7 @@ install() { echo "Setting the correct permissions for the executable..." chmod +x "$INSTALL_DIR/phoenix-code" || { - echo "Failed to set executable permissions. Please check the file path and permissions." + echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" exit 1 } @@ -226,7 +231,7 @@ EOF kbuildsycoca5 fi fi - echo "Installation completed successfully. Phoenix Code is now installed." + echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" } uninstall() { From 3fd3dc4a64b7570d9decdc6cdff9e18a8c49e9b6 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 16 Feb 2024 20:58:16 +0530 Subject: [PATCH 352/864] chore: reduce dependencies fedora and arch --- docs/linux/installer.sh | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index fa0fcae8..1f5a5bf6 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -61,22 +61,17 @@ install_dependencies() { sudo apt update sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ - gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \ - gstreamer1.0-tools gstreamer1.0-libav + gstreamer1.0-tools ;; fedora|rhel|centos) echo "Detected a Fedora/Red Hat based distribution." - sudo dnf update sudo dnf install webkit2gtk3 gtk3 \ - gstreamer1-plugins-base gstreamer1-plugins-good \ - gstreamer1-plugins-bad-free gstreamer1-plugins-bad-freeworld \ - gstreamer1-plugins-ugly gstreamer1-libav + gstreamer1-plugins-base gstreamer1-plugins-good ;; arch|manjaro) echo "Detected an Arch Linux based distribution." sudo pacman -Syu - sudo pacman -S webkit2gtk gtk3 \ - gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav + sudo pacman -S webkit2gtk gtk3 ;; *) echo "Unsupported distribution. Please manually install the required dependencies." From 3ffbda886a7366db9359856484db678fc6f5a08d Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 17 Feb 2024 01:16:16 +0530 Subject: [PATCH 353/864] feat: add support for upgrade --- docs/linux/installer.sh | 473 +++++++++++++++++++++------------------- 1 file changed, 247 insertions(+), 226 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 1f5a5bf6..4606ecd8 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,10 +1,7 @@ #!/bin/bash set -e # Exit immediately if a command exits with a non-zero status. # Define common variables -APPIMAGE_DIR=$HOME/.local/bin DESKTOP_DIR=$HOME/.local/share/applications -NEW_APPIMAGE=phcode -ICON=phoenix_icon.png GITHUB_REPO="charlypa/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" @@ -21,191 +18,116 @@ RED="\e[31m" RESET="\e[0m" create_invocation_script() { - local binary_path="$1" - local script_name="$2" - local link_dir="$3" - - echo "Creating an invocation script for the binary..." - echo "#!/bin/bash" > "$binary_path/$script_name.sh" - echo "$binary_path/$script_name \"\$@\"" >> "$binary_path/$script_name.sh" - chmod +x "$binary_path/$script_name.sh" - - echo "Copying the invocation script to $link_dir..." - mkdir -p "$link_dir" # Ensure the directory exists - cp "$binary_path/$script_name.sh" "$link_dir/$script_name" + local binary_path="$1" + local script_name="$2" + local link_dir="$3" + + echo "Creating an invocation script for the binary..." + echo "#!/bin/bash" > "$binary_path/$script_name.sh" + echo "$binary_path/$script_name \"\$@\"" >> "$binary_path/$script_name.sh" + chmod +x "$binary_path/$script_name.sh" + + echo "Copying the invocation script to $link_dir..." + mkdir -p "$link_dir" # Ensure the directory exists + cp "$binary_path/$script_name.sh" "$link_dir/$script_name" } install_dependencies() { - echo "Attempting to install required dependencies..." - - # Inform the user that the next steps require administrative access - echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." - - # Check if the script can execute sudo commands without interaction - if ! sudo -n true 2>/dev/null; then - echo "Please enter your password to proceed with the installation of dependencies." - fi - - # Attempt to identify the Linux distribution - if [ -f /etc/os-release ]; then - . /etc/os-release - DISTRO=$ID - else - echo "Unable to identify the operating system." + echo "Attempting to install required dependencies..." + + # Inform the user that the next steps require administrative access + echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." + + # Check if the script can execute sudo commands without interaction + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed with the installation of dependencies." + fi + + # Attempt to identify the Linux distribution + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO=$ID + else + echo "Unable to identify the operating system." + exit 1 + fi + + # Install dependencies based on the distribution + case "$DISTRO" in + ubuntu|debian|linuxmint) + echo "Detected an Ubuntu/Debian based distribution." + sudo apt update + sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + gstreamer1.0-tools + ;; + fedora|rhel|centos) + echo "Detected a Fedora/Red Hat based distribution." + sudo dnf install webkit2gtk3 gtk3 \ + gstreamer1-plugins-base gstreamer1-plugins-good + ;; + arch|manjaro) + echo "Detected an Arch Linux based distribution." + sudo pacman -Syu + sudo pacman -S webkit2gtk gtk3 + ;; + *) + echo "Unsupported distribution. Please manually install the required dependencies." exit 1 - fi - - # Install dependencies based on the distribution - case "$DISTRO" in - ubuntu|debian|linuxmint) - echo "Detected an Ubuntu/Debian based distribution." - sudo apt update - sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ - gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ - gstreamer1.0-tools - ;; - fedora|rhel|centos) - echo "Detected a Fedora/Red Hat based distribution." - sudo dnf install webkit2gtk3 gtk3 \ - gstreamer1-plugins-base gstreamer1-plugins-good - ;; - arch|manjaro) - echo "Detected an Arch Linux based distribution." - sudo pacman -Syu - sudo pacman -S webkit2gtk gtk3 - ;; - *) - echo "Unsupported distribution. Please manually install the required dependencies." - exit 1 - ;; - esac + ;; + esac } verify_and_install_dependencies() { - cd "$TMP_DIR/phoenix-code" - # Ensure the binary is executable - chmod +x "./phoenix-code" - # First attempt to verify the application launch - if ./phoenix-code --runVerify; then - echo "Application launch verification successful." - return 0 # Exit the function successfully if verification succeeds - else - echo "Initial verification failed. Attempting to install dependencies..." - install_dependencies # Function to install required dependencies - fi - - # Second attempt to verify the application launch after installing dependencies - if ./phoenix-code --runVerify; then - echo "Application launch verification successful after installing dependencies." - return 0 # Exit the function successfully if verification succeeds - else - echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." - return 1 # Return an error code to indicate failure - fi - cd - + cd "$TMP_DIR/phoenix-code" + # Ensure the binary is executable + chmod +x "./phoenix-code" + # First attempt to verify the application launch + if ./phoenix-code --runVerify; then + echo "Application launch verification successful." + return 0 # Exit the function successfully if verification succeeds + else + echo "Initial verification failed. Attempting to install dependencies..." + install_dependencies # Function to install required dependencies + fi + + # Second attempt to verify the application launch after installing dependencies + if ./phoenix-code --runVerify; then + echo "Application launch verification successful after installing dependencies." + return 0 # Exit the function successfully if verification succeeds + else + echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." + return 1 # Return an error code to indicate failure + fi + cd - } - -install() { - # Check if the application is already installed - if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then - echo "Phoenix Code appears to be already installed." - - # Prompt the user for input on whether to repair (reinstall) - read -p "Would you like to repair (reinstall) it? (y/N): " response - case "$response" in - [Yy]* ) - echo "Proceeding with the reinstallation..." - uninstall - ;; - * ) - echo "Installation aborted by the user." - exit 0 - ;; - esac - fi - cleanup() { - rm -rf "$TMP_DIR" # This will delete the temporary directory and all its contents, including latest_release.json - } - trap cleanup EXIT - - TMP_DIR=$(mktemp -d) - echo "Using temporary directory $TMP_DIR for processing" - - echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" - wget -qO "$TMP_DIR/latest_release.json" "$API_URL" || { - echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" - exit 1 - } - - CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') - echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" - - BEST_MATCH_URL="" - BEST_MATCH_VERSION=0 - echo "Searching for a compatible binary..." - - while read -r BINARY_URL; do - BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') - if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then - BEST_MATCH_URL="$BINARY_URL" - BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" - echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" - fi - done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") - - if [ -z "$BEST_MATCH_URL" ]; then - echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" - exit 1 - fi - - echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { - echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" - exit 1 - } - echo -e "${YELLOW}Downloading the icon...${RESET}" - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { - echo -e "${RED}Failed to download Icon${RESET}"; - exit 1; - } - echo "Extracting the binary to $TMP_DIR..." - tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { - echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" - exit 1 - } - - # Verify binary execution and install dependencies if necessary - if ! verify_and_install_dependencies; then - echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" - exit 1 - fi - - echo "Setting up the installation directory at $INSTALL_DIR..." - mkdir -p "$INSTALL_DIR" - mkdir -p "$DESKTOP_DIR" - - echo "Moving the necessary files to the installation directory..." - mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { - echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" - exit 1 - } - # Move the icon to the installation directory - mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" - - echo "Setting the correct permissions for the executable..." - chmod +x "$INSTALL_DIR/phoenix-code" || { - echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" - exit 1 - } - - mkdir -p "$LINK_DIR" # Ensure the directory exists - # Call the function to create and copy the invocation script - create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" - # Define MIME types for file extensions - MIME_TYPES="text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;" - # Add directory association - MIME_TYPES+="inode/directory;" - # Create a desktop entry for the application - echo "Creating desktop entry..." - cat > "$DESKTOP_ENTRY" < "$DESKTOP_ENTRY" < /dev/null; then + update-desktop-database "$DESKTOP_DIR" + fi + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi + fi + echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" + +} +downloadAndInstall(){ + cleanup() { + rm -rf "$TMP_DIR" # This will delete the temporary directory and all its contents, including latest_release.json + } + trap cleanup EXIT + + TMP_DIR=$(mktemp -d) + echo "Using temporary directory $TMP_DIR for processing" + + echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" + wget -qO "$TMP_DIR/latest_release.json" "$API_URL" || { + echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" + exit 1 + } + + CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') + echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" + + BEST_MATCH_URL="" + BEST_MATCH_VERSION=0 + echo "Searching for a compatible binary..." + + while read -r BINARY_URL; do + BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') + if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then + BEST_MATCH_URL="$BINARY_URL" + BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" + echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" + fi + done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") + + if [ -z "$BEST_MATCH_URL" ]; then + echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" + exit 1 + fi + + echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { + echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" + exit 1 + } + echo -e "${YELLOW}Downloading the icon...${RESET}" + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { + echo -e "${RED}Failed to download Icon${RESET}"; + exit 1; + } + echo "Extracting the binary to $TMP_DIR..." + tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { + echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" + exit 1 + } + + # Verify binary execution and install dependencies if necessary + if ! verify_and_install_dependencies; then + echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" + exit 1 + fi +} +install() { + # Check if the application is already installed + if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then + echo "Phoenix Code appears to be already installed." + + # Prompt the user for input on whether to repair (reinstall) + read -r -p "Would you like to repair (reinstall) it? (y/N): " response + case "$response" in + [Yy]* ) + echo "Proceeding with the reinstallation..." + uninstall + ;; + * ) + echo "Installation aborted by the user." + exit 0 + ;; + esac + fi + downloadAndInstall + copyFilesToDestination +} +upgrade() { + echo -e "${YELLOW}Starting upgrade of Phoenix Code...${RESET}" + + # Check if the application is installed + if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then + echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" + exit 1 + fi + + echo -e "${YELLOW}Proceeding with the upgrade...${RESET}" + + # You can call the downloadAndInstall function directly if you want to reuse the installation logic for upgrading + downloadAndInstall + uninstall + copyFilesToDestination + echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" +} + +uninstall() { + echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" + + # Remove the invocation script from ~/.local/bin + if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then + echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" + rm "$LINK_DIR/$SCRIPT_NAME" + else + echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" + fi + + # Delete the desktop entry + if [ -f "$DESKTOP_ENTRY" ]; then + echo -e "${YELLOW}Removing desktop entry...${RESET}" + rm "$DESKTOP_ENTRY" + # Update the desktop database for GNOME, Unity, XFCE, etc. - echo "Updating desktop database..." + echo -e "${YELLOW}Updating desktop database...${RESET}" if command -v update-desktop-database &> /dev/null; then update-desktop-database "$DESKTOP_DIR" fi @@ -226,55 +276,26 @@ EOF kbuildsycoca5 fi fi - echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" + else + echo -e "${RED}Desktop entry not found. Skipping...${RESET}" + fi + + # Remove the installation directory and its contents + if [ -d "$INSTALL_DIR" ]; then + echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" + rm -rf "$INSTALL_DIR" + else + echo -e "${RED}Installation directory not found. Skipping...${RESET}" + fi + echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" } -uninstall() { - echo "Starting uninstallation of Phoenix Code..." - - # Remove the invocation script from ~/.local/bin - if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then - echo "Removing invocation script from $LINK_DIR..." - rm "$LINK_DIR/$SCRIPT_NAME" - else - echo "Invocation script not found in $LINK_DIR. Skipping..." - fi - - # Delete the desktop entry - if [ -f "$DESKTOP_ENTRY" ]; then - echo "Removing desktop entry..." - rm "$DESKTOP_ENTRY" - - # Update the desktop database for GNOME, Unity, XFCE, etc. - echo "Updating desktop database..." - if command -v update-desktop-database &> /dev/null; then - update-desktop-database "$DESKTOP_DIR" - fi - - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 - fi - fi - else - echo "Desktop entry not found. Skipping..." - fi - - # Remove the installation directory and its contents - if [ -d "$INSTALL_DIR" ]; then - echo "Removing installation directory and its contents..." - rm -rf "$INSTALL_DIR" - else - echo "Installation directory not found. Skipping..." - fi - - echo "Uninstallation of Phoenix Code completed." -} # Check for command-line arguments if [[ "$1" == "--uninstall" ]]; then uninstall +elif [[ "$1" == "--upgrade" ]]; then + upgrade else install fi From 4b218905ea068ee5368bc4e142d9aeed62cd63c0 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 17 Feb 2024 13:52:53 +0530 Subject: [PATCH 354/864] feat: adding support for help --- docs/linux/installer.sh | 81 +++++++++++++++++++++++++++++++---------- 1 file changed, 62 insertions(+), 19 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 4606ecd8..6234f095 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -17,6 +17,13 @@ YELLOW="\e[33m" RED="\e[31m" RESET="\e[0m" +cleanup() { + rm -rf "$TMP_DIR" # This will delete the temporary directory and all its contents, including latest_release.json +} +trap cleanup EXIT + +TMP_DIR=$(mktemp -d) + create_invocation_script() { local binary_path="$1" local script_name="$2" @@ -144,28 +151,37 @@ EOF # Update the KDE desktop database if KDE is in use if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 - fi + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi fi echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" } -downloadAndInstall(){ - cleanup() { - rm -rf "$TMP_DIR" # This will delete the temporary directory and all its contents, including latest_release.json - } - trap cleanup EXIT - - TMP_DIR=$(mktemp -d) - echo "Using temporary directory $TMP_DIR for processing" +downloadLatestReleaseInfo() { + local release_info_file="$TMP_DIR/latest_release.json" + + if [ -f "$release_info_file" ]; then + echo "Latest release information has already been fetched." + # Extract and print the latest version from the JSON file for logging purposes + LATEST_VERSION=$(grep -Po '"tag_name": "\K.*?(?=")' "$release_info_file") + echo "Latest available version: $LATEST_VERSION" + return # Skip downloading if already done + fi echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" - wget -qO "$TMP_DIR/latest_release.json" "$API_URL" || { + wget -qO "$release_info_file" "$API_URL" || { echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" exit 1 } + # After successful download, extract and print the latest version for logging purposes + LATEST_VERSION=$(grep -Po '"tag_name": "\K.*?(?=")' "$release_info_file") + echo "Latest available version: $LATEST_VERSION" +} +downloadAndInstall(){ + echo "Using temporary directory $TMP_DIR for processing" + downloadLatestReleaseInfo CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" @@ -290,12 +306,39 @@ uninstall() { echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" } - -# Check for command-line arguments -if [[ "$1" == "--uninstall" ]]; then +show_help() { + echo "Usage: $0 [OPTION]" + echo "Install, upgrade, or uninstall Phoenix Code." + echo + echo "Options:" + echo " -h, --help Display this help and exit" + echo " --uninstall Uninstall Phoenix Code" + echo " --upgrade Upgrade Phoenix Code to the latest version" + echo + echo "Without any options, the script will install Phoenix Code." +} +case "$1" in + -h|--help) + show_help + exit 0 + ;; + --uninstall) uninstall -elif [[ "$1" == "--upgrade" ]]; then + exit 0 + ;; + --upgrade) upgrade -else - install -fi + exit 0 + ;; + "") + # No option was provided; proceed with install + ;; + *) + echo -e "${RED}Invalid option: $1${RESET}" + echo "Only '--uninstall', '--upgrade', or no option (for default installation) are valid." + exit 1 # Exit if an invalid option is provided + ;; +esac + +# If no option is provided, proceed with the installation +install From a53918c4c444673c0a8db3d1e8b7c5f76d8f6e01 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 17 Feb 2024 14:37:00 +0530 Subject: [PATCH 355/864] feat: version check during upgrade --- docs/linux/installer.sh | 45 ++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 6234f095..453c6361 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -162,26 +162,25 @@ downloadLatestReleaseInfo() { local release_info_file="$TMP_DIR/latest_release.json" if [ -f "$release_info_file" ]; then - echo "Latest release information has already been fetched." - # Extract and print the latest version from the JSON file for logging purposes - LATEST_VERSION=$(grep -Po '"tag_name": "\K.*?(?=")' "$release_info_file") - echo "Latest available version: $LATEST_VERSION" - return # Skip downloading if already done + # Only extract and echo the version number, without any additional messages + grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" + return fi - echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" + # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly + >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" wget -qO "$release_info_file" "$API_URL" || { - echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" + >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" exit 1 } - # After successful download, extract and print the latest version for logging purposes - LATEST_VERSION=$(grep -Po '"tag_name": "\K.*?(?=")' "$release_info_file") - echo "Latest available version: $LATEST_VERSION" + # Only extract and echo the version number after successful download + grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" } + downloadAndInstall(){ echo "Using temporary directory $TMP_DIR for processing" - downloadLatestReleaseInfo + downloadLatestReleaseInfo > /dev/null CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" @@ -247,21 +246,29 @@ install() { copyFilesToDestination } upgrade() { - echo -e "${YELLOW}Starting upgrade of Phoenix Code...${RESET}" + echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" - # Check if the application is installed + # Ensure Phoenix Code is installed if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" exit 1 fi + # Get the current installed version + CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) + echo "Current installed version: $CURRENT_VERSION" - echo -e "${YELLOW}Proceeding with the upgrade...${RESET}" + LATEST_VERSION=$(downloadLatestReleaseInfo) + # Now LATEST_VERSION should only contain the version number without extra messages + echo "Latest available version: $LATEST_VERSION" + + # Compare versions and upgrade if the latest version is greater + if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then + echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" + # Proceed with upgrade logic here + else + echo "Your Phoenix Code installation is up-to-date." + fi - # You can call the downloadAndInstall function directly if you want to reuse the installation logic for upgrading - downloadAndInstall - uninstall - copyFilesToDestination - echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" } uninstall() { From fd5979514c14cdd4690309438ecdf7309affa5c6 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 17 Feb 2024 14:57:28 +0530 Subject: [PATCH 356/864] chore: harden bash script --- docs/linux/installer.sh | 44 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 453c6361..4645488d 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -e # Exit immediately if a command exits with a non-zero status. +set -euo pipefail # Exit immediately if a command exits with a non-zero status. # Define common variables DESKTOP_DIR=$HOME/.local/share/applications GITHUB_REPO="charlypa/phoenix-desktop" @@ -227,24 +227,29 @@ downloadAndInstall(){ install() { # Check if the application is already installed if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then - echo "Phoenix Code appears to be already installed." + echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" - # Prompt the user for input on whether to repair (reinstall) - read -r -p "Would you like to repair (reinstall) it? (y/N): " response + # Update the prompt to inform the user about the repair behavior with color + echo -e "${YELLOW}The repair option will download and install the latest version available, replacing the current version.${RESET}" + read -r -p "Would you like to proceed with the repair? (y/N): " response case "$response" in [Yy]* ) - echo "Proceeding with the reinstallation..." + echo -e "${GREEN}Proceeding with the repair by installing the latest version...${RESET}" uninstall + downloadAndInstall + copyFilesToDestination ;; * ) - echo "Installation aborted by the user." + echo -e "${RED}Repair aborted by the user.${RESET}" exit 0 ;; esac + else + downloadAndInstall + copyFilesToDestination fi - downloadAndInstall - copyFilesToDestination } + upgrade() { echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" @@ -324,28 +329,25 @@ show_help() { echo echo "Without any options, the script will install Phoenix Code." } -case "$1" in +case "${1-}" in -h|--help) - show_help - exit 0 + show_help # Function to show help ;; --uninstall) - uninstall - exit 0 + uninstall # Function to uninstall ;; --upgrade) - upgrade - exit 0 + upgrade # Function to upgrade ;; "") - # No option was provided; proceed with install + # This case handles when $1 is unset (acts as a default action) + install # Function to install ;; *) - echo -e "${RED}Invalid option: $1${RESET}" - echo "Only '--uninstall', '--upgrade', or no option (for default installation) are valid." - exit 1 # Exit if an invalid option is provided + # This case handles unexpected arguments + echo "Invalid option: $1" >&2 + show_help # Assuming you have a function to show usage information + exit 1 ;; esac -# If no option is provided, proceed with the installation -install From a59cf1f92aade09b7b7844262405a4db99285012 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 17 Feb 2024 16:52:58 +0530 Subject: [PATCH 357/864] doc: updating doccumentaion --- docs/linux/installer.sh | 336 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 331 insertions(+), 5 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 4645488d..c5078505 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -17,20 +17,90 @@ YELLOW="\e[33m" RED="\e[31m" RESET="\e[0m" +# Cleanup Function +# +# Purpose: +# The cleanup function is designed to ensure that the script cleans up any temporary +# resources it used during its execution. Specifically, it removes the temporary directory +# created at the beginning of the script, along with all its contents. This is crucial for +# maintaining a clean file system and avoiding the accumulation of unused files. +# +# Behavior: +# - The function targets a temporary directory specified by the `$TMP_DIR` variable. +# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. +# This includes any temporary files, downloaded assets, or other data generated during the script's execution. +# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes +# automatically when the script exits, regardless of the exit point. This includes normal completion, +# errors, or manual termination via signals like SIGINT (Ctrl+C). +# +# Considerations: +# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. +# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. +# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` +# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. +# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within +# `$TMP_DIR` is expendable and safe to delete. +# +# Usage: +# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` +# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` +# is correctly set to the temporary directory path before invoking the function. +# cleanup() { - rm -rf "$TMP_DIR" # This will delete the temporary directory and all its contents, including latest_release.json + rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. } -trap cleanup EXIT + +trap cleanup EXIT # Register the cleanup function to be called on script exit. + TMP_DIR=$(mktemp -d) +# Create Invocation Script Function +# +# Purpose: +# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. +# This script is intended to simplify the execution of Phoenix Code by providing a more accessible +# command interface. The generated script is placed in a user-accessible binary directory, making it +# possible to run Phoenix Code from anywhere in the system without needing to specify the full path +# to the binary. +# +# Parameters: +# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. +# - script_name: The name to be given to the invocation script. This name is used both for the +# script file itself and for the symlink created in the user's binary directory. +# - link_dir: The directory where a symlink to the invocation script will be placed, typically +# a location in the user's PATH, such as ~/.local/bin, for easy access. +# +# Behavior: +# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. +# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a +# command to execute the Phoenix Code binary with any passed arguments ("$@"). +# 3. Sets executable permissions on the newly created script. +# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. +# +# Considerations: +# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' +# does not conflict with existing files in these directories to prevent unintended overwrites. +# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes +# these directories are already created and accessible. +# - The generated script includes a warning comment advising against deletion, as it is +# essential for the proper functioning of Phoenix Code when invoked through this script. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# after the binary has been placed in its final location. It should not be called arbitrarily, as it +# assumes a specific setup and context established by the installer script. +# create_invocation_script() { local binary_path="$1" local script_name="$2" local link_dir="$3" echo "Creating an invocation script for the binary..." + # Start of the generated script echo "#!/bin/bash" > "$binary_path/$script_name.sh" + # Add a warning comment about the script being auto-generated + echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name.sh" echo "$binary_path/$script_name \"\$@\"" >> "$binary_path/$script_name.sh" chmod +x "$binary_path/$script_name.sh" @@ -38,6 +108,38 @@ create_invocation_script() { mkdir -p "$link_dir" # Ensure the directory exists cp "$binary_path/$script_name.sh" "$link_dir/$script_name" } +# Install Dependencies Function +# +# Purpose: +# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. +# This function identifies the user's Linux distribution and installs the appropriate packages +# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and +# Arch Linux distributions. +# +# Behavior: +# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. +# If the command fails, it prompts the user to enter their password for `sudo` access. +# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. +# 3. Based on the identified distribution, executes the appropriate package manager command +# with the required packages. Supported package managers are `apt` for Debian-based systems, +# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. +# 4. Updates the package index (if applicable) and installs the packages. +# +# Considerations: +# - The function requires internet access to fetch package information and install packages. +# - It assumes that the user has `sudo` privileges to install packages system-wide. +# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, +# this function must be updated accordingly. +# - Unsupported distributions will result in an error message and termination of the script, +# as the required dependencies cannot be installed automatically. +# - This function does not handle potential errors from package installation commands. It's +# recommended to monitor the output for any issues that may require manual intervention. +# +# Usage: +# This function is intended to be called during the Phoenix Code installation process, typically +# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites +# are met for a successful Phoenix Code execution. +# install_dependencies() { echo "Attempting to install required dependencies..." @@ -83,6 +185,46 @@ install_dependencies() { ;; esac } +# Verify and Install Dependencies Function +# +# Purpose: +# This function is responsible for verifying if the Phoenix Code application can be successfully +# launched with the current set of installed dependencies. If the initial verification fails, it +# attempts to install the necessary dependencies and then re-verifies the application launch. +# +# Behavior: +# 1. Changes the current directory to the temporary directory where Phoenix Code is located. +# 2. Sets the executable permission for the Phoenix Code binary and attempts to run it with a +# verification-specific command (e.g., `--runVerify`). This step is intended to check if the +# application can start without installing additional dependencies. +# 3. If the initial verification succeeds, the function exits with a success status (0), indicating +# no further action is needed. +# 4. If the initial verification fails, the function proceeds to invoke `install_dependencies` to +# install any missing dependencies specific to the user's Linux distribution. +# 5. After installing dependencies, it attempts to verify the application launch again. If this +# second attempt succeeds, the function exits with a success status (0). +# 6. If the verification fails even after installing dependencies, the function prints an error +# message advising the user to check the application requirements or contact support, and +# exits with an error status (1). +# 7. Finally, the function ensures to change back to the original directory where the script was +# invoked, preserving the user's shell environment. +# +# Considerations: +# - The function assumes that the Phoenix Code binary is located in a temporary directory and +# that this directory is correctly set in the `$TMP_DIR` variable. +# - It relies on the Phoenix Code binary supporting a `--runVerify` command or equivalent for +# verification purposes. If such a command is not available, this part of the function needs +# adjustment. +# - Dependency installation requires administrative privileges; hence, the user might be prompted +# for a password to allow `sudo` operations. +# - The function does not handle all possible error scenarios during dependency installation. +# Users should monitor the output for potential issues that might need manual intervention. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# before finalizing the installation, to ensure that all system requirements are met for the +# application to run properly. +# verify_and_install_dependencies() { cd "$TMP_DIR/phoenix-code" # Ensure the binary is executable @@ -106,6 +248,46 @@ verify_and_install_dependencies() { fi cd - } + +# Copy Files to Destination Function +# +# Purpose: +# This function is responsible for setting up the final installation directory for Phoenix Code, +# moving the necessary files into place, creating the invocation script, and setting up the desktop +# entry for the application. It ensures that all components of Phoenix Code are correctly installed +# and configured in the user's environment. +# +# Behavior: +# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files +# will reside. +# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. +# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from +# the temporary directory (`$TMP_DIR`) to the installation directory. +# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. +# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. +# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. +# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and +# launchers, and places this file in the desktop entry directory. +# 8. Updates the system's desktop database to ensure the new application entry is recognized and available +# in application menus and launchers. This step might involve commands like `update-desktop-database` +# or `kbuildsycoca5`, depending on the desktop environment. +# +# Considerations: +# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and +# that this directory is correctly set. +# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and +# accessible. If these variables are unset or incorrect, the function may not perform as intended. +# - Administrative privileges may be required for certain operations, such as updating the desktop database +# or setting permissions, depending on the system's configuration. +# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function +# does perform significant file system operations that could potentially conflict with existing user data +# or system settings. +# +# Usage: +# This function is intended to be called as part of the Phoenix Code installation process, after the +# application's binary and other necessary files have been prepared in a temporary location. It finalizes +# the installation by placing all components in their appropriate locations within the user's system. +# copyFilesToDestination(){ echo "Setting up the installation directory at $INSTALL_DIR..." mkdir -p "$INSTALL_DIR" @@ -178,6 +360,45 @@ downloadLatestReleaseInfo() { grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" } +# Download Latest Release Information Function +# +# Purpose: +# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function +# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to +# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. +# +# Behavior: +# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary +# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already +# been fetched and proceeds to extract the version number from this file without re-downloading. +# 2. If the release information file does not exist, the function uses `wget` to download the JSON data +# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint +# of the Phoenix Code GitHub repository. +# 3. The JSON data is saved to `latest_release.json` in the temporary directory. +# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular +# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version +# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number +# portion. +# 5. Echoes the extracted version number for use by the calling context. +# +# Considerations: +# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available +# in the execution environment. +# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code +# repository for this function to work as intended. +# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, +# the `grep` pattern used to extract the version number may need to be updated. +# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an +# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the +# latest release information. +# - The function does not perform error handling for the `wget` command. If the download fails, the script may +# exit or behave unexpectedly depending on the `set -e` setting. +# +# Usage: +# This function is intended to be called during the installation or upgrade process to determine the latest +# version of Phoenix Code. The extracted version number can be used to compare with the currently installed +# version and decide whether an upgrade is necessary. +# downloadAndInstall(){ echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null @@ -224,6 +445,41 @@ downloadAndInstall(){ exit 1 fi } +# Install Function +# +# Purpose: +# Facilitates the entire installation process of Phoenix Code on the user's system. This includes +# checking for previous installations, downloading and installing the latest version, setting up +# necessary directories, and ensuring that all dependencies are met. It also handles user prompts +# for repair or reinstallation options if Phoenix Code is already installed. +# +# Behavior: +# 1. Checks if Phoenix Code is already installed by looking for specific files or directories +# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main +# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). +# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and +# then reinstalls the application, ensuring the user ends up with the latest version. +# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest +# release and install it. This step involves downloading the binary, setting permissions, and +# moving files to their correct locations. +# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, +# create an invocation script, and perform other necessary post-installation configurations. +# +# Considerations: +# - The function assumes that the user has sufficient permissions to write to the target directories +# and install Phoenix Code. Administrative privileges may be required for certain operations. +# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation +# directory will be replaced. Users should ensure that any custom configurations or data are backed up +# before proceeding. +# - Network connectivity is required to download the latest version of Phoenix Code from the repository. +# - The function does not explicitly handle all potential error scenarios, such as download failures or +# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. +# +# Usage: +# This function is intended to be invoked when the script is run without specific options (e.g., not an +# uninstall or upgrade). It can be directly called from the command line when the user wishes to install +# Phoenix Code, or it may be triggered by default when the script is executed without arguments. +# install() { # Check if the application is already installed if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then @@ -249,7 +505,43 @@ install() { copyFilesToDestination fi } - +# Upgrade Function +# +# Purpose: +# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated +# to the latest version available. This function checks the currently installed version against +# the latest version available in the GitHub repository. If a newer version is found, it proceeds +# to download and install the update, effectively replacing the old version with the new one. +# +# Behavior: +# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation +# directory and the invocation script. If not found, it exits with an error message indicating that +# Phoenix Code must be installed before it can be upgraded. +# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version +# check command (e.g., `phoenix-code --version`) and captures the output. +# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` +# function, which retrieves the version number of the latest release. +# 4. Compares the currently installed version with the latest version. If the installed version is older, +# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and +# installation of the new version. +# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. +# +# Considerations: +# - The function relies on the correct implementation of version checking in the Phoenix Code binary. +# The binary must support a command-line option to output its version, and the output format must be +# consistent for correct parsing and comparison. +# - Network connectivity is required to fetch the latest release information from the GitHub repository. +# The upgrade process will fail if the script cannot connect to GitHub. +# - The user must have sufficient permissions to overwrite the existing installation files and to +# execute network requests (e.g., downloading the latest release). +# - The upgrade process replaces the existing installation files. Users should ensure that any +# necessary backups or custom configurations are saved before proceeding with the upgrade. +# +# Usage: +# This function is intended to be called when the user explicitly wants to upgrade their installation +# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the +# script, as defined in the script's main case statement handling command-line arguments. +# upgrade() { echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" @@ -275,7 +567,42 @@ upgrade() { fi } - +# Uninstall Function +# +# Purpose: +# Handles the removal of Phoenix Code from the user's system. This function is responsible for +# cleaning up all files, directories, and links created during the installation process, effectively +# reverting any changes made by the installer script. It ensures that Phoenix Code and its components +# are uninstalled cleanly, leaving no residual files or configurations. +# +# Behavior: +# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). +# This step prevents the Phoenix Code command from being accessible after uninstallation. +# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus +# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. +# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. +# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. +# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including +# the main binary, configuration files, and any other related files placed during installation. +# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. +# +# Considerations: +# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately +# reflect the locations used during the installation. If these variables are incorrect, the uninstallation +# process may not remove all components. +# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed +# in system-wide directories. +# - Users should be advised to back up any important data or configurations related to Phoenix Code before +# initiating the uninstallation process, as this function will remove all associated files without recovery options. +# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot +# be reversed through this script. +# +# Usage: +# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. +# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement +# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this +# function is executed to prevent accidental data loss. +# uninstall() { echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" @@ -350,4 +677,3 @@ case "${1-}" in exit 1 ;; esac - From f173f0321f5cc374b5e4eaa736658c4c3a1ba0e6 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 18 Feb 2024 17:32:13 +0530 Subject: [PATCH 358/864] chore: wraper script name to phcode --- docs/linux/installer.sh | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index c5078505..6400a42b 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -9,7 +9,8 @@ INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries DESKTOP_ENTRY="$DESKTOP_DIR/PhoenixCode.desktop" -SCRIPT_NAME="phoenix-code" # Name of the script to invoke the binary +SCRIPT_NAME="phcode" # Name of the script to invoke the binary +BINARY_NAME="phoenix-code" # Define color variables for easy reference GREEN="\e[32m" @@ -100,13 +101,13 @@ create_invocation_script() { # Start of the generated script echo "#!/bin/bash" > "$binary_path/$script_name.sh" # Add a warning comment about the script being auto-generated - echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name.sh" - echo "$binary_path/$script_name \"\$@\"" >> "$binary_path/$script_name.sh" - chmod +x "$binary_path/$script_name.sh" + echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" + echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" + chmod +x "$binary_path/$script_name" echo "Copying the invocation script to $link_dir..." mkdir -p "$link_dir" # Ensure the directory exists - cp "$binary_path/$script_name.sh" "$link_dir/$script_name" + cp "$binary_path/$script_name" "$link_dir/$script_name" } # Install Dependencies Function # @@ -241,12 +242,13 @@ verify_and_install_dependencies() { # Second attempt to verify the application launch after installing dependencies if ./phoenix-code --runVerify; then echo "Application launch verification successful after installing dependencies." + cd - return 0 # Exit the function successfully if verification succeeds else echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." + cd - return 1 # Return an error code to indicate failure fi - cd - } # Copy Files to Destination Function @@ -505,6 +507,10 @@ install() { copyFilesToDestination fi } +function uninstallBetaAppImage() { + rm -f "$LINK_DIR"/phcode + rm -f "$LINK_DIR"/phoenix_icon.png +} # Upgrade Function # # Purpose: @@ -561,7 +567,10 @@ upgrade() { # Compare versions and upgrade if the latest version is greater if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" - # Proceed with upgrade logic here + downloadAndInstall + uninstall + copyFilesToDestination + echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" else echo "Your Phoenix Code installation is up-to-date." fi @@ -606,6 +615,7 @@ upgrade() { uninstall() { echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" + uninstallBetaAppImage # Remove the invocation script from ~/.local/bin if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" From e47cb98596559eb2079969f1e6127f01545670a1 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 18 Feb 2024 18:41:52 +0530 Subject: [PATCH 359/864] chore: code clean up --- docs/linux/installer.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 6400a42b..4b009d34 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -2,7 +2,7 @@ set -euo pipefail # Exit immediately if a command exits with a non-zero status. # Define common variables DESKTOP_DIR=$HOME/.local/share/applications -GITHUB_REPO="charlypa/phoenix-desktop" +GITHUB_REPO="phcode-dev/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" INSTALL_DIR="$HOME/.phoenix-code" @@ -507,8 +507,8 @@ install() { copyFilesToDestination fi } +# Temporary code to clean up earlier beta installations function uninstallBetaAppImage() { - rm -f "$LINK_DIR"/phcode rm -f "$LINK_DIR"/phoenix_icon.png } # Upgrade Function @@ -614,7 +614,6 @@ upgrade() { # uninstall() { echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" - uninstallBetaAppImage # Remove the invocation script from ~/.local/bin if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then From 2951e63068ba265d43e0a600acd6cbadc7879929 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 19 Feb 2024 10:43:40 +0530 Subject: [PATCH 360/864] chore: add updater window to access tauri api --- src-tauri/tauri.conf.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 76755efd..2c8cfcde 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -234,6 +234,7 @@ ], "windows": [ "main", + "updater", "phcode-1", "phcode-2", "phcode-3", @@ -305,6 +306,7 @@ ], "windows": [ "main", + "updater", "phcode-1", "phcode-2", "phcode-3", From e20e912f36fd67a0bd357119281540dbca8a427f Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 19 Feb 2024 11:12:04 +0530 Subject: [PATCH 361/864] fix: update timestamp url to global sign --- src-tauri/tauri.conf.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2c8cfcde..ffb01b24 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -144,7 +144,7 @@ "windows": { "certificateThumbprint": "AB7D19C00251C1E412594A28DC79D201AAEF50D0", "digestAlgorithm": "sha256", - "timestampUrl": "http://timestamp.comodoca.com", + "timestampUrl": "http://timestamp.globalsign.com/tsa/advanced", "nsis": { "displayLanguageSelector": true, "license": "./license/agpl", @@ -410,4 +410,4 @@ } ] } -} \ No newline at end of file +} From 040e16eddb1793942c622c79e342d6aebf725239 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Tue, 20 Feb 2024 04:47:13 +0000 Subject: [PATCH 362/864] ci: update phcode version to 3.3.6 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 64fcbf97..6872c946 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.5", + "version": "3.3.6", "type": "module", "scripts": { "tauri": "tauri", @@ -53,6 +53,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "05da456e0db5755ba87118f313c929d18aa9bfff" + "commit": "1ded50f42cb3289bf9319649a4953ca87f8df5c2" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3b2320f6..bd3d06a3 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.5" +version = "3.3.6" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ffb01b24..b23bd2ca 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.5" + "version": "3.3.6" }, "tauri": { "allowlist": { @@ -410,4 +410,4 @@ } ] } -} +} \ No newline at end of file From 935521ce039649ff998f4305088132f8a0eedcb6 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 20 Feb 2024 06:09:27 +0000 Subject: [PATCH 363/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 152f8717..669d39cc 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.3.4", - "notes": "Take a look at the assets to download and install Phoenix Code For your platform.\r\n\r\n## A heading\r\n\r\nThis is a title.\r\n![An image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/d8b3c5b9-ec5b-41d0-8283-0dc318a450ec)\r\n\r\nplease share your thoughts and feedback @ [GitHub issues page](https://github.com/phcode-dev/phoenix/issues/new/choose).\r\n\r\n## 🚀 Mac (Intel/M1) DMGs 🚀\r\nM1/Apple silicon macs: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_aarch64.dmg\r\nIntel Macs: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_x64.dmg\r\n\r\n## 🚀 Windows Installers 🚀\r\nWindows installers will be avilable soon...\r\n\r\n## 🚀 Exciting News: Our First Linux Beta Build! 🚀\r\n\r\n**🔧 Installation Instructions**\r\nTo dive into the Linux beta version, simply execute the following command in your terminal:\r\n```bash\r\n# install libfuse2 in ubuntu, else ignore this step\r\nsudo apt-get install libfuse2\r\n\r\nwget -qO- https://updates.phcode.io/linux/installer.sh | bash\r\n```\r\n\r\n**🗑️ Uninstallation**\r\nIf you need to uninstall the beta version, please use the following command:\r\n```bash\r\nwget -qO- https://updates.phcode.io/linux/installer.sh | bash -s -- --uninstall\r\n```\r\n", - "pub_date": "2024-02-13T09:52:05.845Z", + "version": "3.3.6", + "notes": "Testing experimental builds. Do not download!", + "pub_date": "2024-02-20T05:56:39.987Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZaTmZOQjBXRStCYVBrVnFORWI2S1czU2dMM29sWDEvamZlZHBHZm9PSHlEdk5HSW4zTkRVTEdGakZreGhhdkJDTG9mc0dCbzNLdlhHTG1RNFRrTkFJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3ODE0OTk3CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuNF9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKNXQwYXlHMWJlZWRhNmI5VDNuK1drWjNKUUFSL0FhU2dRTW5SZWR0RVIzaXIrMXBSbmd2MEVGT0ZmQWkyTXVGbTdXMllETEs1TnF3U1l1WGRQR3BNQ3c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.4/phoenix-code-experimental-build_3.3.4_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlaWFB5VFNqVDVLWmlBOGdqckV1amkwYUFDdVU1eXhPa2hIQ3R6OVJsMUNReTVwUU9XamNHak55OURHdFJITUlGSVlOcmRWbm5CZ0FOeVpGUDFvZWdzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDA3ODE5CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuNl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKZFVFUnYzSkRyRUNCb2RWd2JGSDVyb0x2bk5VdCt6TGdGeFFhbm52b3pUdnNQK1JOcTNxWll1TG5zcmxremlLSk94UFJoSC9XcG9zQURIUndOT2hPQkE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.6/phoenix-code-experimental-build_3.3.6_amd64.AppImage.tar.gz" + }, + "windows-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhCWlRZQm1JT0ZaSmV2S2VlOUFYWkw2WXFSNGd4M2pSVmdQb3dmeC9GdjdVMmdnaHpqdmozeTBmbnBYTm4vMXNJaFVseHc3UzhhYXp2NHdZSlI1Z0FBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDA3ODY1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuNl94NjQtc2V0dXAubnNpcy56aXAKdXY3RXBFbzhldWUrQjRYRGF1WFUzd1Z4NTNuWm5td01nYWduRFBvQ1dXUmM4MFhtc28xdEludTVTTzFoVUszTEtrM3krLzZFNjViMTh0RUJuMDdZQkE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.6/Phoenix.Code.Experimental.Build_3.3.6_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnM5aE9CRGVKUmJwTE1zbERqS0IvZjJNWGJheXlYaHZlOEhJazRWdVhSdnRBQStlQjZtREZubmtmR1AxZE5hYm1HenNQUjZPR0JnZTV3WlV6UWlPb0F3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3ODE1OTEzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClB3TTQ4UFhIZHFiNlk3WDNrSGZXVVBFRERLRld1ZVNIYkZuWGMwNDV2YmdNRzUrYVBNdzZMYnk4U3ByTldXek54THNMcjNnaWVpdm5iOFB2ZmF1dENnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.4/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9VUEozZURVdWtUdms2VDl3N1FuL0FJR1h6TmZVTEJMRmhOL2ttU05XZVc5cFVaVWo3b0NTTzJ2UnBhYm9mY1AwSEdFZkc0NytVZlJtMkZvMldSaFFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDA4MTQyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClRXcjMxSXdFblNSTHkvL0Z0ODNSWXlENFAxd2FnZzQxWmxUK0hCbzAyRXZwOHhiY0Zra0VJY280T3k4T0VYZ1kxQ1dwdmlJVXFnNnc2dGNsQTFqU0FRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.6/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmpQcGlvUWgrOWVWVEJXVlMxQ2VsNzBVODVzWXJRZTArVzVWd1dKNStIdmpXSHNsaFBUS3p5Wk9rVlRpRnYwUHp6aTBXa3NQU25SZUsvck43cUZvZ1FzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3ODE2NzY5CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjRqWGpnWFZ1R1ZoK09pSXhJVVVKQ2N3a3orUUVVUEtpdVhHSjhjaExzcEJYeFV2bmFyRXNROEErY1YyTkxxL3FVNFpucVphR1g3Z1hEckUxSngwTERnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.4/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" - }, - "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhzSWg2Wnk0QTJXd1o3Y1FvZE1RL2hOd0hncGNHbTNEWC82a3dObmdsOGRBTXB2RHZBbXZoZTRPRnNLakVyU2FRc1hZdVFkNVE2Znl6QzRDbnRWRndNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3ODE3OTIxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuNF94NjQtc2V0dXAubnNpcy56aXAKVTBxaGozVTNnNzJmMmJoa21MYjVrekxVNWd5K2ZFdHJ3R0oyUnVIdUpGbWg3b2VOVWlwOXVnTGJYaFJQdmJEZ3o5bmwzRHlsWjFLQk9OR0h4MUt0QkE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.4/Phoenix.Code.Experimental.Build_3.3.4_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnM4bDQ5YlQ5TFF5U3plUFA0SDlxZk1xNTErbE8wZkszNkxrVUZYcWxPMmxGbUFXeEU0dFdodmNxdEc1cHN0YVdSS3VsVkoyNEdYOU5jaDlDUTlHTkFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDA4NTkwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Ckk4bDZyZzFxbG9LSlFmbDNOa1dlU0x1bVFkdStSOGovSU5sU09xRnpsN2tQc1pVbW5oRHVuTXRDSW94bWhhbWdSWHV3bzU0bWZsRGtRT2JZSmZtOEFRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.6/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 03fb1aa080761234f9a71aa8765241da8a6e9bc5 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 20 Feb 2024 13:14:56 +0530 Subject: [PATCH 364/864] feat: add linux app upgrade command --- src-tauri/Cargo.lock | 2 +- src-tauri/tauri.conf.json | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 6ca15a5c..fef394b6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2742,7 +2742,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.3.5" +version = "3.3.6" dependencies = [ "clipboard-files", "fix-path-env", diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index b23bd2ca..87de3cf4 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -76,6 +76,11 @@ "validator": "\\S*" } ] + }, + { + "name": "run-update-linux-command", + "cmd": "x-terminal-emulator", + "args": ["-e", "wget -qO- https://updates.phcode.io/linux/installer.sh | bash -s -- --upgrade"] } ] } From 010bb05c427af13419bcd0e19006b8217e128404 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 19 Feb 2024 16:43:17 +0530 Subject: [PATCH 365/864] fix: files were not associated as default in ubuntu --- docs/linux/installer.sh | 52 +++++++++++++++++++++++++++++++++++------ 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 4b009d34..236ca535 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -8,10 +8,40 @@ ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries -DESKTOP_ENTRY="$DESKTOP_DIR/PhoenixCode.desktop" +DESKTOP_ENTRY_NAME="PhoenixCode.desktop" +DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" SCRIPT_NAME="phcode" # Name of the script to invoke the binary BINARY_NAME="phoenix-code" +declare -a MIME_TYPES=( + "text/html" + "application/atom+xml" + "application/x-coldfusion" + "text/x-clojure" + "text/coffeescript" + "application/json" + "text/css" + "text/x-diff" + "text/jsx" + "text/markdown" + "application/mathml+xml" + "application/rdf+xml" + "application/rss+xml" + "application/sql" + "image/svg+xml" + "text/x-python" + "application/xml" + "application/vnd.mozilla.xul+xml" + "application/x-yaml" + "text/javascript" + "application/javascript" + "text/mjs" + "application/mjs" + "text/cjs" + "inode/directory" # Added to include directory handling +) + + # Define color variables for easy reference GREEN="\e[32m" YELLOW="\e[33m" @@ -250,6 +280,15 @@ verify_and_install_dependencies() { return 1 # Return an error code to indicate failure fi } +# Set Phoenix Code as the default application for specified MIME types +set_default_application() { + local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file + + for mime_type in "${MIME_TYPES[@]}"; do + xdg-mime default "$desktop_file" "$mime_type" + done + echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" +} # Copy Files to Destination Function # @@ -312,11 +351,8 @@ copyFilesToDestination(){ mkdir -p "$LINK_DIR" # Ensure the directory exists # Call the function to create and copy the invocation script create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" - # Define MIME types for file extensions - MIME_TYPES="text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;" - # Add directory association - MIME_TYPES+="inode/directory;" - # Create a desktop entry for the application + # Convert MIME types array to semicolon-separated string for the desktop entry + MIME_TYPES_STRING=$(IFS=";"; echo "${MIME_TYPES[*]}") echo "Creating desktop entry..." cat > "$DESKTOP_ENTRY" < Date: Mon, 19 Feb 2024 20:31:19 +0530 Subject: [PATCH 366/864] feat: adding more messages to show newly created files --- docs/linux/installer.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 236ca535..2e017d24 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -138,6 +138,8 @@ create_invocation_script() { echo "Copying the invocation script to $link_dir..." mkdir -p "$link_dir" # Ensure the directory exists cp "$binary_path/$script_name" "$link_dir/$script_name" + + echo -e "${YELLOW}Invocation script created at: $link_dir/$script_name${RESET}" } # Install Dependencies Function # @@ -333,8 +335,10 @@ copyFilesToDestination(){ echo "Setting up the installation directory at $INSTALL_DIR..." mkdir -p "$INSTALL_DIR" mkdir -p "$DESKTOP_DIR" + echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" echo "Moving the necessary files to the installation directory..." + echo -e "${YELLOW}Phoenix Code files moved to: $INSTALL_DIR${RESET}" mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" exit 1 @@ -347,6 +351,7 @@ copyFilesToDestination(){ echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" exit 1 } + echo -e "${YELLOW}Executable permissions set for: $INSTALL_DIR/$BINARY_NAME${RESET}" mkdir -p "$LINK_DIR" # Ensure the directory exists # Call the function to create and copy the invocation script @@ -363,10 +368,12 @@ Icon=$INSTALL_DIR/icon.png Terminal=false MimeType=$MIME_TYPES_STRING; EOF + echo -e "${YELLOW}Desktop entry created at: $DESKTOP_ENTRY${RESET}" # Update the desktop database for GNOME, Unity, XFCE, etc. echo "Updating desktop database..." if command -v update-desktop-database &> /dev/null; then update-desktop-database "$DESKTOP_DIR" + echo -e "${YELLOW}Desktop database updated in: $DESKTOP_DIR${RESET}" fi # Update the KDE desktop database if KDE is in use From ec4989134de6428c68ac804e2a5910483563ab41 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 20 Feb 2024 13:53:08 +0530 Subject: [PATCH 367/864] fix: phoenix displayed in lost and found in kubuntu --- docs/linux/installer.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 2e017d24..2f47674f 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -euo pipefail # Exit immediately if a command exits with a non-zero status. + set -euo pipefail # Exit immediately if a command exits with a non-zero status. # Define common variables DESKTOP_DIR=$HOME/.local/share/applications GITHUB_REPO="phcode-dev/phoenix-desktop" @@ -363,10 +363,16 @@ copyFilesToDestination(){ [Desktop Entry] Type=Application Name=Phoenix Code +GenericName=Code Editor +Comment=Code editor +Keywords=Programming;Development;IDE;Editor;Code; Exec=$INSTALL_DIR/phoenix-code %F Icon=$INSTALL_DIR/icon.png Terminal=false MimeType=$MIME_TYPES_STRING; +Categories=Development;IDE;Utility;TextEditor; +StartupNotify=true +StartupWMClass=phoenix-code EOF echo -e "${YELLOW}Desktop entry created at: $DESKTOP_ENTRY${RESET}" # Update the desktop database for GNOME, Unity, XFCE, etc. From 2d28d48cb1891d342ee2e1ad1dababf158514812 Mon Sep 17 00:00:00 2001 From: charly p abraham Date: Tue, 20 Feb 2024 13:59:14 +0530 Subject: [PATCH 368/864] Update installer.sh removing extra space --- docs/linux/installer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 2f47674f..bce3160b 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,5 +1,5 @@ #!/bin/bash - set -euo pipefail # Exit immediately if a command exits with a non-zero status. +set -euo pipefail # Exit immediately if a command exits with a non-zero status. # Define common variables DESKTOP_DIR=$HOME/.local/share/applications GITHUB_REPO="phcode-dev/phoenix-desktop" From 79be0d0a7e4592d0dc8bc74c076f0f2ca38d78e1 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 20 Feb 2024 15:22:54 +0530 Subject: [PATCH 369/864] chore: updating colours for messages in echo for linux install --- docs/linux/installer.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index bce3160b..27614c1c 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -139,7 +139,7 @@ create_invocation_script() { mkdir -p "$link_dir" # Ensure the directory exists cp "$binary_path/$script_name" "$link_dir/$script_name" - echo -e "${YELLOW}Invocation script created at: $link_dir/$script_name${RESET}" + echo -e "Invocation script created at: $link_dir/$script_name" } # Install Dependencies Function # @@ -338,7 +338,7 @@ copyFilesToDestination(){ echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" echo "Moving the necessary files to the installation directory..." - echo -e "${YELLOW}Phoenix Code files moved to: $INSTALL_DIR${RESET}" + echo -e "Phoenix Code files moved to: $INSTALL_DIR" mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" exit 1 @@ -351,7 +351,7 @@ copyFilesToDestination(){ echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" exit 1 } - echo -e "${YELLOW}Executable permissions set for: $INSTALL_DIR/$BINARY_NAME${RESET}" + echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" mkdir -p "$LINK_DIR" # Ensure the directory exists # Call the function to create and copy the invocation script @@ -379,7 +379,7 @@ EOF echo "Updating desktop database..." if command -v update-desktop-database &> /dev/null; then update-desktop-database "$DESKTOP_DIR" - echo -e "${YELLOW}Desktop database updated in: $DESKTOP_DIR${RESET}" + echo -e "Desktop database updated in: $DESKTOP_DIR" fi # Update the KDE desktop database if KDE is in use @@ -481,7 +481,7 @@ downloadAndInstall(){ echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" exit 1 } - echo -e "${YELLOW}Downloading the icon...${RESET}" + echo -e "Downloading the icon..." wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { echo -e "${RED}Failed to download Icon${RESET}"; exit 1; @@ -538,18 +538,17 @@ install() { if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" - # Update the prompt to inform the user about the repair behavior with color - echo -e "${YELLOW}The repair option will download and install the latest version available, replacing the current version.${RESET}" - read -r -p "Would you like to proceed with the repair? (y/N): " response + # Simplified prompt for reinstall without detailed explanation + read -r -p "Would you like to reinstall it? (y/N): " response case "$response" in [Yy]* ) - echo -e "${GREEN}Proceeding with the repair by installing the latest version...${RESET}" + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" uninstall downloadAndInstall copyFilesToDestination ;; * ) - echo -e "${RED}Repair aborted by the user.${RESET}" + echo -e "${RED}Reinstall aborted by the user.${RESET}" exit 0 ;; esac @@ -558,6 +557,7 @@ install() { copyFilesToDestination fi } + # Temporary code to clean up earlier beta installations function uninstallBetaAppImage() { rm -f "$LINK_DIR"/phoenix_icon.png From 5cc15d8c8ebb1113113b7de556b868cd7b3da605 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 20 Feb 2024 17:50:24 +0530 Subject: [PATCH 370/864] feat: add inmemory key val map in tuari for phstore --- src-tauri/src/main.rs | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 83395a95..4198661e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -7,6 +7,10 @@ use std::env; use tauri::{Manager}; use std::path::PathBuf; +use tauri::{State}; +use std::collections::HashMap; +use std::sync::Mutex; + #[cfg(target_os = "linux")] use std::fs::metadata; #[cfg(target_os = "linux")] @@ -91,6 +95,36 @@ fn _get_clipboard_files() -> Option> { } } +// this in memory hashmap is used to supplement the LMDB node layer in a multi window environment. +struct Storage { + map: Mutex>, +} + +#[tauri::command] +fn put_item(state: State<'_, Storage>, key: String, value: String) { + let mut map = state.map.lock().unwrap(); + map.insert(key, value); +} + +#[tauri::command] +fn get_item(state: State<'_, Storage>, key: String) -> Option { + let map = state.map.lock().unwrap(); + map.get(&key).cloned() +} + +#[tauri::command] +fn get_all_items(state: State<'_, Storage>) -> HashMap { + let map = state.map.lock().unwrap(); + map.clone() +} + +#[tauri::command] +fn delete_item(state: State<'_, Storage>, key: String) { + let mut map = state.map.lock().unwrap(); + map.remove(&key); +} +// in memory hashmap end + static mut DEVTOOLS_LOADED:bool = false; #[tauri::command] @@ -245,6 +279,9 @@ fn main() { let _ = fix_path_env::fix(); tauri::Builder::default() + .manage(Storage { + map: Mutex::new(HashMap::new()), + }) .register_uri_scheme_protocol("phtauri", move |app, request| { // can't use `tauri` because that's already in use let path = remove_version_from_url(request.uri()); let path = path.strip_prefix("phtauri://localhost"); @@ -302,6 +339,7 @@ fn main() { get_mac_deep_link_requests, toggle_devtools, console_log, console_error, _get_commandline_args, get_current_working_dir, _get_window_labels, + put_item, get_item, get_all_items, delete_item, _get_windows_drives, _rename_path, show_in_folder, zoom_window, _get_clipboard_files]) .setup(|app| { init::init_app(app); From f5327c2e86c47ea2d9acbd7218b2414a3ffe66bd Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 20 Feb 2024 18:01:54 +0530 Subject: [PATCH 371/864] fix: build fail in mac --- src-tauri/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 4198661e..166633b6 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -227,7 +227,7 @@ fn remove_version_from_url(url: &str) -> String { } #[cfg(target_os = "macos")] -use std::sync::{Arc, Mutex}; +use std::sync::{Arc}; #[cfg(target_os = "macos")] use lazy_static::lazy_static; From 0d3059199510423cb0c6da8631b1eea4b5ba2660 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 21 Feb 2024 06:50:16 +0000 Subject: [PATCH 372/864] ci: update phcode version to 3.3.7 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 6872c946..bd420b89 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.6", + "version": "3.3.7", "type": "module", "scripts": { "tauri": "tauri", @@ -53,6 +53,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "1ded50f42cb3289bf9319649a4953ca87f8df5c2" + "commit": "35ffea70f6b9f98870a1a8970c030acb939fc781" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index bd3d06a3..70f2f8cd 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.6" +version = "3.3.7" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 87de3cf4..9ae53d0a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.6" + "version": "3.3.7" }, "tauri": { "allowlist": { @@ -80,7 +80,10 @@ { "name": "run-update-linux-command", "cmd": "x-terminal-emulator", - "args": ["-e", "wget -qO- https://updates.phcode.io/linux/installer.sh | bash -s -- --upgrade"] + "args": [ + "-e", + "wget -qO- https://updates.phcode.io/linux/installer.sh | bash -s -- --upgrade" + ] } ] } From 540f6ed2f92dfd7a2b9d10e5be15c811b8361b84 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 21 Feb 2024 14:23:27 +0530 Subject: [PATCH 373/864] build: rename install script as installer-dev to not affect production installer --- docs/linux/installer-dev.sh | 739 +++++++++++++++++++++++++++++++++ docs/linux/installer.sh | 805 +++++------------------------------- 2 files changed, 848 insertions(+), 696 deletions(-) create mode 100755 docs/linux/installer-dev.sh mode change 100755 => 100644 docs/linux/installer.sh diff --git a/docs/linux/installer-dev.sh b/docs/linux/installer-dev.sh new file mode 100755 index 00000000..27614c1c --- /dev/null +++ b/docs/linux/installer-dev.sh @@ -0,0 +1,739 @@ +#!/bin/bash +set -euo pipefail # Exit immediately if a command exits with a non-zero status. +# Define common variables +DESKTOP_DIR=$HOME/.local/share/applications +GITHUB_REPO="phcode-dev/phoenix-desktop" +API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" +ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" +INSTALL_DIR="$HOME/.phoenix-code" +LINK_DIR="$HOME/.local/bin" +DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries +DESKTOP_ENTRY_NAME="PhoenixCode.desktop" +DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" +SCRIPT_NAME="phcode" # Name of the script to invoke the binary +BINARY_NAME="phoenix-code" + +declare -a MIME_TYPES=( + "text/html" + "application/atom+xml" + "application/x-coldfusion" + "text/x-clojure" + "text/coffeescript" + "application/json" + "text/css" + "text/x-diff" + "text/jsx" + "text/markdown" + "application/mathml+xml" + "application/rdf+xml" + "application/rss+xml" + "application/sql" + "image/svg+xml" + "text/x-python" + "application/xml" + "application/vnd.mozilla.xul+xml" + "application/x-yaml" + "text/javascript" + "application/javascript" + "text/mjs" + "application/mjs" + "text/cjs" + "inode/directory" # Added to include directory handling +) + + +# Define color variables for easy reference +GREEN="\e[32m" +YELLOW="\e[33m" +RED="\e[31m" +RESET="\e[0m" + +# Cleanup Function +# +# Purpose: +# The cleanup function is designed to ensure that the script cleans up any temporary +# resources it used during its execution. Specifically, it removes the temporary directory +# created at the beginning of the script, along with all its contents. This is crucial for +# maintaining a clean file system and avoiding the accumulation of unused files. +# +# Behavior: +# - The function targets a temporary directory specified by the `$TMP_DIR` variable. +# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. +# This includes any temporary files, downloaded assets, or other data generated during the script's execution. +# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes +# automatically when the script exits, regardless of the exit point. This includes normal completion, +# errors, or manual termination via signals like SIGINT (Ctrl+C). +# +# Considerations: +# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. +# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. +# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` +# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. +# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within +# `$TMP_DIR` is expendable and safe to delete. +# +# Usage: +# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` +# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` +# is correctly set to the temporary directory path before invoking the function. +# +cleanup() { + rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. +} + +trap cleanup EXIT # Register the cleanup function to be called on script exit. + + +TMP_DIR=$(mktemp -d) + +# Create Invocation Script Function +# +# Purpose: +# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. +# This script is intended to simplify the execution of Phoenix Code by providing a more accessible +# command interface. The generated script is placed in a user-accessible binary directory, making it +# possible to run Phoenix Code from anywhere in the system without needing to specify the full path +# to the binary. +# +# Parameters: +# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. +# - script_name: The name to be given to the invocation script. This name is used both for the +# script file itself and for the symlink created in the user's binary directory. +# - link_dir: The directory where a symlink to the invocation script will be placed, typically +# a location in the user's PATH, such as ~/.local/bin, for easy access. +# +# Behavior: +# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. +# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a +# command to execute the Phoenix Code binary with any passed arguments ("$@"). +# 3. Sets executable permissions on the newly created script. +# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. +# +# Considerations: +# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' +# does not conflict with existing files in these directories to prevent unintended overwrites. +# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes +# these directories are already created and accessible. +# - The generated script includes a warning comment advising against deletion, as it is +# essential for the proper functioning of Phoenix Code when invoked through this script. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# after the binary has been placed in its final location. It should not be called arbitrarily, as it +# assumes a specific setup and context established by the installer script. +# +create_invocation_script() { + local binary_path="$1" + local script_name="$2" + local link_dir="$3" + + echo "Creating an invocation script for the binary..." + # Start of the generated script + echo "#!/bin/bash" > "$binary_path/$script_name.sh" + # Add a warning comment about the script being auto-generated + echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" + echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" + chmod +x "$binary_path/$script_name" + + echo "Copying the invocation script to $link_dir..." + mkdir -p "$link_dir" # Ensure the directory exists + cp "$binary_path/$script_name" "$link_dir/$script_name" + + echo -e "Invocation script created at: $link_dir/$script_name" +} +# Install Dependencies Function +# +# Purpose: +# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. +# This function identifies the user's Linux distribution and installs the appropriate packages +# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and +# Arch Linux distributions. +# +# Behavior: +# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. +# If the command fails, it prompts the user to enter their password for `sudo` access. +# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. +# 3. Based on the identified distribution, executes the appropriate package manager command +# with the required packages. Supported package managers are `apt` for Debian-based systems, +# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. +# 4. Updates the package index (if applicable) and installs the packages. +# +# Considerations: +# - The function requires internet access to fetch package information and install packages. +# - It assumes that the user has `sudo` privileges to install packages system-wide. +# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, +# this function must be updated accordingly. +# - Unsupported distributions will result in an error message and termination of the script, +# as the required dependencies cannot be installed automatically. +# - This function does not handle potential errors from package installation commands. It's +# recommended to monitor the output for any issues that may require manual intervention. +# +# Usage: +# This function is intended to be called during the Phoenix Code installation process, typically +# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites +# are met for a successful Phoenix Code execution. +# +install_dependencies() { + echo "Attempting to install required dependencies..." + + # Inform the user that the next steps require administrative access + echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." + + # Check if the script can execute sudo commands without interaction + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed with the installation of dependencies." + fi + + # Attempt to identify the Linux distribution + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO=$ID + else + echo "Unable to identify the operating system." + exit 1 + fi + + # Install dependencies based on the distribution + case "$DISTRO" in + ubuntu|debian|linuxmint) + echo "Detected an Ubuntu/Debian based distribution." + sudo apt update + sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + gstreamer1.0-tools + ;; + fedora|rhel|centos) + echo "Detected a Fedora/Red Hat based distribution." + sudo dnf install webkit2gtk3 gtk3 \ + gstreamer1-plugins-base gstreamer1-plugins-good + ;; + arch|manjaro) + echo "Detected an Arch Linux based distribution." + sudo pacman -Syu + sudo pacman -S webkit2gtk gtk3 + ;; + *) + echo "Unsupported distribution. Please manually install the required dependencies." + exit 1 + ;; + esac +} +# Verify and Install Dependencies Function +# +# Purpose: +# This function is responsible for verifying if the Phoenix Code application can be successfully +# launched with the current set of installed dependencies. If the initial verification fails, it +# attempts to install the necessary dependencies and then re-verifies the application launch. +# +# Behavior: +# 1. Changes the current directory to the temporary directory where Phoenix Code is located. +# 2. Sets the executable permission for the Phoenix Code binary and attempts to run it with a +# verification-specific command (e.g., `--runVerify`). This step is intended to check if the +# application can start without installing additional dependencies. +# 3. If the initial verification succeeds, the function exits with a success status (0), indicating +# no further action is needed. +# 4. If the initial verification fails, the function proceeds to invoke `install_dependencies` to +# install any missing dependencies specific to the user's Linux distribution. +# 5. After installing dependencies, it attempts to verify the application launch again. If this +# second attempt succeeds, the function exits with a success status (0). +# 6. If the verification fails even after installing dependencies, the function prints an error +# message advising the user to check the application requirements or contact support, and +# exits with an error status (1). +# 7. Finally, the function ensures to change back to the original directory where the script was +# invoked, preserving the user's shell environment. +# +# Considerations: +# - The function assumes that the Phoenix Code binary is located in a temporary directory and +# that this directory is correctly set in the `$TMP_DIR` variable. +# - It relies on the Phoenix Code binary supporting a `--runVerify` command or equivalent for +# verification purposes. If such a command is not available, this part of the function needs +# adjustment. +# - Dependency installation requires administrative privileges; hence, the user might be prompted +# for a password to allow `sudo` operations. +# - The function does not handle all possible error scenarios during dependency installation. +# Users should monitor the output for potential issues that might need manual intervention. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# before finalizing the installation, to ensure that all system requirements are met for the +# application to run properly. +# +verify_and_install_dependencies() { + cd "$TMP_DIR/phoenix-code" + # Ensure the binary is executable + chmod +x "./phoenix-code" + # First attempt to verify the application launch + if ./phoenix-code --runVerify; then + echo "Application launch verification successful." + return 0 # Exit the function successfully if verification succeeds + else + echo "Initial verification failed. Attempting to install dependencies..." + install_dependencies # Function to install required dependencies + fi + + # Second attempt to verify the application launch after installing dependencies + if ./phoenix-code --runVerify; then + echo "Application launch verification successful after installing dependencies." + cd - + return 0 # Exit the function successfully if verification succeeds + else + echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." + cd - + return 1 # Return an error code to indicate failure + fi +} +# Set Phoenix Code as the default application for specified MIME types +set_default_application() { + local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file + + for mime_type in "${MIME_TYPES[@]}"; do + xdg-mime default "$desktop_file" "$mime_type" + done + echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" +} + +# Copy Files to Destination Function +# +# Purpose: +# This function is responsible for setting up the final installation directory for Phoenix Code, +# moving the necessary files into place, creating the invocation script, and setting up the desktop +# entry for the application. It ensures that all components of Phoenix Code are correctly installed +# and configured in the user's environment. +# +# Behavior: +# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files +# will reside. +# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. +# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from +# the temporary directory (`$TMP_DIR`) to the installation directory. +# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. +# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. +# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. +# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and +# launchers, and places this file in the desktop entry directory. +# 8. Updates the system's desktop database to ensure the new application entry is recognized and available +# in application menus and launchers. This step might involve commands like `update-desktop-database` +# or `kbuildsycoca5`, depending on the desktop environment. +# +# Considerations: +# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and +# that this directory is correctly set. +# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and +# accessible. If these variables are unset or incorrect, the function may not perform as intended. +# - Administrative privileges may be required for certain operations, such as updating the desktop database +# or setting permissions, depending on the system's configuration. +# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function +# does perform significant file system operations that could potentially conflict with existing user data +# or system settings. +# +# Usage: +# This function is intended to be called as part of the Phoenix Code installation process, after the +# application's binary and other necessary files have been prepared in a temporary location. It finalizes +# the installation by placing all components in their appropriate locations within the user's system. +# +copyFilesToDestination(){ + echo "Setting up the installation directory at $INSTALL_DIR..." + mkdir -p "$INSTALL_DIR" + mkdir -p "$DESKTOP_DIR" + echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" + + echo "Moving the necessary files to the installation directory..." + echo -e "Phoenix Code files moved to: $INSTALL_DIR" + mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { + echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" + exit 1 + } + # Move the icon to the installation directory + mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" + + echo "Setting the correct permissions for the executable..." + chmod +x "$INSTALL_DIR/phoenix-code" || { + echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" + exit 1 + } + echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" + + mkdir -p "$LINK_DIR" # Ensure the directory exists + # Call the function to create and copy the invocation script + create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" + # Convert MIME types array to semicolon-separated string for the desktop entry + MIME_TYPES_STRING=$(IFS=";"; echo "${MIME_TYPES[*]}") + echo "Creating desktop entry..." + cat > "$DESKTOP_ENTRY" < /dev/null; then + update-desktop-database "$DESKTOP_DIR" + echo -e "Desktop database updated in: $DESKTOP_DIR" + fi + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi + fi + # Set Phoenix Code as the default application for the MIME types + set_default_application + echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" + +} +downloadLatestReleaseInfo() { + local release_info_file="$TMP_DIR/latest_release.json" + + if [ -f "$release_info_file" ]; then + # Only extract and echo the version number, without any additional messages + grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" + return + fi + + # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly + >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" + wget -qO "$release_info_file" "$API_URL" || { + >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" + exit 1 + } + + # Only extract and echo the version number after successful download + grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" +} + +# Download Latest Release Information Function +# +# Purpose: +# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function +# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to +# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. +# +# Behavior: +# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary +# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already +# been fetched and proceeds to extract the version number from this file without re-downloading. +# 2. If the release information file does not exist, the function uses `wget` to download the JSON data +# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint +# of the Phoenix Code GitHub repository. +# 3. The JSON data is saved to `latest_release.json` in the temporary directory. +# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular +# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version +# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number +# portion. +# 5. Echoes the extracted version number for use by the calling context. +# +# Considerations: +# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available +# in the execution environment. +# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code +# repository for this function to work as intended. +# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, +# the `grep` pattern used to extract the version number may need to be updated. +# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an +# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the +# latest release information. +# - The function does not perform error handling for the `wget` command. If the download fails, the script may +# exit or behave unexpectedly depending on the `set -e` setting. +# +# Usage: +# This function is intended to be called during the installation or upgrade process to determine the latest +# version of Phoenix Code. The extracted version number can be used to compare with the currently installed +# version and decide whether an upgrade is necessary. +# +downloadAndInstall(){ + echo "Using temporary directory $TMP_DIR for processing" + downloadLatestReleaseInfo > /dev/null + CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') + echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" + + BEST_MATCH_URL="" + BEST_MATCH_VERSION=0 + echo "Searching for a compatible binary..." + + while read -r BINARY_URL; do + BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') + if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then + BEST_MATCH_URL="$BINARY_URL" + BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" + echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" + fi + done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") + + if [ -z "$BEST_MATCH_URL" ]; then + echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" + exit 1 + fi + + echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { + echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" + exit 1 + } + echo -e "Downloading the icon..." + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { + echo -e "${RED}Failed to download Icon${RESET}"; + exit 1; + } + echo "Extracting the binary to $TMP_DIR..." + tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { + echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" + exit 1 + } + + # Verify binary execution and install dependencies if necessary + if ! verify_and_install_dependencies; then + echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" + exit 1 + fi +} +# Install Function +# +# Purpose: +# Facilitates the entire installation process of Phoenix Code on the user's system. This includes +# checking for previous installations, downloading and installing the latest version, setting up +# necessary directories, and ensuring that all dependencies are met. It also handles user prompts +# for repair or reinstallation options if Phoenix Code is already installed. +# +# Behavior: +# 1. Checks if Phoenix Code is already installed by looking for specific files or directories +# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main +# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). +# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and +# then reinstalls the application, ensuring the user ends up with the latest version. +# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest +# release and install it. This step involves downloading the binary, setting permissions, and +# moving files to their correct locations. +# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, +# create an invocation script, and perform other necessary post-installation configurations. +# +# Considerations: +# - The function assumes that the user has sufficient permissions to write to the target directories +# and install Phoenix Code. Administrative privileges may be required for certain operations. +# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation +# directory will be replaced. Users should ensure that any custom configurations or data are backed up +# before proceeding. +# - Network connectivity is required to download the latest version of Phoenix Code from the repository. +# - The function does not explicitly handle all potential error scenarios, such as download failures or +# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. +# +# Usage: +# This function is intended to be invoked when the script is run without specific options (e.g., not an +# uninstall or upgrade). It can be directly called from the command line when the user wishes to install +# Phoenix Code, or it may be triggered by default when the script is executed without arguments. +# +install() { + # Check if the application is already installed + if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then + echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" + + # Simplified prompt for reinstall without detailed explanation + read -r -p "Would you like to reinstall it? (y/N): " response + case "$response" in + [Yy]* ) + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + uninstall + downloadAndInstall + copyFilesToDestination + ;; + * ) + echo -e "${RED}Reinstall aborted by the user.${RESET}" + exit 0 + ;; + esac + else + downloadAndInstall + copyFilesToDestination + fi +} + +# Temporary code to clean up earlier beta installations +function uninstallBetaAppImage() { + rm -f "$LINK_DIR"/phoenix_icon.png +} +# Upgrade Function +# +# Purpose: +# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated +# to the latest version available. This function checks the currently installed version against +# the latest version available in the GitHub repository. If a newer version is found, it proceeds +# to download and install the update, effectively replacing the old version with the new one. +# +# Behavior: +# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation +# directory and the invocation script. If not found, it exits with an error message indicating that +# Phoenix Code must be installed before it can be upgraded. +# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version +# check command (e.g., `phoenix-code --version`) and captures the output. +# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` +# function, which retrieves the version number of the latest release. +# 4. Compares the currently installed version with the latest version. If the installed version is older, +# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and +# installation of the new version. +# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. +# +# Considerations: +# - The function relies on the correct implementation of version checking in the Phoenix Code binary. +# The binary must support a command-line option to output its version, and the output format must be +# consistent for correct parsing and comparison. +# - Network connectivity is required to fetch the latest release information from the GitHub repository. +# The upgrade process will fail if the script cannot connect to GitHub. +# - The user must have sufficient permissions to overwrite the existing installation files and to +# execute network requests (e.g., downloading the latest release). +# - The upgrade process replaces the existing installation files. Users should ensure that any +# necessary backups or custom configurations are saved before proceeding with the upgrade. +# +# Usage: +# This function is intended to be called when the user explicitly wants to upgrade their installation +# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the +# script, as defined in the script's main case statement handling command-line arguments. +# +upgrade() { + echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" + + # Ensure Phoenix Code is installed + if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then + echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" + exit 1 + fi + # Get the current installed version + CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) + echo "Current installed version: $CURRENT_VERSION" + + LATEST_VERSION=$(downloadLatestReleaseInfo) + # Now LATEST_VERSION should only contain the version number without extra messages + echo "Latest available version: $LATEST_VERSION" + + # Compare versions and upgrade if the latest version is greater + if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then + echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" + downloadAndInstall + uninstall + copyFilesToDestination + echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" + else + echo "Your Phoenix Code installation is up-to-date." + fi + +} +# Uninstall Function +# +# Purpose: +# Handles the removal of Phoenix Code from the user's system. This function is responsible for +# cleaning up all files, directories, and links created during the installation process, effectively +# reverting any changes made by the installer script. It ensures that Phoenix Code and its components +# are uninstalled cleanly, leaving no residual files or configurations. +# +# Behavior: +# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). +# This step prevents the Phoenix Code command from being accessible after uninstallation. +# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus +# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. +# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. +# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. +# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including +# the main binary, configuration files, and any other related files placed during installation. +# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. +# +# Considerations: +# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately +# reflect the locations used during the installation. If these variables are incorrect, the uninstallation +# process may not remove all components. +# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed +# in system-wide directories. +# - Users should be advised to back up any important data or configurations related to Phoenix Code before +# initiating the uninstallation process, as this function will remove all associated files without recovery options. +# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot +# be reversed through this script. +# +# Usage: +# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. +# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement +# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this +# function is executed to prevent accidental data loss. +# +uninstall() { + echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" + uninstallBetaAppImage + # Remove the invocation script from ~/.local/bin + if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then + echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" + rm "$LINK_DIR/$SCRIPT_NAME" + else + echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" + fi + + # Delete the desktop entry + if [ -f "$DESKTOP_ENTRY" ]; then + echo -e "${YELLOW}Removing desktop entry...${RESET}" + rm "$DESKTOP_ENTRY" + + # Update the desktop database for GNOME, Unity, XFCE, etc. + echo -e "${YELLOW}Updating desktop database...${RESET}" + if command -v update-desktop-database &> /dev/null; then + update-desktop-database "$DESKTOP_DIR" + fi + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi + fi + else + echo -e "${RED}Desktop entry not found. Skipping...${RESET}" + fi + + # Remove the installation directory and its contents + if [ -d "$INSTALL_DIR" ]; then + echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" + rm -rf "$INSTALL_DIR" + else + echo -e "${RED}Installation directory not found. Skipping...${RESET}" + fi + echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" +} + +show_help() { + echo "Usage: $0 [OPTION]" + echo "Install, upgrade, or uninstall Phoenix Code." + echo + echo "Options:" + echo " -h, --help Display this help and exit" + echo " --uninstall Uninstall Phoenix Code" + echo " --upgrade Upgrade Phoenix Code to the latest version" + echo + echo "Without any options, the script will install Phoenix Code." +} +case "${1-}" in + -h|--help) + show_help # Function to show help + ;; + --uninstall) + uninstall # Function to uninstall + ;; + --upgrade) + upgrade # Function to upgrade + ;; + "") + # This case handles when $1 is unset (acts as a default action) + install # Function to install + ;; + *) + # This case handles unexpected arguments + echo "Invalid option: $1" >&2 + show_help # Assuming you have a function to show usage information + exit 1 + ;; +esac diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh old mode 100755 new mode 100644 index 27614c1c..39bd3e75 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,739 +1,152 @@ #!/bin/bash -set -euo pipefail # Exit immediately if a command exits with a non-zero status. +set -e # Exit immediately if a command exits with a non-zero status. # Define common variables +APPIMAGE_DIR=$HOME/.local/bin DESKTOP_DIR=$HOME/.local/share/applications +NEW_APPIMAGE=phcode +ICON=phoenix_icon.png GITHUB_REPO="phcode-dev/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" -INSTALL_DIR="$HOME/.phoenix-code" -LINK_DIR="$HOME/.local/bin" -DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries -DESKTOP_ENTRY_NAME="PhoenixCode.desktop" -DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" -SCRIPT_NAME="phcode" # Name of the script to invoke the binary -BINARY_NAME="phoenix-code" - -declare -a MIME_TYPES=( - "text/html" - "application/atom+xml" - "application/x-coldfusion" - "text/x-clojure" - "text/coffeescript" - "application/json" - "text/css" - "text/x-diff" - "text/jsx" - "text/markdown" - "application/mathml+xml" - "application/rdf+xml" - "application/rss+xml" - "application/sql" - "image/svg+xml" - "text/x-python" - "application/xml" - "application/vnd.mozilla.xul+xml" - "application/x-yaml" - "text/javascript" - "application/javascript" - "text/mjs" - "application/mjs" - "text/cjs" - "inode/directory" # Added to include directory handling -) - - -# Define color variables for easy reference -GREEN="\e[32m" -YELLOW="\e[33m" -RED="\e[31m" -RESET="\e[0m" - -# Cleanup Function -# -# Purpose: -# The cleanup function is designed to ensure that the script cleans up any temporary -# resources it used during its execution. Specifically, it removes the temporary directory -# created at the beginning of the script, along with all its contents. This is crucial for -# maintaining a clean file system and avoiding the accumulation of unused files. -# -# Behavior: -# - The function targets a temporary directory specified by the `$TMP_DIR` variable. -# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. -# This includes any temporary files, downloaded assets, or other data generated during the script's execution. -# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes -# automatically when the script exits, regardless of the exit point. This includes normal completion, -# errors, or manual termination via signals like SIGINT (Ctrl+C). -# -# Considerations: -# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. -# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. -# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` -# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. -# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within -# `$TMP_DIR` is expendable and safe to delete. -# -# Usage: -# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` -# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` -# is correctly set to the temporary directory path before invoking the function. -# -cleanup() { - rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. -} - -trap cleanup EXIT # Register the cleanup function to be called on script exit. - - -TMP_DIR=$(mktemp -d) - -# Create Invocation Script Function -# -# Purpose: -# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. -# This script is intended to simplify the execution of Phoenix Code by providing a more accessible -# command interface. The generated script is placed in a user-accessible binary directory, making it -# possible to run Phoenix Code from anywhere in the system without needing to specify the full path -# to the binary. -# -# Parameters: -# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. -# - script_name: The name to be given to the invocation script. This name is used both for the -# script file itself and for the symlink created in the user's binary directory. -# - link_dir: The directory where a symlink to the invocation script will be placed, typically -# a location in the user's PATH, such as ~/.local/bin, for easy access. -# -# Behavior: -# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. -# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a -# command to execute the Phoenix Code binary with any passed arguments ("$@"). -# 3. Sets executable permissions on the newly created script. -# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. -# -# Considerations: -# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' -# does not conflict with existing files in these directories to prevent unintended overwrites. -# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes -# these directories are already created and accessible. -# - The generated script includes a warning comment advising against deletion, as it is -# essential for the proper functioning of Phoenix Code when invoked through this script. -# -# Usage: -# This function is intended to be called during the installation or upgrade process of Phoenix Code, -# after the binary has been placed in its final location. It should not be called arbitrarily, as it -# assumes a specific setup and context established by the installer script. -# -create_invocation_script() { - local binary_path="$1" - local script_name="$2" - local link_dir="$3" +check_and_install_libfuse() { + # Identify the Linux distribution + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO=$ID + else + echo "Cannot identify the operating system." + exit 1 + fi - echo "Creating an invocation script for the binary..." - # Start of the generated script - echo "#!/bin/bash" > "$binary_path/$script_name.sh" - # Add a warning comment about the script being auto-generated - echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" - echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" - chmod +x "$binary_path/$script_name" + echo "Checking for FUSE library..." - echo "Copying the invocation script to $link_dir..." - mkdir -p "$link_dir" # Ensure the directory exists - cp "$binary_path/$script_name" "$link_dir/$script_name" + if [ "$DISTRO" = "ubuntu" ]; then + # Check and install libfuse2 on Ubuntu + if ! dpkg -s libfuse2 &> /dev/null; then + echo "libfuse2 not found, installing..." + sudo apt-get update && sudo apt-get install -y libfuse2 || { echo "Failed to install libfuse2"; exit 1; } + else + echo "libfuse2 is already installed." + fi + elif [ "$DISTRO" = "fedora" ]; then + # Check and install fuse-libs on Fedora + if [ "$DISTRO" = "fedora" ]; then + # Check and install fuse-libs on Fedora + if ! rpm -q fuse-libs &> /dev/null; then + echo "fuse-libs not found, installing..." + sudo dnf install -y fuse-libs || { echo "Failed to install fuse-libs"; exit 1; } + else + echo "fuse-libs is already installed." + fi + fi - echo -e "Invocation script created at: $link_dir/$script_name" + else + echo "Unsupported distribution: $DISTRO" + exit 1 + fi } -# Install Dependencies Function -# -# Purpose: -# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. -# This function identifies the user's Linux distribution and installs the appropriate packages -# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and -# Arch Linux distributions. -# -# Behavior: -# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. -# If the command fails, it prompts the user to enter their password for `sudo` access. -# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. -# 3. Based on the identified distribution, executes the appropriate package manager command -# with the required packages. Supported package managers are `apt` for Debian-based systems, -# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. -# 4. Updates the package index (if applicable) and installs the packages. -# -# Considerations: -# - The function requires internet access to fetch package information and install packages. -# - It assumes that the user has `sudo` privileges to install packages system-wide. -# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, -# this function must be updated accordingly. -# - Unsupported distributions will result in an error message and termination of the script, -# as the required dependencies cannot be installed automatically. -# - This function does not handle potential errors from package installation commands. It's -# recommended to monitor the output for any issues that may require manual intervention. -# -# Usage: -# This function is intended to be called during the Phoenix Code installation process, typically -# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites -# are met for a successful Phoenix Code execution. -# -install_dependencies() { - echo "Attempting to install required dependencies..." - # Inform the user that the next steps require administrative access - echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." +install() { + check_and_install_libfuse + # Fetch the latest release data from GitHub + echo "Fetching latest release from $GITHUB_REPO..." + wget -qO- $API_URL > latest_release.json || { echo "Failed to fetch latest release info"; exit 1; } + + # Extract the download URL for the AppImage + APPIMAGE_URL=$(grep -oP '"browser_download_url": "\K(.*phoenix-desktop.*\.AppImage)(?=")' latest_release.json) || { echo "Failed to extract AppImage URL"; exit 1; } + + # If no AppImage URL is found, exit the script + if [ -z "$APPIMAGE_URL" ]; then + echo "No AppImage URL found in the latest release." + rm latest_release.json + exit 1 + fi - # Check if the script can execute sudo commands without interaction - if ! sudo -n true 2>/dev/null; then - echo "Please enter your password to proceed with the installation of dependencies." - fi + # Download the AppImage + echo "Downloading AppImage from $APPIMAGE_URL..." + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL || { echo "Failed to download AppImage"; exit 1; } + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $ICON $ICON_URL || { echo "Failed to download Icon"; exit 1; } + # Remove the temporary JSON file + rm latest_release.json - # Attempt to identify the Linux distribution - if [ -f /etc/os-release ]; then - . /etc/os-release - DISTRO=$ID - else - echo "Unable to identify the operating system." - exit 1 - fi - # Install dependencies based on the distribution - case "$DISTRO" in - ubuntu|debian|linuxmint) - echo "Detected an Ubuntu/Debian based distribution." - sudo apt update - sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ - gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ - gstreamer1.0-tools - ;; - fedora|rhel|centos) - echo "Detected a Fedora/Red Hat based distribution." - sudo dnf install webkit2gtk3 gtk3 \ - gstreamer1-plugins-base gstreamer1-plugins-good - ;; - arch|manjaro) - echo "Detected an Arch Linux based distribution." - sudo pacman -Syu - sudo pacman -S webkit2gtk gtk3 - ;; - *) - echo "Unsupported distribution. Please manually install the required dependencies." - exit 1 - ;; - esac -} -# Verify and Install Dependencies Function -# -# Purpose: -# This function is responsible for verifying if the Phoenix Code application can be successfully -# launched with the current set of installed dependencies. If the initial verification fails, it -# attempts to install the necessary dependencies and then re-verifies the application launch. -# -# Behavior: -# 1. Changes the current directory to the temporary directory where Phoenix Code is located. -# 2. Sets the executable permission for the Phoenix Code binary and attempts to run it with a -# verification-specific command (e.g., `--runVerify`). This step is intended to check if the -# application can start without installing additional dependencies. -# 3. If the initial verification succeeds, the function exits with a success status (0), indicating -# no further action is needed. -# 4. If the initial verification fails, the function proceeds to invoke `install_dependencies` to -# install any missing dependencies specific to the user's Linux distribution. -# 5. After installing dependencies, it attempts to verify the application launch again. If this -# second attempt succeeds, the function exits with a success status (0). -# 6. If the verification fails even after installing dependencies, the function prints an error -# message advising the user to check the application requirements or contact support, and -# exits with an error status (1). -# 7. Finally, the function ensures to change back to the original directory where the script was -# invoked, preserving the user's shell environment. -# -# Considerations: -# - The function assumes that the Phoenix Code binary is located in a temporary directory and -# that this directory is correctly set in the `$TMP_DIR` variable. -# - It relies on the Phoenix Code binary supporting a `--runVerify` command or equivalent for -# verification purposes. If such a command is not available, this part of the function needs -# adjustment. -# - Dependency installation requires administrative privileges; hence, the user might be prompted -# for a password to allow `sudo` operations. -# - The function does not handle all possible error scenarios during dependency installation. -# Users should monitor the output for potential issues that might need manual intervention. -# -# Usage: -# This function is intended to be called during the installation or upgrade process of Phoenix Code, -# before finalizing the installation, to ensure that all system requirements are met for the -# application to run properly. -# -verify_and_install_dependencies() { - cd "$TMP_DIR/phoenix-code" - # Ensure the binary is executable - chmod +x "./phoenix-code" - # First attempt to verify the application launch - if ./phoenix-code --runVerify; then - echo "Application launch verification successful." - return 0 # Exit the function successfully if verification succeeds - else - echo "Initial verification failed. Attempting to install dependencies..." - install_dependencies # Function to install required dependencies - fi + # Proceed with installation steps as before... + # Create necessary directories + mkdir -p $APPIMAGE_DIR + mkdir -p $DESKTOP_DIR - # Second attempt to verify the application launch after installing dependencies - if ./phoenix-code --runVerify; then - echo "Application launch verification successful after installing dependencies." - cd - - return 0 # Exit the function successfully if verification succeeds - else - echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." - cd - - return 1 # Return an error code to indicate failure - fi -} -# Set Phoenix Code as the default application for specified MIME types -set_default_application() { - local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file + # Copy and rename the AppImage, and copy the icon to the AppImage directory + echo "Installing Phoenix..." + mv $NEW_APPIMAGE $APPIMAGE_DIR/$NEW_APPIMAGE + mv "$ICON" $APPIMAGE_DIR # Ensure this icon file is in the current directory - for mime_type in "${MIME_TYPES[@]}"; do - xdg-mime default "$desktop_file" "$mime_type" - done - echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" -} + # Make the new AppImage executable + chmod +x $APPIMAGE_DIR/$NEW_APPIMAGE -# Copy Files to Destination Function -# -# Purpose: -# This function is responsible for setting up the final installation directory for Phoenix Code, -# moving the necessary files into place, creating the invocation script, and setting up the desktop -# entry for the application. It ensures that all components of Phoenix Code are correctly installed -# and configured in the user's environment. -# -# Behavior: -# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files -# will reside. -# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. -# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from -# the temporary directory (`$TMP_DIR`) to the installation directory. -# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. -# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. -# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. -# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and -# launchers, and places this file in the desktop entry directory. -# 8. Updates the system's desktop database to ensure the new application entry is recognized and available -# in application menus and launchers. This step might involve commands like `update-desktop-database` -# or `kbuildsycoca5`, depending on the desktop environment. -# -# Considerations: -# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and -# that this directory is correctly set. -# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and -# accessible. If these variables are unset or incorrect, the function may not perform as intended. -# - Administrative privileges may be required for certain operations, such as updating the desktop database -# or setting permissions, depending on the system's configuration. -# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function -# does perform significant file system operations that could potentially conflict with existing user data -# or system settings. -# -# Usage: -# This function is intended to be called as part of the Phoenix Code installation process, after the -# application's binary and other necessary files have been prepared in a temporary location. It finalizes -# the installation by placing all components in their appropriate locations within the user's system. -# -copyFilesToDestination(){ - echo "Setting up the installation directory at $INSTALL_DIR..." - mkdir -p "$INSTALL_DIR" - mkdir -p "$DESKTOP_DIR" - echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" - echo "Moving the necessary files to the installation directory..." - echo -e "Phoenix Code files moved to: $INSTALL_DIR" - mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { - echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" - exit 1 - } - # Move the icon to the installation directory - mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" + # Define MIME types for file extensions + MIME_TYPES="text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;" - echo "Setting the correct permissions for the executable..." - chmod +x "$INSTALL_DIR/phoenix-code" || { - echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" - exit 1 - } - echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" + # Add directory association + MIME_TYPES+="inode/directory;" - mkdir -p "$LINK_DIR" # Ensure the directory exists - # Call the function to create and copy the invocation script - create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" - # Convert MIME types array to semicolon-separated string for the desktop entry - MIME_TYPES_STRING=$(IFS=";"; echo "${MIME_TYPES[*]}") - echo "Creating desktop entry..." - cat > "$DESKTOP_ENTRY" < $DESKTOP_DIR/PhoenixCode.desktop < /dev/null; then - update-desktop-database "$DESKTOP_DIR" - echo -e "Desktop database updated in: $DESKTOP_DIR" - fi - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 + # Update the desktop database for GNOME, Unity, XFCE, etc. + if command -v update-desktop-database &> /dev/null + then + update-desktop-database $DESKTOP_DIR fi - fi - # Set Phoenix Code as the default application for the MIME types - set_default_application - echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" - -} -downloadLatestReleaseInfo() { - local release_info_file="$TMP_DIR/latest_release.json" - - if [ -f "$release_info_file" ]; then - # Only extract and echo the version number, without any additional messages - grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" - return - fi - # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly - >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" - wget -qO "$release_info_file" "$API_URL" || { - >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" - exit 1 - } - - # Only extract and echo the version number after successful download - grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" -} - -# Download Latest Release Information Function -# -# Purpose: -# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function -# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to -# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. -# -# Behavior: -# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary -# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already -# been fetched and proceeds to extract the version number from this file without re-downloading. -# 2. If the release information file does not exist, the function uses `wget` to download the JSON data -# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint -# of the Phoenix Code GitHub repository. -# 3. The JSON data is saved to `latest_release.json` in the temporary directory. -# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular -# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version -# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number -# portion. -# 5. Echoes the extracted version number for use by the calling context. -# -# Considerations: -# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available -# in the execution environment. -# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code -# repository for this function to work as intended. -# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, -# the `grep` pattern used to extract the version number may need to be updated. -# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an -# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the -# latest release information. -# - The function does not perform error handling for the `wget` command. If the download fails, the script may -# exit or behave unexpectedly depending on the `set -e` setting. -# -# Usage: -# This function is intended to be called during the installation or upgrade process to determine the latest -# version of Phoenix Code. The extracted version number can be used to compare with the currently installed -# version and decide whether an upgrade is necessary. -# -downloadAndInstall(){ - echo "Using temporary directory $TMP_DIR for processing" - downloadLatestReleaseInfo > /dev/null - CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') - echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" - - BEST_MATCH_URL="" - BEST_MATCH_VERSION=0 - echo "Searching for a compatible binary..." - - while read -r BINARY_URL; do - BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') - if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then - BEST_MATCH_URL="$BINARY_URL" - BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" - echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null + then + kbuildsycoca5 + fi fi - done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") - - if [ -z "$BEST_MATCH_URL" ]; then - echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" - exit 1 - fi - - echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { - echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" - exit 1 - } - echo -e "Downloading the icon..." - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { - echo -e "${RED}Failed to download Icon${RESET}"; - exit 1; - } - echo "Extracting the binary to $TMP_DIR..." - tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { - echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" - exit 1 - } - - # Verify binary execution and install dependencies if necessary - if ! verify_and_install_dependencies; then - echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" - exit 1 - fi -} -# Install Function -# -# Purpose: -# Facilitates the entire installation process of Phoenix Code on the user's system. This includes -# checking for previous installations, downloading and installing the latest version, setting up -# necessary directories, and ensuring that all dependencies are met. It also handles user prompts -# for repair or reinstallation options if Phoenix Code is already installed. -# -# Behavior: -# 1. Checks if Phoenix Code is already installed by looking for specific files or directories -# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main -# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). -# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and -# then reinstalls the application, ensuring the user ends up with the latest version. -# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest -# release and install it. This step involves downloading the binary, setting permissions, and -# moving files to their correct locations. -# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, -# create an invocation script, and perform other necessary post-installation configurations. -# -# Considerations: -# - The function assumes that the user has sufficient permissions to write to the target directories -# and install Phoenix Code. Administrative privileges may be required for certain operations. -# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation -# directory will be replaced. Users should ensure that any custom configurations or data are backed up -# before proceeding. -# - Network connectivity is required to download the latest version of Phoenix Code from the repository. -# - The function does not explicitly handle all potential error scenarios, such as download failures or -# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. -# -# Usage: -# This function is intended to be invoked when the script is run without specific options (e.g., not an -# uninstall or upgrade). It can be directly called from the command line when the user wishes to install -# Phoenix Code, or it may be triggered by default when the script is executed without arguments. -# -install() { - # Check if the application is already installed - if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then - echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" - - # Simplified prompt for reinstall without detailed explanation - read -r -p "Would you like to reinstall it? (y/N): " response - case "$response" in - [Yy]* ) - echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" - uninstall - downloadAndInstall - copyFilesToDestination - ;; - * ) - echo -e "${RED}Reinstall aborted by the user.${RESET}" - exit 0 - ;; - esac - else - downloadAndInstall - copyFilesToDestination - fi -} -# Temporary code to clean up earlier beta installations -function uninstallBetaAppImage() { - rm -f "$LINK_DIR"/phoenix_icon.png + echo "Phoenix Code installed successfully." } -# Upgrade Function -# -# Purpose: -# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated -# to the latest version available. This function checks the currently installed version against -# the latest version available in the GitHub repository. If a newer version is found, it proceeds -# to download and install the update, effectively replacing the old version with the new one. -# -# Behavior: -# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation -# directory and the invocation script. If not found, it exits with an error message indicating that -# Phoenix Code must be installed before it can be upgraded. -# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version -# check command (e.g., `phoenix-code --version`) and captures the output. -# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` -# function, which retrieves the version number of the latest release. -# 4. Compares the currently installed version with the latest version. If the installed version is older, -# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and -# installation of the new version. -# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. -# -# Considerations: -# - The function relies on the correct implementation of version checking in the Phoenix Code binary. -# The binary must support a command-line option to output its version, and the output format must be -# consistent for correct parsing and comparison. -# - Network connectivity is required to fetch the latest release information from the GitHub repository. -# The upgrade process will fail if the script cannot connect to GitHub. -# - The user must have sufficient permissions to overwrite the existing installation files and to -# execute network requests (e.g., downloading the latest release). -# - The upgrade process replaces the existing installation files. Users should ensure that any -# necessary backups or custom configurations are saved before proceeding with the upgrade. -# -# Usage: -# This function is intended to be called when the user explicitly wants to upgrade their installation -# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the -# script, as defined in the script's main case statement handling command-line arguments. -# -upgrade() { - echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" - - # Ensure Phoenix Code is installed - if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then - echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" - exit 1 - fi - # Get the current installed version - CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) - echo "Current installed version: $CURRENT_VERSION" - - LATEST_VERSION=$(downloadLatestReleaseInfo) - # Now LATEST_VERSION should only contain the version number without extra messages - echo "Latest available version: $LATEST_VERSION" - - # Compare versions and upgrade if the latest version is greater - if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then - echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" - downloadAndInstall - uninstall - copyFilesToDestination - echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" - else - echo "Your Phoenix Code installation is up-to-date." - fi -} -# Uninstall Function -# -# Purpose: -# Handles the removal of Phoenix Code from the user's system. This function is responsible for -# cleaning up all files, directories, and links created during the installation process, effectively -# reverting any changes made by the installer script. It ensures that Phoenix Code and its components -# are uninstalled cleanly, leaving no residual files or configurations. -# -# Behavior: -# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). -# This step prevents the Phoenix Code command from being accessible after uninstallation. -# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus -# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. -# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. -# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. -# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including -# the main binary, configuration files, and any other related files placed during installation. -# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. -# -# Considerations: -# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately -# reflect the locations used during the installation. If these variables are incorrect, the uninstallation -# process may not remove all components. -# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed -# in system-wide directories. -# - Users should be advised to back up any important data or configurations related to Phoenix Code before -# initiating the uninstallation process, as this function will remove all associated files without recovery options. -# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot -# be reversed through this script. -# -# Usage: -# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. -# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement -# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this -# function is executed to prevent accidental data loss. -# uninstall() { - echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" - uninstallBetaAppImage - # Remove the invocation script from ~/.local/bin - if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then - echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" - rm "$LINK_DIR/$SCRIPT_NAME" - else - echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" - fi - - # Delete the desktop entry - if [ -f "$DESKTOP_ENTRY" ]; then - echo -e "${YELLOW}Removing desktop entry...${RESET}" - rm "$DESKTOP_ENTRY" - - # Update the desktop database for GNOME, Unity, XFCE, etc. - echo -e "${YELLOW}Updating desktop database...${RESET}" - if command -v update-desktop-database &> /dev/null; then - update-desktop-database "$DESKTOP_DIR" + # Remove the AppImage and the icon + echo "Uninstalling Phoenix..." + rm -f $APPIMAGE_DIR/$NEW_APPIMAGE + rm -f $APPIMAGE_DIR/$ICON + + # Remove the desktop entry + rm -f $DESKTOP_DIR/PhoenixCode.desktop + + # Update the desktop database for GNOME, Unity, XFCE, etc. (if available) + if command -v update-desktop-database &> /dev/null + then + update-desktop-database $DESKTOP_DIR fi # Update the KDE desktop database if KDE is in use if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then + if command -v kbuildsycoca5 &> /dev/null + then kbuildsycoca5 fi fi - else - echo -e "${RED}Desktop entry not found. Skipping...${RESET}" - fi - # Remove the installation directory and its contents - if [ -d "$INSTALL_DIR" ]; then - echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" - rm -rf "$INSTALL_DIR" - else - echo -e "${RED}Installation directory not found. Skipping...${RESET}" - fi - echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" + echo "Phoenix uninstalled successfully." } -show_help() { - echo "Usage: $0 [OPTION]" - echo "Install, upgrade, or uninstall Phoenix Code." - echo - echo "Options:" - echo " -h, --help Display this help and exit" - echo " --uninstall Uninstall Phoenix Code" - echo " --upgrade Upgrade Phoenix Code to the latest version" - echo - echo "Without any options, the script will install Phoenix Code." -} -case "${1-}" in - -h|--help) - show_help # Function to show help - ;; - --uninstall) - uninstall # Function to uninstall - ;; - --upgrade) - upgrade # Function to upgrade - ;; - "") - # This case handles when $1 is unset (acts as a default action) - install # Function to install - ;; - *) - # This case handles unexpected arguments - echo "Invalid option: $1" >&2 - show_help # Assuming you have a function to show usage information - exit 1 - ;; -esac +# Check for command-line arguments +if [[ "$1" == "--uninstall" ]]; then + uninstall +else + install +fi \ No newline at end of file From 193c8039eb67d1c149610c74c11559038036dc5f Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 21 Feb 2024 14:12:40 +0530 Subject: [PATCH 374/864] fix: build falure due to node download in github workflow --- package-lock.json | 44 +++++++++++++++++++++++++++++++-- package.json | 5 ++-- src-build/downloadNodeBinary.js | 23 +++++++++++------ 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index b4dc4d65..60dcbb9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { "name": "phoenix-code-ide", - "version": "3.2.23", + "version": "3.3.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.2.23", + "version": "3.3.6", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.9", "adm-zip": "0.5.10", "axios": "1.6.7", + "axios-retry": "4.0.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", @@ -268,6 +269,18 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/axios-retry": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.0.0.tgz", + "integrity": "sha512-F6P4HVGITD/v4z9Lw2mIA24IabTajvpDZmKa6zq/gGwn57wN5j1P3uWrAV0+diqnW6kTM2fTqmWNfgYWGmMuiA==", + "dev": true, + "dependencies": { + "is-retry-allowed": "^2.2.0" + }, + "peerDependencies": { + "axios": "0.x || 1.x" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -766,6 +779,18 @@ "node": ">=0.12.0" } }, + "node_modules/is-retry-allowed": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", + "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", @@ -1509,6 +1534,15 @@ "proxy-from-env": "^1.1.0" } }, + "axios-retry": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.0.0.tgz", + "integrity": "sha512-F6P4HVGITD/v4z9Lw2mIA24IabTajvpDZmKa6zq/gGwn57wN5j1P3uWrAV0+diqnW6kTM2fTqmWNfgYWGmMuiA==", + "dev": true, + "requires": { + "is-retry-allowed": "^2.2.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1872,6 +1906,12 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-retry-allowed": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", + "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "dev": true + }, "is-stream": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", diff --git a/package.json b/package.json index bd420b89..753cc3a9 100644 --- a/package.json +++ b/package.json @@ -48,11 +48,12 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.0", - "axios": "1.6.7" + "axios": "1.6.7", + "axios-retry": "4.0.0" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", "commit": "35ffea70f6b9f98870a1a8970c030acb939fc781" } -} \ No newline at end of file +} diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index 7e5482ff..ae81f23c 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -7,10 +7,16 @@ import {dirname} from 'path'; import * as fsExtra from "fs-extra"; import {getPlatformDetails, getSideCarBinName, removeDir} from "./utils.js"; import axios from 'axios'; - +import axiosRetry from 'axios-retry'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); +// Setup axios-retry +axiosRetry(axios, { + retries: 3, + retryDelay: axiosRetry.exponentialDelay, + retryCondition: (error) => error.code === 'ECONNABORTED' || /5\d{2}/.test(error.response?.status) +}); /** * Downloads the latest Node.js binary for the specified platform and architecture. * If the file already exists, it will not be downloaded again. If the download fails, @@ -46,7 +52,7 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { const outputPath = path.resolve(__dirname, asset.name); if (fs.existsSync(outputPath)) { - console.log('File already downloaded:', asset.name); + console.log(`File already downloaded: ${asset.name}`); return asset.name; } @@ -62,19 +68,22 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { return new Promise((resolve, reject) => { writer.on('finish', () => { - console.log('Download completed:', asset.name); + console.log(`Download completed: ${asset.name}`); resolve(asset.name); }); - writer.on('error', err => { - fs.unlinkSync(outputPath); // remove the partially downloaded file + writer.on('error', (err) => { + fs.unlink(outputPath, (unlinkErr) => { + if (unlinkErr) console.error(`Error removing incomplete download: ${unlinkErr}`); + }); reject(err); }); }); } catch (err) { - console.error('Error:', err.message); + console.error(`Error: ${err.message}`); if (maxRetries > 0) { console.log('Retrying download...'); + await new Promise(resolve => setTimeout(resolve, 1000)); // Wait before retrying return downloadNodeBinary(platform, arch, maxRetries - 1); } else { throw new Error('Max retries reached, download failed.'); @@ -230,4 +239,4 @@ console.log(args); const platformDetails = (args.length === 1) ? JSON.parse(args[0]) : getPlatformDetails(); console.log(platformDetails); -await copyLatestNodeForBuild(platformDetails.platform, platformDetails.arch); \ No newline at end of file +await copyLatestNodeForBuild(platformDetails.platform, platformDetails.arch); From d89c5d05571fb11270bf6327589149fb8685a055 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 21 Feb 2024 15:03:06 +0530 Subject: [PATCH 375/864] chore: remove debian package generation --- src-tauri/src/bundle/linux/deb/main.desktop.download | 11 ----------- src-tauri/tauri.conf.json | 7 +------ 2 files changed, 1 insertion(+), 17 deletions(-) delete mode 100644 src-tauri/src/bundle/linux/deb/main.desktop.download diff --git a/src-tauri/src/bundle/linux/deb/main.desktop.download b/src-tauri/src/bundle/linux/deb/main.desktop.download deleted file mode 100644 index b6d143c9..00000000 --- a/src-tauri/src/bundle/linux/deb/main.desktop.download +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Categories={{categories}} -{{#if comment}} -Comment={{comment}} -{{/if}} -Exec={{exec}} -Icon={{icon}} -Name={{name}} -Terminal=false -Type=Application -MimeType=text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;inode/directory; diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 9ae53d0a..b837d191 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -110,10 +110,6 @@ "active": true, "category": "DeveloperTool", "copyright": "Copyright (c) 2022 - present Core.ai", - "deb": { - "desktopTemplate": "./src/bundle/linux/deb/main.desktop.download", - "depends": [] - }, "appimage": { "bundleMediaFramework": true }, @@ -142,7 +138,6 @@ ], "shortDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", "targets": [ - "deb", "appimage", "nsis", "app", @@ -418,4 +413,4 @@ } ] } -} \ No newline at end of file +} From 17a6533ff057192613447f0bd695a758bbd2ad04 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 21 Feb 2024 09:49:22 +0000 Subject: [PATCH 376/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 669d39cc..569800b8 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.3.6", - "notes": "Testing experimental builds. Do not download!", - "pub_date": "2024-02-20T05:56:39.987Z", + "version": "3.3.7", + "notes": "Testing updates.", + "pub_date": "2024-02-21T07:24:54.431Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlaWFB5VFNqVDVLWmlBOGdqckV1amkwYUFDdVU1eXhPa2hIQ3R6OVJsMUNReTVwUU9XamNHak55OURHdFJITUlGSVlOcmRWbm5CZ0FOeVpGUDFvZWdzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDA3ODE5CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuNl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKZFVFUnYzSkRyRUNCb2RWd2JGSDVyb0x2bk5VdCt6TGdGeFFhbm52b3pUdnNQK1JOcTNxWll1TG5zcmxremlLSk94UFJoSC9XcG9zQURIUndOT2hPQkE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.6/phoenix-code-experimental-build_3.3.6_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtTQ1RsRnFhVlJoVU1mbGZ0eU4zL056RTMzczZONTBUbG9DZ21uNldlNFpOQS9LSlNod3Vub21OMFJxNVh1NzJlelpPYmRMamIzUG9CelJCZGlkbWdnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDk5MDEyCWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuN19hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKTTNNTEVUYjZJUUo4VERHaUFnK250M0JYL0NNQWVVWmxXNENPV0gxR0g0YnJLaVBmVndsYW5mNlNPOEtnVWUxbDNva1ZvYzlJZmJ4bnk1MW1DZnZ5Q0E9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.7/phoenix-code-experimental-build_3.3.7_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhCWlRZQm1JT0ZaSmV2S2VlOUFYWkw2WXFSNGd4M2pSVmdQb3dmeC9GdjdVMmdnaHpqdmozeTBmbnBYTm4vMXNJaFVseHc3UzhhYXp2NHdZSlI1Z0FBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDA3ODY1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuNl94NjQtc2V0dXAubnNpcy56aXAKdXY3RXBFbzhldWUrQjRYRGF1WFUzd1Z4NTNuWm5td01nYWduRFBvQ1dXUmM4MFhtc28xdEludTVTTzFoVUszTEtrM3krLzZFNjViMTh0RUJuMDdZQkE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.6/Phoenix.Code.Experimental.Build_3.3.6_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5aUmw2TitZTmtVb2VCdEgweEQ5VE1UZUQ0cTdYZk8xOUNnRFB2c09sano2akR2NXFncStLYU5seEswTGZ1M01MRmtWTEhXZktNYUVNaFRRbVY1Z0E4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDk5MDYxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuN194NjQtc2V0dXAubnNpcy56aXAKblNsV205Umd6eityQTQ4d2N6a01ibnRPODhDaThqaGJ6VzhsbThRZjB1NmNsakRIUlhBZ3N2WUZvdFFTUEwrOGVwTmRFSUl2WkNQMFN4Nktod0VvQXc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.7/Phoenix.Code.Experimental.Build_3.3.7_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9VUEozZURVdWtUdms2VDl3N1FuL0FJR1h6TmZVTEJMRmhOL2ttU05XZVc5cFVaVWo3b0NTTzJ2UnBhYm9mY1AwSEdFZkc0NytVZlJtMkZvMldSaFFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDA4MTQyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClRXcjMxSXdFblNSTHkvL0Z0ODNSWXlENFAxd2FnZzQxWmxUK0hCbzAyRXZwOHhiY0Zra0VJY280T3k4T0VYZ1kxQ1dwdmlJVXFnNnc2dGNsQTFqU0FRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.6/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlQNHJSWDJUK3BSS211Y0I2UE9MZGxUWE1yVEJOUEZzR3hOMFltYWFtV3B6K3h3M1hKK3ZGaWcySklRaTdtbVNnalRtU084V1l5RDArUldsWmdFR3dNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDk5NTcyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cm9jUUovNlBvL0ZjbG05WXhDeXJ1TEdJZGhPSmNmWGpwRXJicm1PdFdYWWdxNGRpTzg1eDRVQy9KeENyd215WmRsbzYxbG81cVlqdDdXSWE1VU1oOUNRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.7/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnM4bDQ5YlQ5TFF5U3plUFA0SDlxZk1xNTErbE8wZkszNkxrVUZYcWxPMmxGbUFXeEU0dFdodmNxdEc1cHN0YVdSS3VsVkoyNEdYOU5jaDlDUTlHTkFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDA4NTkwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Ckk4bDZyZzFxbG9LSlFmbDNOa1dlU0x1bVFkdStSOGovSU5sU09xRnpsN2tQc1pVbW5oRHVuTXRDSW94bWhhbWdSWHV3bzU0bWZsRGtRT2JZSmZtOEFRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.6/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlYVGVybzNWTEhNU1ZKTlBxZzV3ZkF2WVZTbWUxbUsycWpmY3B3U0FrN0VEMThRS1lqTFo5UlhjTkY0a2JJcWxPbmNZQjhMQkJRV1E3ZWdscmVDcmdBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTAwMjgzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnhnSkhieFhmL2lnNnUwemhIaHkvbHJBTlN2cEtGSWZVWlpEa1FaS1ZxT05VL2EwRmtPTnV2NnMwOHg1K0FtSGZEdCtCbFFTai81aHFFcFBPZ01UWkFBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.7/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 76c40ab8806fe58d3340574b82d93bfe5ced1070 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 21 Feb 2024 10:32:46 +0000 Subject: [PATCH 377/864] ci: update phcode version to 3.3.8 --- package.json | 6 +++--- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 753cc3a9..01899298 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.7", + "version": "3.3.8", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "35ffea70f6b9f98870a1a8970c030acb939fc781" + "commit": "17302c26ef6024a73bef53e8007c536f29bd2f47" } -} +} \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 70f2f8cd..0b08a1f7 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.7" +version = "3.3.8" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index b837d191..32e28d04 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.7" + "version": "3.3.8" }, "tauri": { "allowlist": { @@ -413,4 +413,4 @@ } ] } -} +} \ No newline at end of file From 0083548b00a0bbeb90a103468d450863f53a2d75 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 21 Feb 2024 17:38:11 +0530 Subject: [PATCH 378/864] ci: dev built linux install scripts for testing --- .../installer-latest-experimental-build.sh | 769 ++++++++++++++++++ ...installer-dev.sh => installer-pre-prod.sh} | 0 src-tauri/tauri.conf.json | 8 + 3 files changed, 777 insertions(+) create mode 100755 docs/linux/installer-latest-experimental-build.sh rename docs/linux/{installer-dev.sh => installer-pre-prod.sh} (100%) diff --git a/docs/linux/installer-latest-experimental-build.sh b/docs/linux/installer-latest-experimental-build.sh new file mode 100755 index 00000000..e1d479d3 --- /dev/null +++ b/docs/linux/installer-latest-experimental-build.sh @@ -0,0 +1,769 @@ +#!/bin/bash +set -euo pipefail # Exit immediately if a command exits with a non-zero status. +# Check if jq is installed. This is only used in dev builds and not actual prod builds as jq +# is not a default in most systems +if ! command -v jq &> /dev/null +then + echo "jq is not installed. This check is only present in dev builds" + # Provide installation command based on the package manager. + # Adjust the command according to the target Linux distribution's package manager. + echo "To install jq, run one of the following commands based on your Linux distribution:" + + # Suggest installation commands for different package managers + echo "Ubuntu/Debian: sudo apt-get install jq" + echo "Fedora: sudo dnf install jq" + echo "CentOS/RHEL: sudo yum install jq" + echo "Arch Linux: sudo pacman -S jq" + + # Wait for the user to press any key + read -n 1 -s -r -p "Press any key to continue after installing jq" + echo +fi +# Continue with the rest of the script... +# Define common variables +DESKTOP_DIR=$HOME/.local/share/applications +GITHUB_REPO="phcode-dev/phoenix-desktop" +RELEASES_URL="https://api.github.com/repos/$GITHUB_REPO/releases" +# Fetch the list of releases, assuming the first prerelease in the list is the latest, get the prerelase api url +API_URL=$(wget -qO- "$RELEASES_URL" | jq -r '[.[] | select(.prerelease == true)][0].url') +echo "$API_URL" + +ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" +INSTALL_DIR="$HOME/.phoenix-code" +LINK_DIR="$HOME/.local/bin" +DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries +DESKTOP_ENTRY_NAME="PhoenixCode.desktop" +DESKTOP_APP_NAME="Phoenix Code Experimental Build" +DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" +SCRIPT_NAME="phcode" # Name of the script to invoke the binary +BINARY_NAME="phoenix-code" + +declare -a MIME_TYPES=( + "text/html" + "application/atom+xml" + "application/x-coldfusion" + "text/x-clojure" + "text/coffeescript" + "application/json" + "text/css" + "text/x-diff" + "text/jsx" + "text/markdown" + "application/mathml+xml" + "application/rdf+xml" + "application/rss+xml" + "application/sql" + "image/svg+xml" + "text/x-python" + "application/xml" + "application/vnd.mozilla.xul+xml" + "application/x-yaml" + "text/javascript" + "application/javascript" + "text/mjs" + "application/mjs" + "text/cjs" + "inode/directory" # Added to include directory handling +) + + +# Define color variables for easy reference +GREEN="\e[32m" +YELLOW="\e[33m" +RED="\e[31m" +RESET="\e[0m" + +# Cleanup Function +# +# Purpose: +# The cleanup function is designed to ensure that the script cleans up any temporary +# resources it used during its execution. Specifically, it removes the temporary directory +# created at the beginning of the script, along with all its contents. This is crucial for +# maintaining a clean file system and avoiding the accumulation of unused files. +# +# Behavior: +# - The function targets a temporary directory specified by the `$TMP_DIR` variable. +# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. +# This includes any temporary files, downloaded assets, or other data generated during the script's execution. +# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes +# automatically when the script exits, regardless of the exit point. This includes normal completion, +# errors, or manual termination via signals like SIGINT (Ctrl+C). +# +# Considerations: +# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. +# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. +# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` +# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. +# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within +# `$TMP_DIR` is expendable and safe to delete. +# +# Usage: +# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` +# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` +# is correctly set to the temporary directory path before invoking the function. +# +cleanup() { + rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. +} + +trap cleanup EXIT # Register the cleanup function to be called on script exit. + + +TMP_DIR=$(mktemp -d) + +# Create Invocation Script Function +# +# Purpose: +# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. +# This script is intended to simplify the execution of Phoenix Code by providing a more accessible +# command interface. The generated script is placed in a user-accessible binary directory, making it +# possible to run Phoenix Code from anywhere in the system without needing to specify the full path +# to the binary. +# +# Parameters: +# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. +# - script_name: The name to be given to the invocation script. This name is used both for the +# script file itself and for the symlink created in the user's binary directory. +# - link_dir: The directory where a symlink to the invocation script will be placed, typically +# a location in the user's PATH, such as ~/.local/bin, for easy access. +# +# Behavior: +# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. +# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a +# command to execute the Phoenix Code binary with any passed arguments ("$@"). +# 3. Sets executable permissions on the newly created script. +# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. +# +# Considerations: +# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' +# does not conflict with existing files in these directories to prevent unintended overwrites. +# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes +# these directories are already created and accessible. +# - The generated script includes a warning comment advising against deletion, as it is +# essential for the proper functioning of Phoenix Code when invoked through this script. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# after the binary has been placed in its final location. It should not be called arbitrarily, as it +# assumes a specific setup and context established by the installer script. +# +create_invocation_script() { + local binary_path="$1" + local script_name="$2" + local link_dir="$3" + + echo "Creating an invocation script for the binary..." + # Start of the generated script + echo "#!/bin/bash" > "$binary_path/$script_name.sh" + # Add a warning comment about the script being auto-generated + echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" + echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" + chmod +x "$binary_path/$script_name" + + echo "Copying the invocation script to $link_dir..." + mkdir -p "$link_dir" # Ensure the directory exists + cp "$binary_path/$script_name" "$link_dir/$script_name" + + echo -e "Invocation script created at: $link_dir/$script_name" +} +# Install Dependencies Function +# +# Purpose: +# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. +# This function identifies the user's Linux distribution and installs the appropriate packages +# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and +# Arch Linux distributions. +# +# Behavior: +# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. +# If the command fails, it prompts the user to enter their password for `sudo` access. +# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. +# 3. Based on the identified distribution, executes the appropriate package manager command +# with the required packages. Supported package managers are `apt` for Debian-based systems, +# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. +# 4. Updates the package index (if applicable) and installs the packages. +# +# Considerations: +# - The function requires internet access to fetch package information and install packages. +# - It assumes that the user has `sudo` privileges to install packages system-wide. +# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, +# this function must be updated accordingly. +# - Unsupported distributions will result in an error message and termination of the script, +# as the required dependencies cannot be installed automatically. +# - This function does not handle potential errors from package installation commands. It's +# recommended to monitor the output for any issues that may require manual intervention. +# +# Usage: +# This function is intended to be called during the Phoenix Code installation process, typically +# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites +# are met for a successful Phoenix Code execution. +# +install_dependencies() { + echo "Attempting to install required dependencies..." + + # Inform the user that the next steps require administrative access + echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." + + # Check if the script can execute sudo commands without interaction + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed with the installation of dependencies." + fi + + # Attempt to identify the Linux distribution + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO=$ID + else + echo "Unable to identify the operating system." + exit 1 + fi + + # Install dependencies based on the distribution + case "$DISTRO" in + ubuntu|debian|linuxmint) + echo "Detected an Ubuntu/Debian based distribution." + sudo apt update + sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + gstreamer1.0-tools + ;; + fedora|rhel|centos) + echo "Detected a Fedora/Red Hat based distribution." + sudo dnf install webkit2gtk3 gtk3 \ + gstreamer1-plugins-base gstreamer1-plugins-good + ;; + arch|manjaro) + echo "Detected an Arch Linux based distribution." + sudo pacman -Syu + sudo pacman -S webkit2gtk gtk3 + ;; + *) + echo "Unsupported distribution. Please manually install the required dependencies." + exit 1 + ;; + esac +} +# Verify and Install Dependencies Function +# +# Purpose: +# This function is responsible for verifying if the Phoenix Code application can be successfully +# launched with the current set of installed dependencies. If the initial verification fails, it +# attempts to install the necessary dependencies and then re-verifies the application launch. +# +# Behavior: +# 1. Changes the current directory to the temporary directory where Phoenix Code is located. +# 2. Sets the executable permission for the Phoenix Code binary and attempts to run it with a +# verification-specific command (e.g., `--runVerify`). This step is intended to check if the +# application can start without installing additional dependencies. +# 3. If the initial verification succeeds, the function exits with a success status (0), indicating +# no further action is needed. +# 4. If the initial verification fails, the function proceeds to invoke `install_dependencies` to +# install any missing dependencies specific to the user's Linux distribution. +# 5. After installing dependencies, it attempts to verify the application launch again. If this +# second attempt succeeds, the function exits with a success status (0). +# 6. If the verification fails even after installing dependencies, the function prints an error +# message advising the user to check the application requirements or contact support, and +# exits with an error status (1). +# 7. Finally, the function ensures to change back to the original directory where the script was +# invoked, preserving the user's shell environment. +# +# Considerations: +# - The function assumes that the Phoenix Code binary is located in a temporary directory and +# that this directory is correctly set in the `$TMP_DIR` variable. +# - It relies on the Phoenix Code binary supporting a `--runVerify` command or equivalent for +# verification purposes. If such a command is not available, this part of the function needs +# adjustment. +# - Dependency installation requires administrative privileges; hence, the user might be prompted +# for a password to allow `sudo` operations. +# - The function does not handle all possible error scenarios during dependency installation. +# Users should monitor the output for potential issues that might need manual intervention. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# before finalizing the installation, to ensure that all system requirements are met for the +# application to run properly. +# +verify_and_install_dependencies() { + cd "$TMP_DIR/phoenix-code" + # Ensure the binary is executable + chmod +x "./phoenix-code" + # First attempt to verify the application launch + if ./phoenix-code --runVerify; then + echo "Application launch verification successful." + return 0 # Exit the function successfully if verification succeeds + else + echo "Initial verification failed. Attempting to install dependencies..." + install_dependencies # Function to install required dependencies + fi + + # Second attempt to verify the application launch after installing dependencies + if ./phoenix-code --runVerify; then + echo "Application launch verification successful after installing dependencies." + cd - + return 0 # Exit the function successfully if verification succeeds + else + echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." + cd - + return 1 # Return an error code to indicate failure + fi +} +# Set Phoenix Code as the default application for specified MIME types +set_default_application() { + local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file + + for mime_type in "${MIME_TYPES[@]}"; do + xdg-mime default "$desktop_file" "$mime_type" + done + echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" +} + +# Copy Files to Destination Function +# +# Purpose: +# This function is responsible for setting up the final installation directory for Phoenix Code, +# moving the necessary files into place, creating the invocation script, and setting up the desktop +# entry for the application. It ensures that all components of Phoenix Code are correctly installed +# and configured in the user's environment. +# +# Behavior: +# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files +# will reside. +# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. +# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from +# the temporary directory (`$TMP_DIR`) to the installation directory. +# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. +# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. +# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. +# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and +# launchers, and places this file in the desktop entry directory. +# 8. Updates the system's desktop database to ensure the new application entry is recognized and available +# in application menus and launchers. This step might involve commands like `update-desktop-database` +# or `kbuildsycoca5`, depending on the desktop environment. +# +# Considerations: +# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and +# that this directory is correctly set. +# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and +# accessible. If these variables are unset or incorrect, the function may not perform as intended. +# - Administrative privileges may be required for certain operations, such as updating the desktop database +# or setting permissions, depending on the system's configuration. +# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function +# does perform significant file system operations that could potentially conflict with existing user data +# or system settings. +# +# Usage: +# This function is intended to be called as part of the Phoenix Code installation process, after the +# application's binary and other necessary files have been prepared in a temporary location. It finalizes +# the installation by placing all components in their appropriate locations within the user's system. +# +copyFilesToDestination(){ + echo "Setting up the installation directory at $INSTALL_DIR..." + mkdir -p "$INSTALL_DIR" + mkdir -p "$DESKTOP_DIR" + echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" + + echo "Moving the necessary files to the installation directory..." + echo -e "Phoenix Code files moved to: $INSTALL_DIR" + mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { + echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" + exit 1 + } + # Move the icon to the installation directory + mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" + + echo "Setting the correct permissions for the executable..." + chmod +x "$INSTALL_DIR/phoenix-code" || { + echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" + exit 1 + } + echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" + + mkdir -p "$LINK_DIR" # Ensure the directory exists + # Call the function to create and copy the invocation script + create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" + # Convert MIME types array to semicolon-separated string for the desktop entry + MIME_TYPES_STRING=$(IFS=";"; echo "${MIME_TYPES[*]}") + echo "Creating desktop entry..." + cat > "$DESKTOP_ENTRY" < /dev/null; then + update-desktop-database "$DESKTOP_DIR" + echo -e "Desktop database updated in: $DESKTOP_DIR" + fi + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi + fi + # Set Phoenix Code as the default application for the MIME types + set_default_application + echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" + +} +downloadLatestReleaseInfo() { + local release_info_file="$TMP_DIR/latest_release.json" + + if [ -f "$release_info_file" ]; then + # Only extract and echo the version number, without any additional messages + grep -Po '"tag_name": "dev-app-v\K[\d.]+(?=")' "$release_info_file" + return + fi + + # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly + >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET} " + wget -qO "$release_info_file" "$API_URL" || { + >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" + exit 1 + } + + # Only extract and echo the version number after successful download + grep -Po '"tag_name": "dev-app-v\K[\d.]+(?=")' "$release_info_file" +} + +# Download Latest Release Information Function +# +# Purpose: +# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function +# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to +# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. +# +# Behavior: +# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary +# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already +# been fetched and proceeds to extract the version number from this file without re-downloading. +# 2. If the release information file does not exist, the function uses `wget` to download the JSON data +# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint +# of the Phoenix Code GitHub repository. +# 3. The JSON data is saved to `latest_release.json` in the temporary directory. +# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular +# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version +# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number +# portion. +# 5. Echoes the extracted version number for use by the calling context. +# +# Considerations: +# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available +# in the execution environment. +# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code +# repository for this function to work as intended. +# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, +# the `grep` pattern used to extract the version number may need to be updated. +# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an +# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the +# latest release information. +# - The function does not perform error handling for the `wget` command. If the download fails, the script may +# exit or behave unexpectedly depending on the `set -e` setting. +# +# Usage: +# This function is intended to be called during the installation or upgrade process to determine the latest +# version of Phoenix Code. The extracted version number can be used to compare with the currently installed +# version and decide whether an upgrade is necessary. +# +downloadAndInstall(){ + echo "Using temporary directory $TMP_DIR for processing" + downloadLatestReleaseInfo > /dev/null + CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') + echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" + + BEST_MATCH_URL="" + BEST_MATCH_VERSION=0 + echo "Searching for a compatible binary..." + + while read -r BINARY_URL; do + BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') + if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then + BEST_MATCH_URL="$BINARY_URL" + BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" + echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" + fi + done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") + + if [ -z "$BEST_MATCH_URL" ]; then + echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" + exit 1 + fi + + echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { + echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" + exit 1 + } + echo -e "Downloading the icon..." + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { + echo -e "${RED}Failed to download Icon${RESET}"; + exit 1; + } + echo "Extracting the binary to $TMP_DIR..." + tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { + echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" + exit 1 + } + + if [ -f "$TMP_DIR/phoenix-code/phoenix-code-experimental-build" ]; then + echo "The file $TMP_DIR/phoenix-code/phoenix-code-experimental-build exist. Dev build detected." + mv "$TMP_DIR/phoenix-code/phoenix-code-experimental-build" "$TMP_DIR/phoenix-code/phoenix-code" + fi + + # Verify binary execution and install dependencies if necessary + if ! verify_and_install_dependencies; then + echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" + exit 1 + fi +} +# Install Function +# +# Purpose: +# Facilitates the entire installation process of Phoenix Code on the user's system. This includes +# checking for previous installations, downloading and installing the latest version, setting up +# necessary directories, and ensuring that all dependencies are met. It also handles user prompts +# for repair or reinstallation options if Phoenix Code is already installed. +# +# Behavior: +# 1. Checks if Phoenix Code is already installed by looking for specific files or directories +# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main +# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). +# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and +# then reinstalls the application, ensuring the user ends up with the latest version. +# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest +# release and install it. This step involves downloading the binary, setting permissions, and +# moving files to their correct locations. +# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, +# create an invocation script, and perform other necessary post-installation configurations. +# +# Considerations: +# - The function assumes that the user has sufficient permissions to write to the target directories +# and install Phoenix Code. Administrative privileges may be required for certain operations. +# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation +# directory will be replaced. Users should ensure that any custom configurations or data are backed up +# before proceeding. +# - Network connectivity is required to download the latest version of Phoenix Code from the repository. +# - The function does not explicitly handle all potential error scenarios, such as download failures or +# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. +# +# Usage: +# This function is intended to be invoked when the script is run without specific options (e.g., not an +# uninstall or upgrade). It can be directly called from the command line when the user wishes to install +# Phoenix Code, or it may be triggered by default when the script is executed without arguments. +# +install() { + # Check if the application is already installed + if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then + echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" + + # Simplified prompt for reinstall without detailed explanation + read -r -p "Would you like to reinstall it? (y/N): " response + case "$response" in + [Yy]* ) + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + uninstall + downloadAndInstall + copyFilesToDestination + ;; + * ) + echo -e "${RED}Reinstall aborted by the user.${RESET}" + exit 0 + ;; + esac + else + downloadAndInstall + copyFilesToDestination + fi +} + +# Temporary code to clean up earlier beta installations +function uninstallBetaAppImage() { + rm -f "$LINK_DIR"/phoenix_icon.png +} +# Upgrade Function +# +# Purpose: +# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated +# to the latest version available. This function checks the currently installed version against +# the latest version available in the GitHub repository. If a newer version is found, it proceeds +# to download and install the update, effectively replacing the old version with the new one. +# +# Behavior: +# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation +# directory and the invocation script. If not found, it exits with an error message indicating that +# Phoenix Code must be installed before it can be upgraded. +# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version +# check command (e.g., `phoenix-code --version`) and captures the output. +# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` +# function, which retrieves the version number of the latest release. +# 4. Compares the currently installed version with the latest version. If the installed version is older, +# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and +# installation of the new version. +# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. +# +# Considerations: +# - The function relies on the correct implementation of version checking in the Phoenix Code binary. +# The binary must support a command-line option to output its version, and the output format must be +# consistent for correct parsing and comparison. +# - Network connectivity is required to fetch the latest release information from the GitHub repository. +# The upgrade process will fail if the script cannot connect to GitHub. +# - The user must have sufficient permissions to overwrite the existing installation files and to +# execute network requests (e.g., downloading the latest release). +# - The upgrade process replaces the existing installation files. Users should ensure that any +# necessary backups or custom configurations are saved before proceeding with the upgrade. +# +# Usage: +# This function is intended to be called when the user explicitly wants to upgrade their installation +# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the +# script, as defined in the script's main case statement handling command-line arguments. +# +upgrade() { + echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" + + # Ensure Phoenix Code is installed + if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then + echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" + exit 1 + fi + # Get the current installed version + CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) + echo "Current installed version: $CURRENT_VERSION" + + LATEST_VERSION=$(downloadLatestReleaseInfo) + # Now LATEST_VERSION should only contain the version number without extra messages + echo "Latest available version: $LATEST_VERSION" + + # Compare versions and upgrade if the latest version is greater + if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then + echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" + downloadAndInstall + uninstall + copyFilesToDestination + echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" + else + echo "Your Phoenix Code installation is up-to-date." + fi + +} +# Uninstall Function +# +# Purpose: +# Handles the removal of Phoenix Code from the user's system. This function is responsible for +# cleaning up all files, directories, and links created during the installation process, effectively +# reverting any changes made by the installer script. It ensures that Phoenix Code and its components +# are uninstalled cleanly, leaving no residual files or configurations. +# +# Behavior: +# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). +# This step prevents the Phoenix Code command from being accessible after uninstallation. +# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus +# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. +# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. +# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. +# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including +# the main binary, configuration files, and any other related files placed during installation. +# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. +# +# Considerations: +# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately +# reflect the locations used during the installation. If these variables are incorrect, the uninstallation +# process may not remove all components. +# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed +# in system-wide directories. +# - Users should be advised to back up any important data or configurations related to Phoenix Code before +# initiating the uninstallation process, as this function will remove all associated files without recovery options. +# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot +# be reversed through this script. +# +# Usage: +# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. +# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement +# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this +# function is executed to prevent accidental data loss. +# +uninstall() { + echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" + uninstallBetaAppImage + # Remove the invocation script from ~/.local/bin + if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then + echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" + rm "$LINK_DIR/$SCRIPT_NAME" + else + echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" + fi + + # Delete the desktop entry + if [ -f "$DESKTOP_ENTRY" ]; then + echo -e "${YELLOW}Removing desktop entry...${RESET}" + rm "$DESKTOP_ENTRY" + + # Update the desktop database for GNOME, Unity, XFCE, etc. + echo -e "${YELLOW}Updating desktop database...${RESET}" + if command -v update-desktop-database &> /dev/null; then + update-desktop-database "$DESKTOP_DIR" + fi + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi + fi + else + echo -e "${RED}Desktop entry not found. Skipping...${RESET}" + fi + + # Remove the installation directory and its contents + if [ -d "$INSTALL_DIR" ]; then + echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" + rm -rf "$INSTALL_DIR" + else + echo -e "${RED}Installation directory not found. Skipping...${RESET}" + fi + echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" +} + +show_help() { + echo "Usage: $0 [OPTION]" + echo "Install, upgrade, or uninstall Phoenix Code." + echo + echo "Options:" + echo " -h, --help Display this help and exit" + echo " --uninstall Uninstall Phoenix Code" + echo " --upgrade Upgrade Phoenix Code to the latest version" + echo + echo "Without any options, the script will install Phoenix Code." +} +case "${1-}" in + -h|--help) + show_help # Function to show help + ;; + --uninstall) + uninstall # Function to uninstall + ;; + --upgrade) + upgrade # Function to upgrade + ;; + "") + # This case handles when $1 is unset (acts as a default action) + install # Function to install + ;; + *) + # This case handles unexpected arguments + echo "Invalid option: $1" >&2 + show_help # Assuming you have a function to show usage information + exit 1 + ;; +esac diff --git a/docs/linux/installer-dev.sh b/docs/linux/installer-pre-prod.sh similarity index 100% rename from docs/linux/installer-dev.sh rename to docs/linux/installer-pre-prod.sh diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 32e28d04..9f7a08be 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -84,6 +84,14 @@ "-e", "wget -qO- https://updates.phcode.io/linux/installer.sh | bash -s -- --upgrade" ] + }, + { + "name": "run-update-linux-command-dev", + "cmd": "x-terminal-emulator", + "args": [ + "-e", + "wget -qO- https://updates.phcode.io/linux/installer-latest-experimental-build.sh | bash -s -- --upgrade" + ] } ] } From 8f79c7aac0a8ecc2a431165c642af08ea0dd3bdf Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 21 Feb 2024 17:45:19 +0530 Subject: [PATCH 379/864] ci: dev built linux install scripts for testing --- docs/linux/installer-pre-prod.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/linux/installer-pre-prod.sh b/docs/linux/installer-pre-prod.sh index 27614c1c..241361bb 100755 --- a/docs/linux/installer-pre-prod.sh +++ b/docs/linux/installer-pre-prod.sh @@ -9,6 +9,7 @@ INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries DESKTOP_ENTRY_NAME="PhoenixCode.desktop" +DESKTOP_APP_NAME="Phoenix Code" DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" SCRIPT_NAME="phcode" # Name of the script to invoke the binary BINARY_NAME="phoenix-code" @@ -362,7 +363,7 @@ copyFilesToDestination(){ cat > "$DESKTOP_ENTRY" < Date: Thu, 22 Feb 2024 03:37:26 +0000 Subject: [PATCH 380/864] ci: update phcode version to 3.3.9 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 01899298..b41abf0b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.8", + "version": "3.3.9", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "17302c26ef6024a73bef53e8007c536f29bd2f47" + "commit": "d3e1065d194e348ff0b3db3d3512f78ce855f1a7" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 0b08a1f7..6ea36cb4 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.8" +version = "3.3.9" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 9f7a08be..904d1707 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.8" + "version": "3.3.9" }, "tauri": { "allowlist": { From 1804667a9835b3a2686e94e068103fbd89e10b68 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 22 Feb 2024 03:39:53 +0000 Subject: [PATCH 381/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 569800b8..9318d5ad 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.3.7", - "notes": "Testing updates.", - "pub_date": "2024-02-21T07:24:54.431Z", + "version": "3.3.8", + "notes": "## test update \r\ntesting", + "pub_date": "2024-02-21T11:18:27.347Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtTQ1RsRnFhVlJoVU1mbGZ0eU4zL056RTMzczZONTBUbG9DZ21uNldlNFpOQS9LSlNod3Vub21OMFJxNVh1NzJlelpPYmRMamIzUG9CelJCZGlkbWdnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDk5MDEyCWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuN19hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKTTNNTEVUYjZJUUo4VERHaUFnK250M0JYL0NNQWVVWmxXNENPV0gxR0g0YnJLaVBmVndsYW5mNlNPOEtnVWUxbDNva1ZvYzlJZmJ4bnk1MW1DZnZ5Q0E9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.7/phoenix-code-experimental-build_3.3.7_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZaalV2YkpsNnhDdFFVWnBxMXdHbFI4b2FIbS95MTNLZG5VOWhmUmpjd05xcWZoTG1wbVJCYzBlbDNKUnhiL3hxSkFieXJGSktPd20vdWcrbFNXQ0FFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTEyMzk5CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuOF9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKV244VkVTNnBjMkdvdEl2WlhOU0pKbzM4c0FxZkpCWG9PY2V4cFI5KzlOdXRoeDVic3NhRjZWaUpkQnh2UTEyaHoyVElMUEYzQ1JpWWZaRzRxMjhYQmc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.8/phoenix-code-experimental-build_3.3.8_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5aUmw2TitZTmtVb2VCdEgweEQ5VE1UZUQ0cTdYZk8xOUNnRFB2c09sano2akR2NXFncStLYU5seEswTGZ1M01MRmtWTEhXZktNYUVNaFRRbVY1Z0E4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDk5MDYxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuN194NjQtc2V0dXAubnNpcy56aXAKblNsV205Umd6eityQTQ4d2N6a01ibnRPODhDaThqaGJ6VzhsbThRZjB1NmNsakRIUlhBZ3N2WUZvdFFTUEwrOGVwTmRFSUl2WkNQMFN4Nktod0VvQXc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.7/Phoenix.Code.Experimental.Build_3.3.7_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRESkRXZHZ1UU9PaUNJM3hOTGwvbEdVMHBWMG40U3Z5MlY5Smd3SVFkTTlmWUhlbUdhUUsxWU1QazFJblVxYjAvVkNOZmVwdVp6bWd0N2lvN3lHeGdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTEyNDA1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuOF94NjQtc2V0dXAubnNpcy56aXAKeXZPM2R5N0l1ZUxpcG5kaUhjbktrYksrMkNqMTlWOW9kVGRlVnlGSWcyUXREOHJ2c1FvZERkWWt6bUdwSHpEWnBLMTNaa0VXVjdqSmI0Wm9uVjVpRHc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.8/Phoenix.Code.Experimental.Build_3.3.8_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlQNHJSWDJUK3BSS211Y0I2UE9MZGxUWE1yVEJOUEZzR3hOMFltYWFtV3B6K3h3M1hKK3ZGaWcySklRaTdtbVNnalRtU084V1l5RDArUldsWmdFR3dNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NDk5NTcyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cm9jUUovNlBvL0ZjbG05WXhDeXJ1TEdJZGhPSmNmWGpwRXJicm1PdFdYWWdxNGRpTzg1eDRVQy9KeENyd215WmRsbzYxbG81cVlqdDdXSWE1VU1oOUNRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.7/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZTbHNiTkVhU2tZM0RLV2JzVFF2bTBrcW5vWWNXRE9kclVxREVGOXdESjg3OWZocWh5ZzRMOWc4TDRiTjIzR3FIMFNVeGJ3T0J0WngzNlpKb1ZSbVFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTEzMzk5CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClVPZkRRZFp4Z1RmYkt2MFNBR1BNZnBNTm1MUk5mYTBiU0lSMTFCOWM3aEExeHUwZ1EwVWZ2Sjk5R09YTXVTYUxNeHI4ZTZPMDBmZVRTRDVxcDdGaUJ3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.8/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlYVGVybzNWTEhNU1ZKTlBxZzV3ZkF2WVZTbWUxbUsycWpmY3B3U0FrN0VEMThRS1lqTFo5UlhjTkY0a2JJcWxPbmNZQjhMQkJRV1E3ZWdscmVDcmdBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTAwMjgzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnhnSkhieFhmL2lnNnUwemhIaHkvbHJBTlN2cEtGSWZVWlpEa1FaS1ZxT05VL2EwRmtPTnV2NnMwOHg1K0FtSGZEdCtCbFFTai81aHFFcFBPZ01UWkFBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.7/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBsK3htZDBRWHZjUDFqcSs4aWJRby9nTDlTQmxnVWVLclpsK2p4eFhWYnhPZVU2Y0Z5RUR4dDNrdlRGWHQ2UGxFbjZCSi9NUEwreTBQYzBYb0wvcFE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTE0Mjk4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cm5XL1JwUkRJNDhuQ3YxUXpTMkQyTjRVWUg1ZTRmRWZackt4UXQ1aGJnK2hBZ0lQZXBIT0VMQlBMeGRjRkwyK0VMMy9RYUozWlBnNU9xTGIybTFFSEFnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.8/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From ab89ef255939ff2e7f688b8050d71e4e23c5c2b8 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 22 Feb 2024 14:25:13 +0530 Subject: [PATCH 382/864] fix: running installer from non-gui sessions was failing --- docs/linux/installer-pre-prod.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/linux/installer-pre-prod.sh b/docs/linux/installer-pre-prod.sh index 241361bb..d36ecc46 100755 --- a/docs/linux/installer-pre-prod.sh +++ b/docs/linux/installer-pre-prod.sh @@ -717,6 +717,13 @@ show_help() { echo echo "Without any options, the script will install Phoenix Code." } + +# Check for GUI session by looking for DISPLAY or WAYLAND_DISPLAY variables +if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then + echo "This script should only be run from terminals in GUI sessions." + exit 1 +fi + case "${1-}" in -h|--help) show_help # Function to show help From 63aae259dfe1330cbd81fb190359f065677ac4e1 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 22 Feb 2024 15:02:51 +0530 Subject: [PATCH 383/864] fix: check for ui session --- docs/linux/installer-latest-experimental-build.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/linux/installer-latest-experimental-build.sh b/docs/linux/installer-latest-experimental-build.sh index e1d479d3..0a94a543 100755 --- a/docs/linux/installer-latest-experimental-build.sh +++ b/docs/linux/installer-latest-experimental-build.sh @@ -746,6 +746,12 @@ show_help() { echo echo "Without any options, the script will install Phoenix Code." } +# Check for GUI session by looking for DISPLAY or WAYLAND_DISPLAY variables +if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then + echo "This script should only be run from terminals in GUI sessions." + exit 1 +fi + case "${1-}" in -h|--help) show_help # Function to show help From 2c93cfa1daebbd2f7b33049eba92710187ea3507 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 22 Feb 2024 10:52:10 +0000 Subject: [PATCH 384/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 9318d5ad..cb54502f 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.3.8", - "notes": "## test update \r\ntesting", - "pub_date": "2024-02-21T11:18:27.347Z", + "version": "3.3.9", + "notes": "## Test auto updates\r\ntest release", + "pub_date": "2024-02-22T04:09:02.909Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZaalV2YkpsNnhDdFFVWnBxMXdHbFI4b2FIbS95MTNLZG5VOWhmUmpjd05xcWZoTG1wbVJCYzBlbDNKUnhiL3hxSkFieXJGSktPd20vdWcrbFNXQ0FFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTEyMzk5CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuOF9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKV244VkVTNnBjMkdvdEl2WlhOU0pKbzM4c0FxZkpCWG9PY2V4cFI5KzlOdXRoeDVic3NhRjZWaUpkQnh2UTEyaHoyVElMUEYzQ1JpWWZaRzRxMjhYQmc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.8/phoenix-code-experimental-build_3.3.8_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZ4cE1ENXZ4RUtqVjV5Nkc2TURMYTJhNFFoeGhCTkJqYjBnQWdrbXA3S0kvdzByT3BFOCt1TjV4WUxvUUhzR1BvaTcyb3VzTTdCRE02WjJLU1Q5QWdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTc0MDE4CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuOV9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKZm4wd1JCbHkyY05TQ1lXay9FL3JXYjRDdHdmcWhKWGsrSm5LdVRBNUpkMm9vMnRFTE14MFJBMGhnWHNrTlV1MXVTMFVMVU45bk9LdGR1MmJnT2V4RHc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.9/phoenix-code-experimental-build_3.3.9_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRESkRXZHZ1UU9PaUNJM3hOTGwvbEdVMHBWMG40U3Z5MlY5Smd3SVFkTTlmWUhlbUdhUUsxWU1QazFJblVxYjAvVkNOZmVwdVp6bWd0N2lvN3lHeGdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTEyNDA1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuOF94NjQtc2V0dXAubnNpcy56aXAKeXZPM2R5N0l1ZUxpcG5kaUhjbktrYksrMkNqMTlWOW9kVGRlVnlGSWcyUXREOHJ2c1FvZERkWWt6bUdwSHpEWnBLMTNaa0VXVjdqSmI0Wm9uVjVpRHc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.8/Phoenix.Code.Experimental.Build_3.3.8_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlWbk5OZDJoMUtvRy94SFF2SjlZaCtzTVBqUVk2YXpvR3RBZGM5QkZ3dEx1SnFXZ01KSDV2SEw0bmx4ejEvWENkUUlTYXpyYW9SUkhSN3I5WFVHSHdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTc0MTYxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuOV94NjQtc2V0dXAubnNpcy56aXAKSlExUnVId0lvYURPZGhxN2UxSHlOQmgwVUtqYzBVSmZRWDZrclBLSXNpTitYb3NndTJwUkxXMnFrUlFuSi9Ya3ZWMk5oRFZLZmlpWXZKWWl1Yit5QVE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.9/Phoenix.Code.Experimental.Build_3.3.9_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZTbHNiTkVhU2tZM0RLV2JzVFF2bTBrcW5vWWNXRE9kclVxREVGOXdESjg3OWZocWh5ZzRMOWc4TDRiTjIzR3FIMFNVeGJ3T0J0WngzNlpKb1ZSbVFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTEzMzk5CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClVPZkRRZFp4Z1RmYkt2MFNBR1BNZnBNTm1MUk5mYTBiU0lSMTFCOWM3aEExeHUwZ1EwVWZ2Sjk5R09YTXVTYUxNeHI4ZTZPMDBmZVRTRDVxcDdGaUJ3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.8/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm0zZk5FakhvNWpKaFJ4ZEdYeXAyNWZjV2YreDJ0S2ttU3B4VDhPM1lBZTFGeDJrNDlpS0o3VmNUR0pTMS9ka2xtTGN3QWJIenRJN0plTVN6TW5VR2c4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTc0Mzc0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmluVHVGTThpU1hWRDV2czlSdHNVdERWblhOTnFIT1djSnlKUFFQOCtwMGhkdDNndjlvUHVzdUFWUGJvWDNiNHFRMlRHYXVYdDFwM1FwWnhHL3ZkNkJBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.9/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBsK3htZDBRWHZjUDFqcSs4aWJRby9nTDlTQmxnVWVLclpsK2p4eFhWYnhPZVU2Y0Z5RUR4dDNrdlRGWHQ2UGxFbjZCSi9NUEwreTBQYzBYb0wvcFE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTE0Mjk4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cm5XL1JwUkRJNDhuQ3YxUXpTMkQyTjRVWUg1ZTRmRWZackt4UXQ1aGJnK2hBZ0lQZXBIT0VMQlBMeGRjRkwyK0VMMy9RYUozWlBnNU9xTGIybTFFSEFnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.8/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhGUTVxbGxDUVpKTFhZZ3lTUHRjbWtwbVZMNnRzOU5UYzVhQVlDYm9FNy9TTmhTRXVveFM1ODVqbU8xQUEwNEtVa3hSSWJPWkFkUjA3bmEvRi9rZ0F3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTc0OTM0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjR3cU91UEk2eWphZ01FbzhGemI3Ynluc3RrUmd2dzZIYVVpN1RlTWVBVTArVXlEcCtBMzY3SzgwejcxZUtra0lYZEZqa2gxNUtRRkc4bDdndFVBR0JRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.9/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 43138dd6061f9376cc932832b0b395e246097a8b Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 22 Feb 2024 20:49:22 +0530 Subject: [PATCH 385/864] chore: add recursive-copy-unix exec command in tauri --- src-tauri/Cargo.lock | 2 +- src-tauri/tauri.conf.json | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fef394b6..acee3a77 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2742,7 +2742,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.3.6" +version = "3.3.9" dependencies = [ "clipboard-files", "fix-path-env", diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 904d1707..13b1a1c5 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -92,6 +92,19 @@ "-e", "wget -qO- https://updates.phcode.io/linux/installer-latest-experimental-build.sh | bash -s -- --upgrade" ] + }, + { + "name": "recursive-copy-unix", + "cmd": "cp", + "args": [ + "-r", + { + "validator": "\\S*" + }, + { + "validator": "\\S*" + } + ] } ] } From 5cce787a49aeeee8e3bd4e65789477f345a5a9a6 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 23 Feb 2024 11:18:27 +0530 Subject: [PATCH 386/864] chire: add recursive-rm-unix private command --- src-tauri/tauri.conf.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 13b1a1c5..02697440 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -105,6 +105,16 @@ "validator": "\\S*" } ] + }, + { + "name": "recursive-rm-unix", + "cmd": "rm", + "args": [ + "-rf", + { + "validator": "\\S*" + } + ] } ] } From 6c7167f065271b318018a878172dfa032b550463 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 23 Feb 2024 07:27:23 +0000 Subject: [PATCH 387/864] ci: update phcode version to 3.3.10 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b41abf0b..c0f6692c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.9", + "version": "3.3.10", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "d3e1065d194e348ff0b3db3d3512f78ce855f1a7" + "commit": "15c106fda490e05a97732d5e21bfcc78b44861e8" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6ea36cb4..20525a0a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.9" +version = "3.3.10" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 02697440..8c4ebfac 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.9" + "version": "3.3.10" }, "tauri": { "allowlist": { From b63cab21239b687cd83eb62b43c5eab2e009af28 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 23 Feb 2024 07:41:53 +0000 Subject: [PATCH 388/864] ci: update phcode version to 3.4.0 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index c0f6692c..724847d2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.3.10", + "version": "3.4.0", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "15c106fda490e05a97732d5e21bfcc78b44861e8" + "commit": "5c91a6a17c779249bb4c982a864d18699c605674" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 20525a0a..9f7e25ea 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.3.10" +version = "3.4.0" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8c4ebfac..c2f0ebd5 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.3.10" + "version": "3.4.0" }, "tauri": { "allowlist": { From 4ddf0200f8a83ce759eb7442997abeb8aaf74ab3 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 23 Feb 2024 09:04:11 +0000 Subject: [PATCH 389/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index cb54502f..03c47884 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.3.9", - "notes": "## Test auto updates\r\ntest release", - "pub_date": "2024-02-22T04:09:02.909Z", + "version": "3.4.0", + "notes": "## Test Update Pre-release\r\nVery updates, much wow!\r\n\r\n![image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/70cba226-cf7c-4879-82b6-679886c6f1df)\r\n\r\n", + "pub_date": "2024-02-23T08:12:48.581Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZ4cE1ENXZ4RUtqVjV5Nkc2TURMYTJhNFFoeGhCTkJqYjBnQWdrbXA3S0kvdzByT3BFOCt1TjV4WUxvUUhzR1BvaTcyb3VzTTdCRE02WjJLU1Q5QWdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTc0MDE4CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjMuOV9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKZm4wd1JCbHkyY05TQ1lXay9FL3JXYjRDdHdmcWhKWGsrSm5LdVRBNUpkMm9vMnRFTE14MFJBMGhnWHNrTlV1MXVTMFVMVU45bk9LdGR1MmJnT2V4RHc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.9/phoenix-code-experimental-build_3.3.9_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmd4TEpOdjF5YUJRVWxtaWxrYnBMazlxS2VLSHhWTDBTeHFOYjlZRWRXOFpoWUljeFFkVmZkTnF1OWF2eGs0REQyT2pIeFZYSFJ2SW12Y1RlWFFNeWdFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njc0OTQzCWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjQuMF9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKbVZaNHRGRE9pKzZWVVBBNzJkMG9yY29FQVlaYTBwOXJ2dEd1TmJzZ0RPd0dVaCt4TVpVTi9qdlh6SWpiT3BxTjFRZk8wdEtYNkZKWnBrMlJBQytrRFE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.0/phoenix-code-experimental-build_3.4.0_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlWbk5OZDJoMUtvRy94SFF2SjlZaCtzTVBqUVk2YXpvR3RBZGM5QkZ3dEx1SnFXZ01KSDV2SEw0bmx4ejEvWENkUUlTYXpyYW9SUkhSN3I5WFVHSHdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTc0MTYxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjMuOV94NjQtc2V0dXAubnNpcy56aXAKSlExUnVId0lvYURPZGhxN2UxSHlOQmgwVUtqYzBVSmZRWDZrclBLSXNpTitYb3NndTJwUkxXMnFrUlFuSi9Ya3ZWMk5oRFZLZmlpWXZKWWl1Yit5QVE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.9/Phoenix.Code.Experimental.Build_3.3.9_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlkNGgzTm1URHVLNndmY1BHanlueURsQ2RFYnJYak1zZU5Db2pZMTQwRlQ1N0VLWHZnUjlISFJVc1MxT1MxRzFvVHJEbEM4a2JTeU11L1ZWUGlzOVEwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njc1MDQyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjQuMF94NjQtc2V0dXAubnNpcy56aXAKSVFQZGU1Z1JKV0pobTdWSVFMSWp5eElDRWtXbHQ4NGYxSkpDamN6eHV3YXU5MCtabldzS1lBajlGVGxGZDVRamtqS3lpb1VMT0xDNnhNU2RXVm5GREE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.0/Phoenix.Code.Experimental.Build_3.4.0_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm0zZk5FakhvNWpKaFJ4ZEdYeXAyNWZjV2YreDJ0S2ttU3B4VDhPM1lBZTFGeDJrNDlpS0o3VmNUR0pTMS9ka2xtTGN3QWJIenRJN0plTVN6TW5VR2c4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTc0Mzc0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmluVHVGTThpU1hWRDV2czlSdHNVdERWblhOTnFIT1djSnlKUFFQOCtwMGhkdDNndjlvUHVzdUFWUGJvWDNiNHFRMlRHYXVYdDFwM1FwWnhHL3ZkNkJBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.9/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlhZ2U5Y0VGR1p1WHBKRGxES1l5Q1pyeGp0dHcwYUxMd2tSTlNGRmVGQjk4S2FGbkd5QzVVQSs1UXQ1aTE3K1dxUGovUGtIWXZpMi95Y1pMNWlkK3dzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njc1Mjk1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CkszUDA2Zi81VUNRV0thY0cxL2hyZjFjcWVRMklzcHMwQU4xaUhKR3QzU0pMU2VBOWZNczZFaVB0OGhXK015WllFTmNaenZ6eHBoVnNBZ01FVEFCckF3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.0/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhGUTVxbGxDUVpKTFhZZ3lTUHRjbWtwbVZMNnRzOU5UYzVhQVlDYm9FNy9TTmhTRXVveFM1ODVqbU8xQUEwNEtVa3hSSWJPWkFkUjA3bmEvRi9rZ0F3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4NTc0OTM0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjR3cU91UEk2eWphZ01FbzhGemI3Ynluc3RrUmd2dzZIYVVpN1RlTWVBVTArVXlEcCtBMzY3SzgwejcxZUtra0lYZEZqa2gxNUtRRkc4bDdndFVBR0JRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.3.9/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnN1bmhFL1ZPenM2R0FXS0xnbEN0MnFpMlJVeFBhSTlYQWZjL1Y4SmlSb082MHdKQ0xYL09RbU5FcU0xc2E4UUpLMjJxNDdseEJteDVYc2loZHJDL2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njc1OTYwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjZuOXhyZ0FaZGFkUjE2NUZFQ25RaW9EbzNaUjBPVUVmNldRWjJPak1RYWN3Q3pOUU9VUEJaTTV4eGQ3NnRqSFBZYlgxTFhLeWhIcHFhOHdmTFRVUUJRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.0/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From d264303b1964ea3fe4b3a096496e1b79412aaedd Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 23 Feb 2024 10:44:18 +0000 Subject: [PATCH 390/864] ci: update phcode version to 3.4.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 724847d2..107a9499 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.4.0", + "version": "3.4.1", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "5c91a6a17c779249bb4c982a864d18699c605674" + "commit": "ebd430e3cfe76c2b14db0ecec3f7fa38c2fb6ace" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9f7e25ea..0ca945c7 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.4.0" +version = "3.4.1" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c2f0ebd5..e3c930b9 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.4.0" + "version": "3.4.1" }, "tauri": { "allowlist": { From b36e259b909ea2bc0403f752157ccc70b3dde128 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 23 Feb 2024 10:55:52 +0000 Subject: [PATCH 391/864] ci: update phcode version to 3.4.2 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 107a9499..bf5a0221 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.4.1", + "version": "3.4.2", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "ebd430e3cfe76c2b14db0ecec3f7fa38c2fb6ace" + "commit": "b3299ebd75cc4115ac358d7d872d12808a26c1b8" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 0ca945c7..4bb529fd 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.4.1" +version = "3.4.2" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index e3c930b9..2697446f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.4.1" + "version": "3.4.2" }, "tauri": { "allowlist": { From 36f7953bc175a92bceb2dd813e8a18b071abaf0c Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 23 Feb 2024 11:31:32 +0000 Subject: [PATCH 392/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 03c47884..e3189163 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,23 @@ { - "version": "3.4.0", - "notes": "## Test Update Pre-release\r\nVery updates, much wow!\r\n\r\n![image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/70cba226-cf7c-4879-82b6-679886c6f1df)\r\n\r\n", - "pub_date": "2024-02-23T08:12:48.581Z", + "version": "3.4.2", + "notes": "## Test Update Pre-release 2\r\nVery updates, much wow!\r\n\r\n![image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/70cba226-cf7c-4879-82b6-679886c6f1df)\r\n\r\n", + "pub_date": "2024-02-23T11:29:55.983Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmd4TEpOdjF5YUJRVWxtaWxrYnBMazlxS2VLSHhWTDBTeHFOYjlZRWRXOFpoWUljeFFkVmZkTnF1OWF2eGs0REQyT2pIeFZYSFJ2SW12Y1RlWFFNeWdFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njc0OTQzCWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjQuMF9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKbVZaNHRGRE9pKzZWVVBBNzJkMG9yY29FQVlaYTBwOXJ2dEd1TmJzZ0RPd0dVaCt4TVpVTi9qdlh6SWpiT3BxTjFRZk8wdEtYNkZKWnBrMlJBQytrRFE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.0/phoenix-code-experimental-build_3.4.0_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZ1cG9mRzR2T1JFYTBGZ29NRFJzRnpMY25RbG1XbUVEN01zeDhla1NsczFFeEdsc3ZPZlJ2QmVMQlNCRTFVNTFZaitLMFQ1YmtnUVluOU14MXprWEFJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njg2NTU1CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjQuMl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKb0tjMjhYaVluQndWZVViQXovUzd2SXdvZk9kSm9VRm5OZzErZFVmQWVQLzlQTXg3a2R0SVNZamVaQjlGL096OCs4SlBXMFBpQlVuR0lLb0NEVzIwRHc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/phoenix-code-experimental-build_3.4.2_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlkNGgzTm1URHVLNndmY1BHanlueURsQ2RFYnJYak1zZU5Db2pZMTQwRlQ1N0VLWHZnUjlISFJVc1MxT1MxRzFvVHJEbEM4a2JTeU11L1ZWUGlzOVEwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njc1MDQyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjQuMF94NjQtc2V0dXAubnNpcy56aXAKSVFQZGU1Z1JKV0pobTdWSVFMSWp5eElDRWtXbHQ4NGYxSkpDamN6eHV3YXU5MCtabldzS1lBajlGVGxGZDVRamtqS3lpb1VMT0xDNnhNU2RXVm5GREE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.0/Phoenix.Code.Experimental.Build_3.4.0_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtabjlDd0xaQnYrZVFhN3F0c3hmQ3hqQnJSa09jMy9jMW9GVFUwZjNoK3JQdFlEamp3aFpNT1R5YWxoWEdKVWdYYzlpRTI1bjQwSFZMTVNrZTRXS0FNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njg2NzE2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjQuMl94NjQtc2V0dXAubnNpcy56aXAKR2lXNUFXbWExajNuaU1DcnIzbmJwOThqeFc2TjBoRm1lU1BhRHJVSFRVdEpmb0VoZkJHeGhJbTFDNkoxaHVoQ2JienB5cFVISjU5TDBRVG5Hd09TQXc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/Phoenix.Code.Experimental.Build_3.4.2_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlhZ2U5Y0VGR1p1WHBKRGxES1l5Q1pyeGp0dHcwYUxMd2tSTlNGRmVGQjk4S2FGbkd5QzVVQSs1UXQ1aTE3K1dxUGovUGtIWXZpMi95Y1pMNWlkK3dzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njc1Mjk1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CkszUDA2Zi81VUNRV0thY0cxL2hyZjFjcWVRMklzcHMwQU4xaUhKR3QzU0pMU2VBOWZNczZFaVB0OGhXK015WllFTmNaenZ6eHBoVnNBZ01FVEFCckF3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.0/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm4vNFlZMnd5R3dCT0U5N0lxRG5ra3lTeHJSM29iYXRUTGFpWFArVm1oMDRyemJHY0FMM0lxMlFwdzgzNDlyWWIrWUdmUnRVRmhLdkcxeFB1enVicXdZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njg3MTk0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmxTYTJQOWIvdGI3SlU1MkR6TUo3V3pSWVhGSGJ5SE5nbVhXaFoyN2FpK3BnbllsRnZTR1Zicko0dXFqUGkzcm1oMCtwcVZSWTZLM0k2cEh3T1pBVEJnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnN1bmhFL1ZPenM2R0FXS0xnbEN0MnFpMlJVeFBhSTlYQWZjL1Y4SmlSb082MHdKQ0xYL09RbU5FcU0xc2E4UUpLMjJxNDdseEJteDVYc2loZHJDL2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njc1OTYwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjZuOXhyZ0FaZGFkUjE2NUZFQ25RaW9EbzNaUjBPVUVmNldRWjJPak1RYWN3Q3pOUU9VUEJaTTV4eGQ3NnRqSFBZYlgxTFhLeWhIcHFhOHdmTFRVUUJRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.0/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhaaENVcno2QTdCZDRDR3drSnlUVWpoMzZvVHljZWRWWllEaWNnTzI5SHBGOHZ4S1kyK3AyMWJmbHUvQldnaVFEcXZxZ3ZUbWxNYjlYODZzOEIyNVFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njg3NzkwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClhqamdjaDZQMURRYjg5bkJJNVpCOVRKaUJQd3FOSWdBeXJTSnFOYUk3T2hTak1rZ3pSSE1lbWxrK3ljV01xKzJKVEVNRGtVSHBPSWplVGlReDltUkJRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 92fdccbd3fd9a208ccd0d23da389e864ee1d2ed7 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 24 Feb 2024 23:46:14 +0530 Subject: [PATCH 393/864] ci: add installer downlaod url json for phcode.io --- docs/install.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 docs/install.json diff --git a/docs/install.json b/docs/install.json new file mode 100644 index 00000000..dec33e09 --- /dev/null +++ b/docs/install.json @@ -0,0 +1,7 @@ +{ + "phcode.io.DownloadURL": { + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_x64.dmg", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_aarch64.dmg", + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/Phoenix.Code.Experimental.Build_3.4.2_x64-setup.exe" + } +} \ No newline at end of file From 22c4deda94277cdd2ec5412c868591351252008f Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 25 Feb 2024 14:48:22 +0530 Subject: [PATCH 394/864] fix: remove default file association for html and folder --- docs/linux/installer-latest-experimental-build.sh | 5 +++++ docs/linux/installer-pre-prod.sh | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/docs/linux/installer-latest-experimental-build.sh b/docs/linux/installer-latest-experimental-build.sh index 0a94a543..d43a1d00 100755 --- a/docs/linux/installer-latest-experimental-build.sh +++ b/docs/linux/installer-latest-experimental-build.sh @@ -312,6 +312,11 @@ set_default_application() { local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file for mime_type in "${MIME_TYPES[@]}"; do + # Skip setting default application for inode/directory and text/html + if [ "$mime_type" = "inode/directory" ] || [ "$mime_type" = "text/html" ]; then + continue # Skip to the next iteration + fi + xdg-mime default "$desktop_file" "$mime_type" done echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" diff --git a/docs/linux/installer-pre-prod.sh b/docs/linux/installer-pre-prod.sh index d36ecc46..c28b165c 100755 --- a/docs/linux/installer-pre-prod.sh +++ b/docs/linux/installer-pre-prod.sh @@ -288,6 +288,11 @@ set_default_application() { local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file for mime_type in "${MIME_TYPES[@]}"; do + # Skip setting default application for inode/directory and text/html + if [ "$mime_type" = "inode/directory" ] || [ "$mime_type" = "text/html" ]; then + continue # Skip to the next iteration + fi + xdg-mime default "$desktop_file" "$mime_type" done echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" From ef13be7ddd7e0f8af0951f4ee1bb725d5476fdf4 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Tue, 27 Feb 2024 04:46:54 +0000 Subject: [PATCH 395/864] ci: update phcode version to 3.4.3 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index bf5a0221..5078e111 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.4.2", + "version": "3.4.3", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "b3299ebd75cc4115ac358d7d872d12808a26c1b8" + "commit": "8f65060d288a5885765f07960e887ec3bcbbc5bb" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4bb529fd..26f478ae 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.4.2" +version = "3.4.3" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 2697446f..ca6513f3 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.4.2" + "version": "3.4.3" }, "tauri": { "allowlist": { From 90b932db761d70eb6af9642e311465bc4dbb9326 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 27 Feb 2024 14:42:15 +0530 Subject: [PATCH 396/864] feat: update download urls in phcode.io website when new release is published --- .github/workflows/updateNotification.js | 34 ++++++++++++++++++++++++ .github/workflows/updateNotification.yml | 1 + docs/readme.md | 3 +++ 3 files changed, 38 insertions(+) diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js index 9c39da6e..f200183a 100644 --- a/.github/workflows/updateNotification.js +++ b/.github/workflows/updateNotification.js @@ -71,6 +71,24 @@ async function _getLatestJson(releaseAssets) { throw new Error(`Could not locate ${LATEST_JSON_GITHUB_RELEASE} file in github releases.`); } +// "Phoenix.Code.Experimental.Build_3.4.2_x64-setup.exe" +const WINDOWS_X64_NAME_SUFFIX = "_x64-setup.exe"; +// "Phoenix.Code.Experimental.Build_3.4.2_x64.dmg" +const MAC_INTEL_NAME_SUFFIX = "_x64.dmg"; +// "Phoenix.Code.Experimental.Build_3.4.2_aarch64.dmg" +const MAC_M1_NAME_SUFFIX = "_aarch64.dmg"; +function _getDownloadURLByNameSuffix(releaseAssets, suffix) { + for(let releaseAsset of releaseAssets) { + if(releaseAsset.name.endsWith(suffix)){ + // "browser_download_url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/Phoenix.Code.Experimental.Build_3.4.2_x64-setup.exe" + const downloadURL = releaseAsset.browser_download_url; + console.log("Latest json download URL is: ", downloadURL); + return downloadURL; + } + } + throw new Error(`Could not locate ${LATEST_JSON_GITHUB_RELEASE} file in github releases.`); +} + function getCurrentVersion(latestJsonPath) { try{ return JSON.parse(fs.readFileSync(latestJsonPath, 'utf8')).version || '0.0.0'; @@ -144,4 +162,20 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) } else { console.warn("Current version: ", currentVersion, " is higher than the new release version ", latestVersion, " . Ignoring this release update!"); } + + // now write the installer.json for phcode.io website download link updates + const installJsonPath = `${githubWorkspaceRoot}/docs/install.json`; + const windowsDownloadURL = _getDownloadURLByNameSuffix(releaseAssets, WINDOWS_X64_NAME_SUFFIX); + const macM1DownloadURL = _getDownloadURLByNameSuffix(releaseAssets, MAC_M1_NAME_SUFFIX); + const macIntelDownloadURL = _getDownloadURLByNameSuffix(releaseAssets, MAC_INTEL_NAME_SUFFIX); + let installJSON = { + "phcode.io.DownloadURL": { + "windows_x64": windowsDownloadURL, + "mac_m1": macM1DownloadURL, + "mac_intel": macIntelDownloadURL + } + }; + installJSON = JSON.stringify(installJSON, null, 4); + console.log("writing install.json to path: ", installJsonPath, " contents: ", installJSON) + fs.writeFileSync(installJsonPath, installJSON); } \ No newline at end of file diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml index 291f8c5c..e1ef16e1 100644 --- a/.github/workflows/updateNotification.yml +++ b/.github/workflows/updateNotification.yml @@ -40,6 +40,7 @@ jobs: title: '[Release BOT] Update release notification as part of new release ${{ github.ref_name }}' add-paths: | docs/tauri/** + docs/install.json body: | Update release notification as part of new release. Once this Pull request is merges in main branch, please merge it into `update-notifications` branch to trigger update rollout diff --git a/docs/readme.md b/docs/readme.md index b14807d4..202cc41d 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -1,2 +1,5 @@ This folder hosts static website for `updates.phcode.io` which generally sends update notifications to all installed phcode builds. + +* `install.json` file in this folder is used by website `phcode.io` to set download button. This is auto updated + when a new release is published or edited. \ No newline at end of file From 84169aa4a5b7bc0750bf0ab7d9fb1e0323912d13 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 27 Feb 2024 14:51:38 +0530 Subject: [PATCH 397/864] fix: update download urls in phcode.io only in pord releases --- .github/workflows/updateNotification.js | 40 ++++++++++++++++--------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js index f200183a..6d0fe8b4 100644 --- a/.github/workflows/updateNotification.js +++ b/.github/workflows/updateNotification.js @@ -57,6 +57,16 @@ function _identifyUpdateJSONPath(releaseAssets) { return UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH.production; } +function isProdStage(releaseAssets) { + for(let releaseAsset of releaseAssets) { + if(releaseAsset.name.startsWith(DEV_STAGE_PRODUCT_NAME_PREFIX) || + releaseAsset.name.startsWith(PRE_RELEASE_STAGE_PRODUCT_NAME_PREFIX)){ + return false; + } + } + return true; +} + async function _getLatestJson(releaseAssets) { for(let releaseAsset of releaseAssets) { if(releaseAsset.name === LATEST_JSON_GITHUB_RELEASE){ @@ -164,18 +174,20 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) } // now write the installer.json for phcode.io website download link updates - const installJsonPath = `${githubWorkspaceRoot}/docs/install.json`; - const windowsDownloadURL = _getDownloadURLByNameSuffix(releaseAssets, WINDOWS_X64_NAME_SUFFIX); - const macM1DownloadURL = _getDownloadURLByNameSuffix(releaseAssets, MAC_M1_NAME_SUFFIX); - const macIntelDownloadURL = _getDownloadURLByNameSuffix(releaseAssets, MAC_INTEL_NAME_SUFFIX); - let installJSON = { - "phcode.io.DownloadURL": { - "windows_x64": windowsDownloadURL, - "mac_m1": macM1DownloadURL, - "mac_intel": macIntelDownloadURL - } - }; - installJSON = JSON.stringify(installJSON, null, 4); - console.log("writing install.json to path: ", installJsonPath, " contents: ", installJSON) - fs.writeFileSync(installJsonPath, installJSON); + if(isProdStage(releaseAssets)){ + const installJsonPath = `${githubWorkspaceRoot}/docs/install.json`; + const windowsDownloadURL = _getDownloadURLByNameSuffix(releaseAssets, WINDOWS_X64_NAME_SUFFIX); + const macM1DownloadURL = _getDownloadURLByNameSuffix(releaseAssets, MAC_M1_NAME_SUFFIX); + const macIntelDownloadURL = _getDownloadURLByNameSuffix(releaseAssets, MAC_INTEL_NAME_SUFFIX); + let installJSON = { + "phcode.io.DownloadURL": { + "windows_x64": windowsDownloadURL, + "mac_m1": macM1DownloadURL, + "mac_intel": macIntelDownloadURL + } + }; + installJSON = JSON.stringify(installJSON, null, 4); + console.log("writing install.json to path: ", installJsonPath, " contents: ", installJSON) + fs.writeFileSync(installJsonPath, installJSON); + } } \ No newline at end of file From 0a32cfcc5d8e10bea260b62bced75031dacab737 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 27 Feb 2024 16:12:37 +0530 Subject: [PATCH 398/864] fix: echo github cotext --- .github/workflows/updateNotification.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml index e1ef16e1..7809241f 100644 --- a/.github/workflows/updateNotification.yml +++ b/.github/workflows/updateNotification.yml @@ -15,8 +15,10 @@ jobs: steps: - name: Dump GitHub context id: github_context_step + env: + GITHUB_CONTEXT_ECHO: ${{ toJson(github) }} run: | - echo '${{ toJSON(github) }}' + echo '$GITHUB_CONTEXT_ECHO' echo "$GITHUB_REF repo=${{github.event.repository.full_name}}" - uses: actions/checkout@v4 From 516414411747cf00a4a2897f23cd90ecb3724a01 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 27 Feb 2024 16:17:43 +0530 Subject: [PATCH 399/864] fix: echo github cotext --- .github/workflows/updateNotification.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml index 7809241f..2ca52bac 100644 --- a/.github/workflows/updateNotification.yml +++ b/.github/workflows/updateNotification.yml @@ -13,12 +13,14 @@ jobs: contents: write pull-requests: write steps: - - name: Dump GitHub context + - name: Print GitHub context + uses: actions/github-script@v5 + with: + script: | + console.log(JSON.stringify(github, null, 2)) + - name: GitHub REF id: github_context_step - env: - GITHUB_CONTEXT_ECHO: ${{ toJson(github) }} run: | - echo '$GITHUB_CONTEXT_ECHO' echo "$GITHUB_REF repo=${{github.event.repository.full_name}}" - uses: actions/checkout@v4 From 853d8cccbbb348141e69f01345e74034ada00bb2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 10:48:54 +0000 Subject: [PATCH 400/864] chore(deps): update actions/github-script action to v7 --- .github/workflows/updateNotification.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml index 2ca52bac..69f026e4 100644 --- a/.github/workflows/updateNotification.yml +++ b/.github/workflows/updateNotification.yml @@ -14,7 +14,7 @@ jobs: pull-requests: write steps: - name: Print GitHub context - uses: actions/github-script@v5 + uses: actions/github-script@v7 with: script: | console.log(JSON.stringify(github, null, 2)) From 4575361e6560d8a273192cfb1ac30e7131eff2f5 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Tue, 27 Feb 2024 10:59:59 +0000 Subject: [PATCH 401/864] ci: update phcode version to 3.4.4 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 5078e111..a23d8e16 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.4.3", + "version": "3.4.4", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "8f65060d288a5885765f07960e887ec3bcbbc5bb" + "commit": "214adae16c8ae15f240b239cffac95d11ebda23d" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 26f478ae..33951edc 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.4.3" +version = "3.4.4" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ca6513f3..21a4266d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.4.3" + "version": "3.4.4" }, "tauri": { "allowlist": { From a217da7357a816e5409f004ef8c87adc08c6f7ca Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 27 Feb 2024 13:05:17 +0000 Subject: [PATCH 402/864] ci: tauri release update notification json --- docs/install.json | 10 +++++----- docs/tauri/update-latest-stable-prod.json | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/install.json b/docs/install.json index dec33e09..0a37c029 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,7 +1,7 @@ { - "phcode.io.DownloadURL": { - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_x64.dmg", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_aarch64.dmg", - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/Phoenix.Code.Experimental.Build_3.4.2_x64-setup.exe" - } + "phcode.io.DownloadURL": { + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64.dmg" + } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index d8756ab6..9d98fe94 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,23 +1,23 @@ { - "version": "3.3.3", - "notes": "Beta release 1", - "pub_date": "2024-02-11T16:53:25.316Z", + "version": "3.4.4", + "notes": "# 🚀 Phoenix Code Beta 2 is here 🚀 \r\n\r\nWe have addressed most of the issues and feedback we got from beta 1.\r\nWhat's New:\r\n\r\n1. Windows native apps are now available along with Mac and Linux.\r\n1. Linux users get a boost! New native binaries are available for a wider range of Linux distributions(Ubuntu/Debian, Fedora, Arch Linux and much more), offering better performance and broader support compared to the previous AppImage format.\r\n1. Stability and bug fixes.", + "pub_date": "2024-02-27T11:48:54.612Z", "platforms": { "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5CVUsvT0FTdzdaaGpMc1VybXdsQldEYmhraHVRTjhpa1RsTEV2Y25tMDFBYnlxUW1LVHRHWDRZMkI5UUwxc04vclFJVEtIT3M1bVhVQjMrSUxEZlFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5NDUwCWZpbGU6cGhvZW5peC1jb2RlXzMuMy4zX2FtZDY0LkFwcEltYWdlLnRhci5negp5OGRiQzU1eUgwMk53RjJkWVk1L1lUNGtUVXRtV3FsOExKUlZDQVdHYWtBTlRpRGZsb0hGN3hlS3J6bTVESmFmR1ZLdmhmL0xxclVuWlB4RUpEd29DUT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/phoenix-code_3.3.3_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnQxU2FsYmR2NzRqWlJJN0JEUUhmUG40YXVuRjQ1V3dlbGsxbDlWQ3grRitucVhKU0dWdnRXOGRxdEJPL0c5T1B3THFsTy95Y2NibFhoSmFORzBNQlFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5MDMzMzM4CWZpbGU6cGhvZW5peC1jb2RlXzMuNC40X2FtZDY0LkFwcEltYWdlLnRhci5negpyZlVhWVcxZWZuSlBrTlNqNnhob21OL3Q5cExqTUNoZSs1RmJKVG4xZkRGdkljQmpPZHd4QUdlOUlaNzVpNzVtSUhyeUNXR1RSS0h2d2FqU2xZOFRCQT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/phoenix-code_3.4.4_amd64.AppImage.tar.gz" }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWml3SXNZeTNDd0gyR2ttZjNaK3NOL0NXckJ5YkpBYVRRYmIyVjd6V2JmZERaVU9lUjdPQmUvV2NZKzFhejRlK1JUT3pyWms5ZlhkcGIrMGRuNmRkQVFBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5NTMyCWZpbGU6UGhvZW5peCBDb2RlXzMuMy4zX3g2NC1zZXR1cC5uc2lzLnppcApWM1FsUTNxMXcxdWpDeForendMZS9YRHNyY1lCUHN4ZXBqc3BmMVRJanpUT0hLRHlqTjBJZExJMWwyb2xYaFZoeDJZODVwaVZaTVV4VVovVzF5NmpEQT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_3.3.3_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnIrdkdnMGJPb1dwYis5ZkRLMkYveklkUTNBaHFFMVp4SE40WW1KaS80WUVQN25HWks0NG9OTXIwcmFWY2M4S0tYRkNJTWloVmdGeTc4TVJRUElncUFzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5MDMzNDAzCWZpbGU6UGhvZW5peCBDb2RlXzMuNC40X3g2NC1zZXR1cC5uc2lzLnppcApDWG9TV21lTVRwNG00YTVjTks4YTRiNjZqaVRIY05tcno4eFREOXhGSXNEUFRHMHNhTktXM0J4Vys3cnhxRDM0eCtRKzZzZDRtREVUWERyeHB1TTJBQT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnMwT04xZ1lRNzE5SStpNUVNdTY4N3h4cmRvTWFEcDRFRkEyTjVoa0lSSG1NaDRsQXBGdEVtcEx2eXlHQUFaN0dXejRHZ3NINGNqLzl2S2V4KzN6RXdFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjY5ODY2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKL1pudFI0NWlBcUpkQU9JS1g4RDd4eE9EeWZsdG5PSWVvRDFzTDVrYmk5b2kwaTNNbzYrU1IzdGg2elUveS9OTkU1cHQzUEdLMllGM0U4bExvTi9lRGc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRyaS92SXhWbll4MEZUN1RwMEpHN0xuOWRLd2FDaklMeXdSZmo3VmNVWENPZXF4NXdxWUhaU1k1YjRmV2NSSC9YUkMyUlFCMkQ5aVBhVXJuTTZyRlFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5MDMzNjc1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKUlpoNUxTU0l1K2VqT3ZLd2tMTUpCQzdKb3Zmaytta0lyOVU2N01UVXFTS29TSnlEQkVDZlNHUWNkb2MvWWJMb0FlUXVEL3pnSC9xSkNrNlJFaTdpQmc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlZOXpJMDlscVdQS0s5VGhsRWV4YWZKTWdkQ3k0bmFPd2lvRDY5Z2hUZ0d4L25pMFExKzc1ZTZEdTZjWXNkUlcrcVdFY1hVcE1ieWZkNEx0dWd4SndvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA3NjcwMzk1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKYkRPaFRGYTl5REg3V0puSVZjRkd3ZVdncG03ZjlUNkJjS1lzTjVnSXIwVG5veTIwMFRwUkhBalF0aFJub0ZvTzNVUGhHcUorRHBaUVpOVFBwZ2djQXc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.3.3/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnV6d0F1WXNuaDhmcUVFemlEUUlGVVJFWkptNThaZjFiK1QxYnNEbkFYL0gyRFRvdERPOFhwdXZWTE9HY0x0eDdzVS9XeklKUjRnR1J0SjBvaUF0dVE0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5MDM0MzQ4CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKVE1IcTNHZDF3QkFjQ2Y0N1pCNER5YXkyT1hmYlZWREVDMUlKT01VZURvbEFmQVl3NW1DRmx3Y0Fsbi9kcEZRQ3lmY1dzcjZYRCs4eEhpNGpXYUJ5QlE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 6058e69041a0add4090125e73202806d035b8221 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 27 Feb 2024 18:40:55 +0530 Subject: [PATCH 403/864] chore: move new linux installer script to prod --- docs/linux/installer-pre-prod.sh | 752 ---------------------------- docs/linux/installer.sh | 820 ++++++++++++++++++++++++++----- 2 files changed, 710 insertions(+), 862 deletions(-) delete mode 100755 docs/linux/installer-pre-prod.sh mode change 100644 => 100755 docs/linux/installer.sh diff --git a/docs/linux/installer-pre-prod.sh b/docs/linux/installer-pre-prod.sh deleted file mode 100755 index c28b165c..00000000 --- a/docs/linux/installer-pre-prod.sh +++ /dev/null @@ -1,752 +0,0 @@ -#!/bin/bash -set -euo pipefail # Exit immediately if a command exits with a non-zero status. -# Define common variables -DESKTOP_DIR=$HOME/.local/share/applications -GITHUB_REPO="phcode-dev/phoenix-desktop" -API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" -ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" -INSTALL_DIR="$HOME/.phoenix-code" -LINK_DIR="$HOME/.local/bin" -DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries -DESKTOP_ENTRY_NAME="PhoenixCode.desktop" -DESKTOP_APP_NAME="Phoenix Code" -DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" -SCRIPT_NAME="phcode" # Name of the script to invoke the binary -BINARY_NAME="phoenix-code" - -declare -a MIME_TYPES=( - "text/html" - "application/atom+xml" - "application/x-coldfusion" - "text/x-clojure" - "text/coffeescript" - "application/json" - "text/css" - "text/x-diff" - "text/jsx" - "text/markdown" - "application/mathml+xml" - "application/rdf+xml" - "application/rss+xml" - "application/sql" - "image/svg+xml" - "text/x-python" - "application/xml" - "application/vnd.mozilla.xul+xml" - "application/x-yaml" - "text/javascript" - "application/javascript" - "text/mjs" - "application/mjs" - "text/cjs" - "inode/directory" # Added to include directory handling -) - - -# Define color variables for easy reference -GREEN="\e[32m" -YELLOW="\e[33m" -RED="\e[31m" -RESET="\e[0m" - -# Cleanup Function -# -# Purpose: -# The cleanup function is designed to ensure that the script cleans up any temporary -# resources it used during its execution. Specifically, it removes the temporary directory -# created at the beginning of the script, along with all its contents. This is crucial for -# maintaining a clean file system and avoiding the accumulation of unused files. -# -# Behavior: -# - The function targets a temporary directory specified by the `$TMP_DIR` variable. -# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. -# This includes any temporary files, downloaded assets, or other data generated during the script's execution. -# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes -# automatically when the script exits, regardless of the exit point. This includes normal completion, -# errors, or manual termination via signals like SIGINT (Ctrl+C). -# -# Considerations: -# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. -# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. -# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` -# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. -# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within -# `$TMP_DIR` is expendable and safe to delete. -# -# Usage: -# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` -# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` -# is correctly set to the temporary directory path before invoking the function. -# -cleanup() { - rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. -} - -trap cleanup EXIT # Register the cleanup function to be called on script exit. - - -TMP_DIR=$(mktemp -d) - -# Create Invocation Script Function -# -# Purpose: -# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. -# This script is intended to simplify the execution of Phoenix Code by providing a more accessible -# command interface. The generated script is placed in a user-accessible binary directory, making it -# possible to run Phoenix Code from anywhere in the system without needing to specify the full path -# to the binary. -# -# Parameters: -# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. -# - script_name: The name to be given to the invocation script. This name is used both for the -# script file itself and for the symlink created in the user's binary directory. -# - link_dir: The directory where a symlink to the invocation script will be placed, typically -# a location in the user's PATH, such as ~/.local/bin, for easy access. -# -# Behavior: -# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. -# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a -# command to execute the Phoenix Code binary with any passed arguments ("$@"). -# 3. Sets executable permissions on the newly created script. -# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. -# -# Considerations: -# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' -# does not conflict with existing files in these directories to prevent unintended overwrites. -# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes -# these directories are already created and accessible. -# - The generated script includes a warning comment advising against deletion, as it is -# essential for the proper functioning of Phoenix Code when invoked through this script. -# -# Usage: -# This function is intended to be called during the installation or upgrade process of Phoenix Code, -# after the binary has been placed in its final location. It should not be called arbitrarily, as it -# assumes a specific setup and context established by the installer script. -# -create_invocation_script() { - local binary_path="$1" - local script_name="$2" - local link_dir="$3" - - echo "Creating an invocation script for the binary..." - # Start of the generated script - echo "#!/bin/bash" > "$binary_path/$script_name.sh" - # Add a warning comment about the script being auto-generated - echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" - echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" - chmod +x "$binary_path/$script_name" - - echo "Copying the invocation script to $link_dir..." - mkdir -p "$link_dir" # Ensure the directory exists - cp "$binary_path/$script_name" "$link_dir/$script_name" - - echo -e "Invocation script created at: $link_dir/$script_name" -} -# Install Dependencies Function -# -# Purpose: -# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. -# This function identifies the user's Linux distribution and installs the appropriate packages -# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and -# Arch Linux distributions. -# -# Behavior: -# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. -# If the command fails, it prompts the user to enter their password for `sudo` access. -# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. -# 3. Based on the identified distribution, executes the appropriate package manager command -# with the required packages. Supported package managers are `apt` for Debian-based systems, -# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. -# 4. Updates the package index (if applicable) and installs the packages. -# -# Considerations: -# - The function requires internet access to fetch package information and install packages. -# - It assumes that the user has `sudo` privileges to install packages system-wide. -# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, -# this function must be updated accordingly. -# - Unsupported distributions will result in an error message and termination of the script, -# as the required dependencies cannot be installed automatically. -# - This function does not handle potential errors from package installation commands. It's -# recommended to monitor the output for any issues that may require manual intervention. -# -# Usage: -# This function is intended to be called during the Phoenix Code installation process, typically -# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites -# are met for a successful Phoenix Code execution. -# -install_dependencies() { - echo "Attempting to install required dependencies..." - - # Inform the user that the next steps require administrative access - echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." - - # Check if the script can execute sudo commands without interaction - if ! sudo -n true 2>/dev/null; then - echo "Please enter your password to proceed with the installation of dependencies." - fi - - # Attempt to identify the Linux distribution - if [ -f /etc/os-release ]; then - . /etc/os-release - DISTRO=$ID - else - echo "Unable to identify the operating system." - exit 1 - fi - - # Install dependencies based on the distribution - case "$DISTRO" in - ubuntu|debian|linuxmint) - echo "Detected an Ubuntu/Debian based distribution." - sudo apt update - sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ - gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ - gstreamer1.0-tools - ;; - fedora|rhel|centos) - echo "Detected a Fedora/Red Hat based distribution." - sudo dnf install webkit2gtk3 gtk3 \ - gstreamer1-plugins-base gstreamer1-plugins-good - ;; - arch|manjaro) - echo "Detected an Arch Linux based distribution." - sudo pacman -Syu - sudo pacman -S webkit2gtk gtk3 - ;; - *) - echo "Unsupported distribution. Please manually install the required dependencies." - exit 1 - ;; - esac -} -# Verify and Install Dependencies Function -# -# Purpose: -# This function is responsible for verifying if the Phoenix Code application can be successfully -# launched with the current set of installed dependencies. If the initial verification fails, it -# attempts to install the necessary dependencies and then re-verifies the application launch. -# -# Behavior: -# 1. Changes the current directory to the temporary directory where Phoenix Code is located. -# 2. Sets the executable permission for the Phoenix Code binary and attempts to run it with a -# verification-specific command (e.g., `--runVerify`). This step is intended to check if the -# application can start without installing additional dependencies. -# 3. If the initial verification succeeds, the function exits with a success status (0), indicating -# no further action is needed. -# 4. If the initial verification fails, the function proceeds to invoke `install_dependencies` to -# install any missing dependencies specific to the user's Linux distribution. -# 5. After installing dependencies, it attempts to verify the application launch again. If this -# second attempt succeeds, the function exits with a success status (0). -# 6. If the verification fails even after installing dependencies, the function prints an error -# message advising the user to check the application requirements or contact support, and -# exits with an error status (1). -# 7. Finally, the function ensures to change back to the original directory where the script was -# invoked, preserving the user's shell environment. -# -# Considerations: -# - The function assumes that the Phoenix Code binary is located in a temporary directory and -# that this directory is correctly set in the `$TMP_DIR` variable. -# - It relies on the Phoenix Code binary supporting a `--runVerify` command or equivalent for -# verification purposes. If such a command is not available, this part of the function needs -# adjustment. -# - Dependency installation requires administrative privileges; hence, the user might be prompted -# for a password to allow `sudo` operations. -# - The function does not handle all possible error scenarios during dependency installation. -# Users should monitor the output for potential issues that might need manual intervention. -# -# Usage: -# This function is intended to be called during the installation or upgrade process of Phoenix Code, -# before finalizing the installation, to ensure that all system requirements are met for the -# application to run properly. -# -verify_and_install_dependencies() { - cd "$TMP_DIR/phoenix-code" - # Ensure the binary is executable - chmod +x "./phoenix-code" - # First attempt to verify the application launch - if ./phoenix-code --runVerify; then - echo "Application launch verification successful." - return 0 # Exit the function successfully if verification succeeds - else - echo "Initial verification failed. Attempting to install dependencies..." - install_dependencies # Function to install required dependencies - fi - - # Second attempt to verify the application launch after installing dependencies - if ./phoenix-code --runVerify; then - echo "Application launch verification successful after installing dependencies." - cd - - return 0 # Exit the function successfully if verification succeeds - else - echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." - cd - - return 1 # Return an error code to indicate failure - fi -} -# Set Phoenix Code as the default application for specified MIME types -set_default_application() { - local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file - - for mime_type in "${MIME_TYPES[@]}"; do - # Skip setting default application for inode/directory and text/html - if [ "$mime_type" = "inode/directory" ] || [ "$mime_type" = "text/html" ]; then - continue # Skip to the next iteration - fi - - xdg-mime default "$desktop_file" "$mime_type" - done - echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" -} - -# Copy Files to Destination Function -# -# Purpose: -# This function is responsible for setting up the final installation directory for Phoenix Code, -# moving the necessary files into place, creating the invocation script, and setting up the desktop -# entry for the application. It ensures that all components of Phoenix Code are correctly installed -# and configured in the user's environment. -# -# Behavior: -# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files -# will reside. -# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. -# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from -# the temporary directory (`$TMP_DIR`) to the installation directory. -# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. -# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. -# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. -# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and -# launchers, and places this file in the desktop entry directory. -# 8. Updates the system's desktop database to ensure the new application entry is recognized and available -# in application menus and launchers. This step might involve commands like `update-desktop-database` -# or `kbuildsycoca5`, depending on the desktop environment. -# -# Considerations: -# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and -# that this directory is correctly set. -# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and -# accessible. If these variables are unset or incorrect, the function may not perform as intended. -# - Administrative privileges may be required for certain operations, such as updating the desktop database -# or setting permissions, depending on the system's configuration. -# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function -# does perform significant file system operations that could potentially conflict with existing user data -# or system settings. -# -# Usage: -# This function is intended to be called as part of the Phoenix Code installation process, after the -# application's binary and other necessary files have been prepared in a temporary location. It finalizes -# the installation by placing all components in their appropriate locations within the user's system. -# -copyFilesToDestination(){ - echo "Setting up the installation directory at $INSTALL_DIR..." - mkdir -p "$INSTALL_DIR" - mkdir -p "$DESKTOP_DIR" - echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" - - echo "Moving the necessary files to the installation directory..." - echo -e "Phoenix Code files moved to: $INSTALL_DIR" - mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { - echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" - exit 1 - } - # Move the icon to the installation directory - mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" - - echo "Setting the correct permissions for the executable..." - chmod +x "$INSTALL_DIR/phoenix-code" || { - echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" - exit 1 - } - echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" - - mkdir -p "$LINK_DIR" # Ensure the directory exists - # Call the function to create and copy the invocation script - create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" - # Convert MIME types array to semicolon-separated string for the desktop entry - MIME_TYPES_STRING=$(IFS=";"; echo "${MIME_TYPES[*]}") - echo "Creating desktop entry..." - cat > "$DESKTOP_ENTRY" < /dev/null; then - update-desktop-database "$DESKTOP_DIR" - echo -e "Desktop database updated in: $DESKTOP_DIR" - fi - - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 - fi - fi - # Set Phoenix Code as the default application for the MIME types - set_default_application - echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" - -} -downloadLatestReleaseInfo() { - local release_info_file="$TMP_DIR/latest_release.json" - - if [ -f "$release_info_file" ]; then - # Only extract and echo the version number, without any additional messages - grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" - return - fi - - # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly - >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" - wget -qO "$release_info_file" "$API_URL" || { - >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" - exit 1 - } - - # Only extract and echo the version number after successful download - grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" -} - -# Download Latest Release Information Function -# -# Purpose: -# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function -# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to -# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. -# -# Behavior: -# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary -# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already -# been fetched and proceeds to extract the version number from this file without re-downloading. -# 2. If the release information file does not exist, the function uses `wget` to download the JSON data -# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint -# of the Phoenix Code GitHub repository. -# 3. The JSON data is saved to `latest_release.json` in the temporary directory. -# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular -# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version -# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number -# portion. -# 5. Echoes the extracted version number for use by the calling context. -# -# Considerations: -# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available -# in the execution environment. -# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code -# repository for this function to work as intended. -# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, -# the `grep` pattern used to extract the version number may need to be updated. -# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an -# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the -# latest release information. -# - The function does not perform error handling for the `wget` command. If the download fails, the script may -# exit or behave unexpectedly depending on the `set -e` setting. -# -# Usage: -# This function is intended to be called during the installation or upgrade process to determine the latest -# version of Phoenix Code. The extracted version number can be used to compare with the currently installed -# version and decide whether an upgrade is necessary. -# -downloadAndInstall(){ - echo "Using temporary directory $TMP_DIR for processing" - downloadLatestReleaseInfo > /dev/null - CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') - echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" - - BEST_MATCH_URL="" - BEST_MATCH_VERSION=0 - echo "Searching for a compatible binary..." - - while read -r BINARY_URL; do - BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') - if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then - BEST_MATCH_URL="$BINARY_URL" - BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" - echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" - fi - done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") - - if [ -z "$BEST_MATCH_URL" ]; then - echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" - exit 1 - fi - - echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { - echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" - exit 1 - } - echo -e "Downloading the icon..." - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { - echo -e "${RED}Failed to download Icon${RESET}"; - exit 1; - } - echo "Extracting the binary to $TMP_DIR..." - tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { - echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" - exit 1 - } - - # Verify binary execution and install dependencies if necessary - if ! verify_and_install_dependencies; then - echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" - exit 1 - fi -} -# Install Function -# -# Purpose: -# Facilitates the entire installation process of Phoenix Code on the user's system. This includes -# checking for previous installations, downloading and installing the latest version, setting up -# necessary directories, and ensuring that all dependencies are met. It also handles user prompts -# for repair or reinstallation options if Phoenix Code is already installed. -# -# Behavior: -# 1. Checks if Phoenix Code is already installed by looking for specific files or directories -# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main -# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). -# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and -# then reinstalls the application, ensuring the user ends up with the latest version. -# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest -# release and install it. This step involves downloading the binary, setting permissions, and -# moving files to their correct locations. -# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, -# create an invocation script, and perform other necessary post-installation configurations. -# -# Considerations: -# - The function assumes that the user has sufficient permissions to write to the target directories -# and install Phoenix Code. Administrative privileges may be required for certain operations. -# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation -# directory will be replaced. Users should ensure that any custom configurations or data are backed up -# before proceeding. -# - Network connectivity is required to download the latest version of Phoenix Code from the repository. -# - The function does not explicitly handle all potential error scenarios, such as download failures or -# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. -# -# Usage: -# This function is intended to be invoked when the script is run without specific options (e.g., not an -# uninstall or upgrade). It can be directly called from the command line when the user wishes to install -# Phoenix Code, or it may be triggered by default when the script is executed without arguments. -# -install() { - # Check if the application is already installed - if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then - echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" - - # Simplified prompt for reinstall without detailed explanation - read -r -p "Would you like to reinstall it? (y/N): " response - case "$response" in - [Yy]* ) - echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" - uninstall - downloadAndInstall - copyFilesToDestination - ;; - * ) - echo -e "${RED}Reinstall aborted by the user.${RESET}" - exit 0 - ;; - esac - else - downloadAndInstall - copyFilesToDestination - fi -} - -# Temporary code to clean up earlier beta installations -function uninstallBetaAppImage() { - rm -f "$LINK_DIR"/phoenix_icon.png -} -# Upgrade Function -# -# Purpose: -# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated -# to the latest version available. This function checks the currently installed version against -# the latest version available in the GitHub repository. If a newer version is found, it proceeds -# to download and install the update, effectively replacing the old version with the new one. -# -# Behavior: -# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation -# directory and the invocation script. If not found, it exits with an error message indicating that -# Phoenix Code must be installed before it can be upgraded. -# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version -# check command (e.g., `phoenix-code --version`) and captures the output. -# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` -# function, which retrieves the version number of the latest release. -# 4. Compares the currently installed version with the latest version. If the installed version is older, -# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and -# installation of the new version. -# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. -# -# Considerations: -# - The function relies on the correct implementation of version checking in the Phoenix Code binary. -# The binary must support a command-line option to output its version, and the output format must be -# consistent for correct parsing and comparison. -# - Network connectivity is required to fetch the latest release information from the GitHub repository. -# The upgrade process will fail if the script cannot connect to GitHub. -# - The user must have sufficient permissions to overwrite the existing installation files and to -# execute network requests (e.g., downloading the latest release). -# - The upgrade process replaces the existing installation files. Users should ensure that any -# necessary backups or custom configurations are saved before proceeding with the upgrade. -# -# Usage: -# This function is intended to be called when the user explicitly wants to upgrade their installation -# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the -# script, as defined in the script's main case statement handling command-line arguments. -# -upgrade() { - echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" - - # Ensure Phoenix Code is installed - if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then - echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" - exit 1 - fi - # Get the current installed version - CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) - echo "Current installed version: $CURRENT_VERSION" - - LATEST_VERSION=$(downloadLatestReleaseInfo) - # Now LATEST_VERSION should only contain the version number without extra messages - echo "Latest available version: $LATEST_VERSION" - - # Compare versions and upgrade if the latest version is greater - if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then - echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" - downloadAndInstall - uninstall - copyFilesToDestination - echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" - else - echo "Your Phoenix Code installation is up-to-date." - fi - -} -# Uninstall Function -# -# Purpose: -# Handles the removal of Phoenix Code from the user's system. This function is responsible for -# cleaning up all files, directories, and links created during the installation process, effectively -# reverting any changes made by the installer script. It ensures that Phoenix Code and its components -# are uninstalled cleanly, leaving no residual files or configurations. -# -# Behavior: -# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). -# This step prevents the Phoenix Code command from being accessible after uninstallation. -# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus -# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. -# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. -# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. -# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including -# the main binary, configuration files, and any other related files placed during installation. -# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. -# -# Considerations: -# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately -# reflect the locations used during the installation. If these variables are incorrect, the uninstallation -# process may not remove all components. -# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed -# in system-wide directories. -# - Users should be advised to back up any important data or configurations related to Phoenix Code before -# initiating the uninstallation process, as this function will remove all associated files without recovery options. -# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot -# be reversed through this script. -# -# Usage: -# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. -# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement -# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this -# function is executed to prevent accidental data loss. -# -uninstall() { - echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" - uninstallBetaAppImage - # Remove the invocation script from ~/.local/bin - if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then - echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" - rm "$LINK_DIR/$SCRIPT_NAME" - else - echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" - fi - - # Delete the desktop entry - if [ -f "$DESKTOP_ENTRY" ]; then - echo -e "${YELLOW}Removing desktop entry...${RESET}" - rm "$DESKTOP_ENTRY" - - # Update the desktop database for GNOME, Unity, XFCE, etc. - echo -e "${YELLOW}Updating desktop database...${RESET}" - if command -v update-desktop-database &> /dev/null; then - update-desktop-database "$DESKTOP_DIR" - fi - - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 - fi - fi - else - echo -e "${RED}Desktop entry not found. Skipping...${RESET}" - fi - - # Remove the installation directory and its contents - if [ -d "$INSTALL_DIR" ]; then - echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" - rm -rf "$INSTALL_DIR" - else - echo -e "${RED}Installation directory not found. Skipping...${RESET}" - fi - echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" -} - -show_help() { - echo "Usage: $0 [OPTION]" - echo "Install, upgrade, or uninstall Phoenix Code." - echo - echo "Options:" - echo " -h, --help Display this help and exit" - echo " --uninstall Uninstall Phoenix Code" - echo " --upgrade Upgrade Phoenix Code to the latest version" - echo - echo "Without any options, the script will install Phoenix Code." -} - -# Check for GUI session by looking for DISPLAY or WAYLAND_DISPLAY variables -if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then - echo "This script should only be run from terminals in GUI sessions." - exit 1 -fi - -case "${1-}" in - -h|--help) - show_help # Function to show help - ;; - --uninstall) - uninstall # Function to uninstall - ;; - --upgrade) - upgrade # Function to upgrade - ;; - "") - # This case handles when $1 is unset (acts as a default action) - install # Function to install - ;; - *) - # This case handles unexpected arguments - echo "Invalid option: $1" >&2 - show_help # Assuming you have a function to show usage information - exit 1 - ;; -esac diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh old mode 100644 new mode 100755 index 39bd3e75..c28b165c --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,152 +1,752 @@ #!/bin/bash -set -e # Exit immediately if a command exits with a non-zero status. +set -euo pipefail # Exit immediately if a command exits with a non-zero status. # Define common variables -APPIMAGE_DIR=$HOME/.local/bin DESKTOP_DIR=$HOME/.local/share/applications -NEW_APPIMAGE=phcode -ICON=phoenix_icon.png GITHUB_REPO="phcode-dev/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" -check_and_install_libfuse() { - # Identify the Linux distribution - if [ -f /etc/os-release ]; then - . /etc/os-release - DISTRO=$ID - else - echo "Cannot identify the operating system." - exit 1 - fi +INSTALL_DIR="$HOME/.phoenix-code" +LINK_DIR="$HOME/.local/bin" +DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries +DESKTOP_ENTRY_NAME="PhoenixCode.desktop" +DESKTOP_APP_NAME="Phoenix Code" +DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" +SCRIPT_NAME="phcode" # Name of the script to invoke the binary +BINARY_NAME="phoenix-code" - echo "Checking for FUSE library..." +declare -a MIME_TYPES=( + "text/html" + "application/atom+xml" + "application/x-coldfusion" + "text/x-clojure" + "text/coffeescript" + "application/json" + "text/css" + "text/x-diff" + "text/jsx" + "text/markdown" + "application/mathml+xml" + "application/rdf+xml" + "application/rss+xml" + "application/sql" + "image/svg+xml" + "text/x-python" + "application/xml" + "application/vnd.mozilla.xul+xml" + "application/x-yaml" + "text/javascript" + "application/javascript" + "text/mjs" + "application/mjs" + "text/cjs" + "inode/directory" # Added to include directory handling +) - if [ "$DISTRO" = "ubuntu" ]; then - # Check and install libfuse2 on Ubuntu - if ! dpkg -s libfuse2 &> /dev/null; then - echo "libfuse2 not found, installing..." - sudo apt-get update && sudo apt-get install -y libfuse2 || { echo "Failed to install libfuse2"; exit 1; } - else - echo "libfuse2 is already installed." - fi - elif [ "$DISTRO" = "fedora" ]; then - # Check and install fuse-libs on Fedora - if [ "$DISTRO" = "fedora" ]; then - # Check and install fuse-libs on Fedora - if ! rpm -q fuse-libs &> /dev/null; then - echo "fuse-libs not found, installing..." - sudo dnf install -y fuse-libs || { echo "Failed to install fuse-libs"; exit 1; } - else - echo "fuse-libs is already installed." - fi - fi - else - echo "Unsupported distribution: $DISTRO" - exit 1 - fi +# Define color variables for easy reference +GREEN="\e[32m" +YELLOW="\e[33m" +RED="\e[31m" +RESET="\e[0m" + +# Cleanup Function +# +# Purpose: +# The cleanup function is designed to ensure that the script cleans up any temporary +# resources it used during its execution. Specifically, it removes the temporary directory +# created at the beginning of the script, along with all its contents. This is crucial for +# maintaining a clean file system and avoiding the accumulation of unused files. +# +# Behavior: +# - The function targets a temporary directory specified by the `$TMP_DIR` variable. +# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. +# This includes any temporary files, downloaded assets, or other data generated during the script's execution. +# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes +# automatically when the script exits, regardless of the exit point. This includes normal completion, +# errors, or manual termination via signals like SIGINT (Ctrl+C). +# +# Considerations: +# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. +# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. +# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` +# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. +# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within +# `$TMP_DIR` is expendable and safe to delete. +# +# Usage: +# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` +# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` +# is correctly set to the temporary directory path before invoking the function. +# +cleanup() { + rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. } -install() { - check_and_install_libfuse - # Fetch the latest release data from GitHub - echo "Fetching latest release from $GITHUB_REPO..." - wget -qO- $API_URL > latest_release.json || { echo "Failed to fetch latest release info"; exit 1; } - - # Extract the download URL for the AppImage - APPIMAGE_URL=$(grep -oP '"browser_download_url": "\K(.*phoenix-desktop.*\.AppImage)(?=")' latest_release.json) || { echo "Failed to extract AppImage URL"; exit 1; } - - # If no AppImage URL is found, exit the script - if [ -z "$APPIMAGE_URL" ]; then - echo "No AppImage URL found in the latest release." - rm latest_release.json - exit 1 - fi +trap cleanup EXIT # Register the cleanup function to be called on script exit. + + +TMP_DIR=$(mktemp -d) + +# Create Invocation Script Function +# +# Purpose: +# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. +# This script is intended to simplify the execution of Phoenix Code by providing a more accessible +# command interface. The generated script is placed in a user-accessible binary directory, making it +# possible to run Phoenix Code from anywhere in the system without needing to specify the full path +# to the binary. +# +# Parameters: +# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. +# - script_name: The name to be given to the invocation script. This name is used both for the +# script file itself and for the symlink created in the user's binary directory. +# - link_dir: The directory where a symlink to the invocation script will be placed, typically +# a location in the user's PATH, such as ~/.local/bin, for easy access. +# +# Behavior: +# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. +# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a +# command to execute the Phoenix Code binary with any passed arguments ("$@"). +# 3. Sets executable permissions on the newly created script. +# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. +# +# Considerations: +# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' +# does not conflict with existing files in these directories to prevent unintended overwrites. +# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes +# these directories are already created and accessible. +# - The generated script includes a warning comment advising against deletion, as it is +# essential for the proper functioning of Phoenix Code when invoked through this script. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# after the binary has been placed in its final location. It should not be called arbitrarily, as it +# assumes a specific setup and context established by the installer script. +# +create_invocation_script() { + local binary_path="$1" + local script_name="$2" + local link_dir="$3" + + echo "Creating an invocation script for the binary..." + # Start of the generated script + echo "#!/bin/bash" > "$binary_path/$script_name.sh" + # Add a warning comment about the script being auto-generated + echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" + echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" + chmod +x "$binary_path/$script_name" - # Download the AppImage - echo "Downloading AppImage from $APPIMAGE_URL..." - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $NEW_APPIMAGE $APPIMAGE_URL || { echo "Failed to download AppImage"; exit 1; } - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO $ICON $ICON_URL || { echo "Failed to download Icon"; exit 1; } - # Remove the temporary JSON file - rm latest_release.json + echo "Copying the invocation script to $link_dir..." + mkdir -p "$link_dir" # Ensure the directory exists + cp "$binary_path/$script_name" "$link_dir/$script_name" + echo -e "Invocation script created at: $link_dir/$script_name" +} +# Install Dependencies Function +# +# Purpose: +# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. +# This function identifies the user's Linux distribution and installs the appropriate packages +# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and +# Arch Linux distributions. +# +# Behavior: +# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. +# If the command fails, it prompts the user to enter their password for `sudo` access. +# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. +# 3. Based on the identified distribution, executes the appropriate package manager command +# with the required packages. Supported package managers are `apt` for Debian-based systems, +# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. +# 4. Updates the package index (if applicable) and installs the packages. +# +# Considerations: +# - The function requires internet access to fetch package information and install packages. +# - It assumes that the user has `sudo` privileges to install packages system-wide. +# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, +# this function must be updated accordingly. +# - Unsupported distributions will result in an error message and termination of the script, +# as the required dependencies cannot be installed automatically. +# - This function does not handle potential errors from package installation commands. It's +# recommended to monitor the output for any issues that may require manual intervention. +# +# Usage: +# This function is intended to be called during the Phoenix Code installation process, typically +# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites +# are met for a successful Phoenix Code execution. +# +install_dependencies() { + echo "Attempting to install required dependencies..." + + # Inform the user that the next steps require administrative access + echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." + + # Check if the script can execute sudo commands without interaction + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed with the installation of dependencies." + fi + + # Attempt to identify the Linux distribution + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO=$ID + else + echo "Unable to identify the operating system." + exit 1 + fi + + # Install dependencies based on the distribution + case "$DISTRO" in + ubuntu|debian|linuxmint) + echo "Detected an Ubuntu/Debian based distribution." + sudo apt update + sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + gstreamer1.0-tools + ;; + fedora|rhel|centos) + echo "Detected a Fedora/Red Hat based distribution." + sudo dnf install webkit2gtk3 gtk3 \ + gstreamer1-plugins-base gstreamer1-plugins-good + ;; + arch|manjaro) + echo "Detected an Arch Linux based distribution." + sudo pacman -Syu + sudo pacman -S webkit2gtk gtk3 + ;; + *) + echo "Unsupported distribution. Please manually install the required dependencies." + exit 1 + ;; + esac +} +# Verify and Install Dependencies Function +# +# Purpose: +# This function is responsible for verifying if the Phoenix Code application can be successfully +# launched with the current set of installed dependencies. If the initial verification fails, it +# attempts to install the necessary dependencies and then re-verifies the application launch. +# +# Behavior: +# 1. Changes the current directory to the temporary directory where Phoenix Code is located. +# 2. Sets the executable permission for the Phoenix Code binary and attempts to run it with a +# verification-specific command (e.g., `--runVerify`). This step is intended to check if the +# application can start without installing additional dependencies. +# 3. If the initial verification succeeds, the function exits with a success status (0), indicating +# no further action is needed. +# 4. If the initial verification fails, the function proceeds to invoke `install_dependencies` to +# install any missing dependencies specific to the user's Linux distribution. +# 5. After installing dependencies, it attempts to verify the application launch again. If this +# second attempt succeeds, the function exits with a success status (0). +# 6. If the verification fails even after installing dependencies, the function prints an error +# message advising the user to check the application requirements or contact support, and +# exits with an error status (1). +# 7. Finally, the function ensures to change back to the original directory where the script was +# invoked, preserving the user's shell environment. +# +# Considerations: +# - The function assumes that the Phoenix Code binary is located in a temporary directory and +# that this directory is correctly set in the `$TMP_DIR` variable. +# - It relies on the Phoenix Code binary supporting a `--runVerify` command or equivalent for +# verification purposes. If such a command is not available, this part of the function needs +# adjustment. +# - Dependency installation requires administrative privileges; hence, the user might be prompted +# for a password to allow `sudo` operations. +# - The function does not handle all possible error scenarios during dependency installation. +# Users should monitor the output for potential issues that might need manual intervention. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# before finalizing the installation, to ensure that all system requirements are met for the +# application to run properly. +# +verify_and_install_dependencies() { + cd "$TMP_DIR/phoenix-code" + # Ensure the binary is executable + chmod +x "./phoenix-code" + # First attempt to verify the application launch + if ./phoenix-code --runVerify; then + echo "Application launch verification successful." + return 0 # Exit the function successfully if verification succeeds + else + echo "Initial verification failed. Attempting to install dependencies..." + install_dependencies # Function to install required dependencies + fi - # Proceed with installation steps as before... - # Create necessary directories - mkdir -p $APPIMAGE_DIR - mkdir -p $DESKTOP_DIR + # Second attempt to verify the application launch after installing dependencies + if ./phoenix-code --runVerify; then + echo "Application launch verification successful after installing dependencies." + cd - + return 0 # Exit the function successfully if verification succeeds + else + echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." + cd - + return 1 # Return an error code to indicate failure + fi +} +# Set Phoenix Code as the default application for specified MIME types +set_default_application() { + local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file - # Copy and rename the AppImage, and copy the icon to the AppImage directory - echo "Installing Phoenix..." - mv $NEW_APPIMAGE $APPIMAGE_DIR/$NEW_APPIMAGE - mv "$ICON" $APPIMAGE_DIR # Ensure this icon file is in the current directory + for mime_type in "${MIME_TYPES[@]}"; do + # Skip setting default application for inode/directory and text/html + if [ "$mime_type" = "inode/directory" ] || [ "$mime_type" = "text/html" ]; then + continue # Skip to the next iteration + fi - # Make the new AppImage executable - chmod +x $APPIMAGE_DIR/$NEW_APPIMAGE + xdg-mime default "$desktop_file" "$mime_type" + done + echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" +} +# Copy Files to Destination Function +# +# Purpose: +# This function is responsible for setting up the final installation directory for Phoenix Code, +# moving the necessary files into place, creating the invocation script, and setting up the desktop +# entry for the application. It ensures that all components of Phoenix Code are correctly installed +# and configured in the user's environment. +# +# Behavior: +# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files +# will reside. +# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. +# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from +# the temporary directory (`$TMP_DIR`) to the installation directory. +# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. +# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. +# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. +# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and +# launchers, and places this file in the desktop entry directory. +# 8. Updates the system's desktop database to ensure the new application entry is recognized and available +# in application menus and launchers. This step might involve commands like `update-desktop-database` +# or `kbuildsycoca5`, depending on the desktop environment. +# +# Considerations: +# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and +# that this directory is correctly set. +# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and +# accessible. If these variables are unset or incorrect, the function may not perform as intended. +# - Administrative privileges may be required for certain operations, such as updating the desktop database +# or setting permissions, depending on the system's configuration. +# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function +# does perform significant file system operations that could potentially conflict with existing user data +# or system settings. +# +# Usage: +# This function is intended to be called as part of the Phoenix Code installation process, after the +# application's binary and other necessary files have been prepared in a temporary location. It finalizes +# the installation by placing all components in their appropriate locations within the user's system. +# +copyFilesToDestination(){ + echo "Setting up the installation directory at $INSTALL_DIR..." + mkdir -p "$INSTALL_DIR" + mkdir -p "$DESKTOP_DIR" + echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" - # Define MIME types for file extensions - MIME_TYPES="text/html;application/atom+xml;application/x-coldfusion;text/x-clojure;text/coffeescript;application/json;text/css;text/html;text/x-diff;text/jsx;text/markdown;application/mathml+xml;application/rdf+xml;application/rss+xml;text/css;application/sql;image/svg+xml;text/html;text/x-python;application/xml;application/vnd.mozilla.xul+xml;application/x-yaml;text/typescript;" + echo "Moving the necessary files to the installation directory..." + echo -e "Phoenix Code files moved to: $INSTALL_DIR" + mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { + echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" + exit 1 + } + # Move the icon to the installation directory + mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" - # Add directory association - MIME_TYPES+="inode/directory;" + echo "Setting the correct permissions for the executable..." + chmod +x "$INSTALL_DIR/phoenix-code" || { + echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" + exit 1 + } + echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" - # Create a desktop entry for the AppImage with MIME type associations -cat > $DESKTOP_DIR/PhoenixCode.desktop < "$DESKTOP_ENTRY" < /dev/null; then + update-desktop-database "$DESKTOP_DIR" + echo -e "Desktop database updated in: $DESKTOP_DIR" + fi - # Update the desktop database for GNOME, Unity, XFCE, etc. - if command -v update-desktop-database &> /dev/null - then - update-desktop-database $DESKTOP_DIR + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 fi + fi + # Set Phoenix Code as the default application for the MIME types + set_default_application + echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null - then - kbuildsycoca5 - fi +} +downloadLatestReleaseInfo() { + local release_info_file="$TMP_DIR/latest_release.json" + + if [ -f "$release_info_file" ]; then + # Only extract and echo the version number, without any additional messages + grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" + return + fi + + # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly + >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" + wget -qO "$release_info_file" "$API_URL" || { + >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" + exit 1 + } + + # Only extract and echo the version number after successful download + grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" +} + +# Download Latest Release Information Function +# +# Purpose: +# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function +# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to +# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. +# +# Behavior: +# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary +# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already +# been fetched and proceeds to extract the version number from this file without re-downloading. +# 2. If the release information file does not exist, the function uses `wget` to download the JSON data +# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint +# of the Phoenix Code GitHub repository. +# 3. The JSON data is saved to `latest_release.json` in the temporary directory. +# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular +# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version +# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number +# portion. +# 5. Echoes the extracted version number for use by the calling context. +# +# Considerations: +# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available +# in the execution environment. +# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code +# repository for this function to work as intended. +# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, +# the `grep` pattern used to extract the version number may need to be updated. +# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an +# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the +# latest release information. +# - The function does not perform error handling for the `wget` command. If the download fails, the script may +# exit or behave unexpectedly depending on the `set -e` setting. +# +# Usage: +# This function is intended to be called during the installation or upgrade process to determine the latest +# version of Phoenix Code. The extracted version number can be used to compare with the currently installed +# version and decide whether an upgrade is necessary. +# +downloadAndInstall(){ + echo "Using temporary directory $TMP_DIR for processing" + downloadLatestReleaseInfo > /dev/null + CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') + echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" + + BEST_MATCH_URL="" + BEST_MATCH_VERSION=0 + echo "Searching for a compatible binary..." + + while read -r BINARY_URL; do + BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') + if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then + BEST_MATCH_URL="$BINARY_URL" + BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" + echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" fi + done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") + + if [ -z "$BEST_MATCH_URL" ]; then + echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" + exit 1 + fi - echo "Phoenix Code installed successfully." + echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { + echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" + exit 1 + } + echo -e "Downloading the icon..." + wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { + echo -e "${RED}Failed to download Icon${RESET}"; + exit 1; + } + echo "Extracting the binary to $TMP_DIR..." + tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { + echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" + exit 1 + } + + # Verify binary execution and install dependencies if necessary + if ! verify_and_install_dependencies; then + echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" + exit 1 + fi } +# Install Function +# +# Purpose: +# Facilitates the entire installation process of Phoenix Code on the user's system. This includes +# checking for previous installations, downloading and installing the latest version, setting up +# necessary directories, and ensuring that all dependencies are met. It also handles user prompts +# for repair or reinstallation options if Phoenix Code is already installed. +# +# Behavior: +# 1. Checks if Phoenix Code is already installed by looking for specific files or directories +# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main +# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). +# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and +# then reinstalls the application, ensuring the user ends up with the latest version. +# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest +# release and install it. This step involves downloading the binary, setting permissions, and +# moving files to their correct locations. +# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, +# create an invocation script, and perform other necessary post-installation configurations. +# +# Considerations: +# - The function assumes that the user has sufficient permissions to write to the target directories +# and install Phoenix Code. Administrative privileges may be required for certain operations. +# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation +# directory will be replaced. Users should ensure that any custom configurations or data are backed up +# before proceeding. +# - Network connectivity is required to download the latest version of Phoenix Code from the repository. +# - The function does not explicitly handle all potential error scenarios, such as download failures or +# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. +# +# Usage: +# This function is intended to be invoked when the script is run without specific options (e.g., not an +# uninstall or upgrade). It can be directly called from the command line when the user wishes to install +# Phoenix Code, or it may be triggered by default when the script is executed without arguments. +# +install() { + # Check if the application is already installed + if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then + echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" + # Simplified prompt for reinstall without detailed explanation + read -r -p "Would you like to reinstall it? (y/N): " response + case "$response" in + [Yy]* ) + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + uninstall + downloadAndInstall + copyFilesToDestination + ;; + * ) + echo -e "${RED}Reinstall aborted by the user.${RESET}" + exit 0 + ;; + esac + else + downloadAndInstall + copyFilesToDestination + fi +} + +# Temporary code to clean up earlier beta installations +function uninstallBetaAppImage() { + rm -f "$LINK_DIR"/phoenix_icon.png +} +# Upgrade Function +# +# Purpose: +# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated +# to the latest version available. This function checks the currently installed version against +# the latest version available in the GitHub repository. If a newer version is found, it proceeds +# to download and install the update, effectively replacing the old version with the new one. +# +# Behavior: +# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation +# directory and the invocation script. If not found, it exits with an error message indicating that +# Phoenix Code must be installed before it can be upgraded. +# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version +# check command (e.g., `phoenix-code --version`) and captures the output. +# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` +# function, which retrieves the version number of the latest release. +# 4. Compares the currently installed version with the latest version. If the installed version is older, +# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and +# installation of the new version. +# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. +# +# Considerations: +# - The function relies on the correct implementation of version checking in the Phoenix Code binary. +# The binary must support a command-line option to output its version, and the output format must be +# consistent for correct parsing and comparison. +# - Network connectivity is required to fetch the latest release information from the GitHub repository. +# The upgrade process will fail if the script cannot connect to GitHub. +# - The user must have sufficient permissions to overwrite the existing installation files and to +# execute network requests (e.g., downloading the latest release). +# - The upgrade process replaces the existing installation files. Users should ensure that any +# necessary backups or custom configurations are saved before proceeding with the upgrade. +# +# Usage: +# This function is intended to be called when the user explicitly wants to upgrade their installation +# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the +# script, as defined in the script's main case statement handling command-line arguments. +# +upgrade() { + echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" + + # Ensure Phoenix Code is installed + if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then + echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" + exit 1 + fi + # Get the current installed version + CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) + echo "Current installed version: $CURRENT_VERSION" + + LATEST_VERSION=$(downloadLatestReleaseInfo) + # Now LATEST_VERSION should only contain the version number without extra messages + echo "Latest available version: $LATEST_VERSION" + + # Compare versions and upgrade if the latest version is greater + if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then + echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" + downloadAndInstall + uninstall + copyFilesToDestination + echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" + else + echo "Your Phoenix Code installation is up-to-date." + fi + +} +# Uninstall Function +# +# Purpose: +# Handles the removal of Phoenix Code from the user's system. This function is responsible for +# cleaning up all files, directories, and links created during the installation process, effectively +# reverting any changes made by the installer script. It ensures that Phoenix Code and its components +# are uninstalled cleanly, leaving no residual files or configurations. +# +# Behavior: +# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). +# This step prevents the Phoenix Code command from being accessible after uninstallation. +# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus +# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. +# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. +# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. +# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including +# the main binary, configuration files, and any other related files placed during installation. +# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. +# +# Considerations: +# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately +# reflect the locations used during the installation. If these variables are incorrect, the uninstallation +# process may not remove all components. +# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed +# in system-wide directories. +# - Users should be advised to back up any important data or configurations related to Phoenix Code before +# initiating the uninstallation process, as this function will remove all associated files without recovery options. +# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot +# be reversed through this script. +# +# Usage: +# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. +# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement +# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this +# function is executed to prevent accidental data loss. +# uninstall() { - # Remove the AppImage and the icon - echo "Uninstalling Phoenix..." - rm -f $APPIMAGE_DIR/$NEW_APPIMAGE - rm -f $APPIMAGE_DIR/$ICON - - # Remove the desktop entry - rm -f $DESKTOP_DIR/PhoenixCode.desktop - - # Update the desktop database for GNOME, Unity, XFCE, etc. (if available) - if command -v update-desktop-database &> /dev/null - then - update-desktop-database $DESKTOP_DIR + echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" + uninstallBetaAppImage + # Remove the invocation script from ~/.local/bin + if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then + echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" + rm "$LINK_DIR/$SCRIPT_NAME" + else + echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" + fi + + # Delete the desktop entry + if [ -f "$DESKTOP_ENTRY" ]; then + echo -e "${YELLOW}Removing desktop entry...${RESET}" + rm "$DESKTOP_ENTRY" + + # Update the desktop database for GNOME, Unity, XFCE, etc. + echo -e "${YELLOW}Updating desktop database...${RESET}" + if command -v update-desktop-database &> /dev/null; then + update-desktop-database "$DESKTOP_DIR" fi # Update the KDE desktop database if KDE is in use if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null - then + if command -v kbuildsycoca5 &> /dev/null; then kbuildsycoca5 fi fi + else + echo -e "${RED}Desktop entry not found. Skipping...${RESET}" + fi - echo "Phoenix uninstalled successfully." + # Remove the installation directory and its contents + if [ -d "$INSTALL_DIR" ]; then + echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" + rm -rf "$INSTALL_DIR" + else + echo -e "${RED}Installation directory not found. Skipping...${RESET}" + fi + echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" } -# Check for command-line arguments -if [[ "$1" == "--uninstall" ]]; then - uninstall -else - install -fi \ No newline at end of file +show_help() { + echo "Usage: $0 [OPTION]" + echo "Install, upgrade, or uninstall Phoenix Code." + echo + echo "Options:" + echo " -h, --help Display this help and exit" + echo " --uninstall Uninstall Phoenix Code" + echo " --upgrade Upgrade Phoenix Code to the latest version" + echo + echo "Without any options, the script will install Phoenix Code." +} + +# Check for GUI session by looking for DISPLAY or WAYLAND_DISPLAY variables +if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then + echo "This script should only be run from terminals in GUI sessions." + exit 1 +fi + +case "${1-}" in + -h|--help) + show_help # Function to show help + ;; + --uninstall) + uninstall # Function to uninstall + ;; + --upgrade) + upgrade # Function to upgrade + ;; + "") + # This case handles when $1 is unset (acts as a default action) + install # Function to install + ;; + *) + # This case handles unexpected arguments + echo "Invalid option: $1" >&2 + show_help # Assuming you have a function to show usage information + exit 1 + ;; +esac From 9cb3eb4b81b798e9f8f78bb74b1992c625a1db1d Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 27 Feb 2024 13:15:00 +0000 Subject: [PATCH 404/864] ci: tauri release update notification json --- docs/tauri/update-latest-stable-prod.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 9d98fe94..bfc0e2ca 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,6 +1,6 @@ { "version": "3.4.4", - "notes": "# 🚀 Phoenix Code Beta 2 is here 🚀 \r\n\r\nWe have addressed most of the issues and feedback we got from beta 1.\r\nWhat's New:\r\n\r\n1. Windows native apps are now available along with Mac and Linux.\r\n1. Linux users get a boost! New native binaries are available for a wider range of Linux distributions(Ubuntu/Debian, Fedora, Arch Linux and much more), offering better performance and broader support compared to the previous AppImage format.\r\n1. Stability and bug fixes.", + "notes": "# 🚀 Phoenix Code Beta 2 is here 🚀 \r\n\r\nWe have addressed most of the issues and feedback we got from beta 1.\r\nWhat's New:\r\n\r\n1. Windows native apps are now available along with Mac and Linux.\r\n1. Linux users get a boost! New native binaries are available for a wider range of Linux distributions(Ubuntu/Debian, Fedora, Arch Linux and much more), offering better performance and broader support compared to the previous AppImage format.\r\n1. Stability and bug fixes.\r\nplease share your thoughts and feedback @ [GitHub issues page](https://github.com/phcode-dev/phoenix/issues/new/choose).\r\n\r\n## 🚀 Mac (Intel/M1) DMGs 🚀\r\nDownload M1/Apple silicon macs: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_aarch64.dmg\r\nDownload Intel Macs: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64.dmg\r\n\r\n## 🚀 Windows Installers 🚀\r\n\r\nDownload: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64-setup.exe\r\n\r\n## 🚀 Linux Installation 🚀\r\n\r\n**🔧 Installation Instructions**\r\nTo dive into the Linux beta version, simply execute the following command in your terminal:\r\n```bash\r\nwget -qO- https://updates.phcode.io/linux/installer.sh | bash\r\n```\r\n\r\n**🗑️ Uninstallation**\r\nIf you need to uninstall the beta version, please use the following command:\r\n```bash\r\nwget -qO- https://updates.phcode.io/linux/installer.sh | bash -s -- --uninstall\r\n```", "pub_date": "2024-02-27T11:48:54.612Z", "platforms": { "linux-x86_64": { From cb84fb12b81c5fd5edd8950d1ae65620b13c2c9a Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 27 Feb 2024 20:05:49 +0530 Subject: [PATCH 405/864] fix: installer was not lauching repair mode when lauched from wget --- docs/linux/installer.sh | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index c28b165c..73eb5f1c 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -543,21 +543,28 @@ install() { # Check if the application is already installed if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" - - # Simplified prompt for reinstall without detailed explanation - read -r -p "Would you like to reinstall it? (y/N): " response - case "$response" in - [Yy]* ) - echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" - uninstall - downloadAndInstall - copyFilesToDestination - ;; - * ) - echo -e "${RED}Reinstall aborted by the user.${RESET}" - exit 0 - ;; - esac + # Checking if the shell has a controlling terminal if its non interactive reinstall phoenix with latest version + if [ ! -t 0 ]; then + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + uninstall + downloadAndInstall + copyFilesToDestination + else + # Simplified prompt for reinstall without detailed explanation + read -r -p "Would you like to reinstall it? (y/N): " response + case "$response" in + [Yy]* ) + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + uninstall + downloadAndInstall + copyFilesToDestination + ;; + * ) + echo -e "${RED}Reinstall aborted by the user.${RESET}" + exit 0 + ;; + esac + fi else downloadAndInstall copyFilesToDestination From b32246d8de83ef04fbe268d26e416781a83bc13d Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 3 Mar 2024 16:57:36 +0530 Subject: [PATCH 406/864] chore: update win installer script as text file --- package.json | 4 ++-- .../src/bundle/windows/nsis/{installer.nsi => installer.txt} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename src-tauri/src/bundle/windows/nsis/{installer.nsi => installer.txt} (100%) diff --git a/package.json b/package.json index a23d8e16..e86c2186 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "_ci-update-phcode-build": "node src-build/update-phcode-build.js", "_watch_src-node": "chokidar '../phoenix/src-node/**/*' --ignore '../phoenix/src-node/node_modules/**/*' -c 'npm run _make_src-node_debug_dev'", "serve": "npm run _servePhoenix && npm run _make_src-node && tauri dev", - "postinstall": "node ./src-build/downloadNodeBinary.js", + "postinstall": "node ./src-build/downloadNodeBinary.js && shx cp src-tauri/src/bundle/windows/nsis/installer.txt src-tauri/src/bundle/windows/nsis/installer.nsi", "cleanNodeBinary": "node src-build/cleanNodeBinary.js", "installNodeArmDarwin": "node ./src-build/downloadNodeBinary.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", "getPackageVersion": "node ./src-build/getVersion.js" @@ -56,4 +56,4 @@ "branch": "tauri", "commit": "214adae16c8ae15f240b239cffac95d11ebda23d" } -} \ No newline at end of file +} diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.txt similarity index 100% rename from src-tauri/src/bundle/windows/nsis/installer.nsi rename to src-tauri/src/bundle/windows/nsis/installer.txt From 589d7f11d62d765c8bbc15f77ca2530232083862 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 3 Mar 2024 16:59:52 +0530 Subject: [PATCH 407/864] chore: update gitignore --- .gitignore | 2 ++ package-lock.json | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5b4c7492..113ef6d0 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ dist-ssr *.njsproj *.sln *.sw? + +src-tauri/src/bundle/windows/nsis/installer.nsi diff --git a/package-lock.json b/package-lock.json index 60dcbb9a..4f9daf87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.3.6", + "version": "3.4.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.3.6", + "version": "3.4.4", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.9", From a281503615281f70e51e2b57bb64d6251900074f Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 3 Mar 2024 17:15:43 +0530 Subject: [PATCH 408/864] Revert "chore: update gitignore" This reverts commit 589d7f11d62d765c8bbc15f77ca2530232083862. --- .gitignore | 2 -- package-lock.json | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 113ef6d0..5b4c7492 100644 --- a/.gitignore +++ b/.gitignore @@ -34,5 +34,3 @@ dist-ssr *.njsproj *.sln *.sw? - -src-tauri/src/bundle/windows/nsis/installer.nsi diff --git a/package-lock.json b/package-lock.json index 4f9daf87..60dcbb9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.4.4", + "version": "3.3.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.4.4", + "version": "3.3.6", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.9", From f0144fa4087945e605d568dfdc8f514f57f0f0fd Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 3 Mar 2024 17:16:37 +0530 Subject: [PATCH 409/864] Revert "chore: update win installer script as text file" This reverts commit b32246d8de83ef04fbe268d26e416781a83bc13d. --- package.json | 4 ++-- .../src/bundle/windows/nsis/{installer.txt => installer.nsi} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename src-tauri/src/bundle/windows/nsis/{installer.txt => installer.nsi} (100%) diff --git a/package.json b/package.json index e86c2186..a23d8e16 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "_ci-update-phcode-build": "node src-build/update-phcode-build.js", "_watch_src-node": "chokidar '../phoenix/src-node/**/*' --ignore '../phoenix/src-node/node_modules/**/*' -c 'npm run _make_src-node_debug_dev'", "serve": "npm run _servePhoenix && npm run _make_src-node && tauri dev", - "postinstall": "node ./src-build/downloadNodeBinary.js && shx cp src-tauri/src/bundle/windows/nsis/installer.txt src-tauri/src/bundle/windows/nsis/installer.nsi", + "postinstall": "node ./src-build/downloadNodeBinary.js", "cleanNodeBinary": "node src-build/cleanNodeBinary.js", "installNodeArmDarwin": "node ./src-build/downloadNodeBinary.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", "getPackageVersion": "node ./src-build/getVersion.js" @@ -56,4 +56,4 @@ "branch": "tauri", "commit": "214adae16c8ae15f240b239cffac95d11ebda23d" } -} +} \ No newline at end of file diff --git a/src-tauri/src/bundle/windows/nsis/installer.txt b/src-tauri/src/bundle/windows/nsis/installer.nsi similarity index 100% rename from src-tauri/src/bundle/windows/nsis/installer.txt rename to src-tauri/src/bundle/windows/nsis/installer.nsi From 20e3a872458c54c6cf1f187aaff617c845eb4fd8 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 4 Mar 2024 14:44:26 +0000 Subject: [PATCH 410/864] ci: update phcode version to 3.4.6 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index a23d8e16..25c8cdde 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.4.4", + "version": "3.4.6", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "214adae16c8ae15f240b239cffac95d11ebda23d" + "commit": "0c5ca39380f0c7ee74d524006007040b28cf5bcf" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 33951edc..9292a986 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.4.4" +version = "3.4.6" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 21a4266d..aa7b3e69 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.4.4" + "version": "3.4.6" }, "tauri": { "allowlist": { From 1a3290851c82ca129832fe07037a6e8b4daa9701 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 22:03:11 +0000 Subject: [PATCH 411/864] build(deps): bump mio from 0.8.9 to 0.8.11 in /src-tauri Bumps [mio](https://github.com/tokio-rs/mio) from 0.8.9 to 0.8.11. - [Release notes](https://github.com/tokio-rs/mio/releases) - [Changelog](https://github.com/tokio-rs/mio/blob/master/CHANGELOG.md) - [Commits](https://github.com/tokio-rs/mio/compare/v0.8.9...v0.8.11) --- updated-dependencies: - dependency-name: mio dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index acee3a77..eb704fa6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2198,9 +2198,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -2742,7 +2742,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.3.9" +version = "3.4.6" dependencies = [ "clipboard-files", "fix-path-env", From a4404280643464733043d957acfafc357691ee6c Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 5 Mar 2024 15:55:17 +0000 Subject: [PATCH 412/864] ci: tauri release update notification json --- docs/install.json | 6 +++--- docs/tauri/update-latest-stable-prod.json | 26 +++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/install.json b/docs/install.json index 0a37c029..eff91b92 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,7 +1,7 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64.dmg" + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_3.4.6_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_3.4.6_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_3.4.6_x64.dmg" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index bfc0e2ca..e78b278b 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,23 +1,23 @@ { - "version": "3.4.4", - "notes": "# 🚀 Phoenix Code Beta 2 is here 🚀 \r\n\r\nWe have addressed most of the issues and feedback we got from beta 1.\r\nWhat's New:\r\n\r\n1. Windows native apps are now available along with Mac and Linux.\r\n1. Linux users get a boost! New native binaries are available for a wider range of Linux distributions(Ubuntu/Debian, Fedora, Arch Linux and much more), offering better performance and broader support compared to the previous AppImage format.\r\n1. Stability and bug fixes.\r\nplease share your thoughts and feedback @ [GitHub issues page](https://github.com/phcode-dev/phoenix/issues/new/choose).\r\n\r\n## 🚀 Mac (Intel/M1) DMGs 🚀\r\nDownload M1/Apple silicon macs: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_aarch64.dmg\r\nDownload Intel Macs: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64.dmg\r\n\r\n## 🚀 Windows Installers 🚀\r\n\r\nDownload: https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64-setup.exe\r\n\r\n## 🚀 Linux Installation 🚀\r\n\r\n**🔧 Installation Instructions**\r\nTo dive into the Linux beta version, simply execute the following command in your terminal:\r\n```bash\r\nwget -qO- https://updates.phcode.io/linux/installer.sh | bash\r\n```\r\n\r\n**🗑️ Uninstallation**\r\nIf you need to uninstall the beta version, please use the following command:\r\n```bash\r\nwget -qO- https://updates.phcode.io/linux/installer.sh | bash -s -- --uninstall\r\n```", - "pub_date": "2024-02-27T11:48:54.612Z", + "version": "3.4.6", + "notes": "# Introducing Phoenix Code Desktop- Now on Windows, Mac & Linux 🎉\r\n\r\nWe're thrilled to share a huge update with you all today - Phoenix Code native apps are officially here! 🎉 . Get your copy from [phcode.io](https://phcode.io) !\r\n\r\nWe have been working hard over the last several months to make native apps possible. It took a lot of effort and perseverance with our limited resources to reach this far. We hope to have your support in doing more :)\r\n\r\nWith this update, Phoenix Code can now run almost anywhere! Native apps are available for Windows, Mac and most Linux distributions. For Chrome-OS and other platforms, simply use the web browser version; no install needed.\r\n\r\n## Looking Ahead\r\n\r\n> Our guiding principle is to make coding as intuitive and fun as playing a video game - for web developers, designers, and students.\r\n\r\nWith the native apps now available, we're starting the next phase of our journey. Beginning this month, there will be\r\na new update of Phoenix Code released every month.\r\n\r\nHowever, our ambitions come with costs, and it's your support that makes all the difference.\r\n\r\n## How You Can Support:\r\n * **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n * **Spread the word** about Phoenix to friends and colleagues.\r\n * [**Consider supporting us** on Open Collective](https://opencollective.com/phoenix-ide). Every contribution helps us to keep improving and expanding Phoenix Code.\r\n\r\nWe're grateful for the incredible support this community has shown us so far. Let's continue to make Phoenix Code even better, together.\r\n\r\nWith gratitude,\r\n\r\nThe Phoenix Team\r\n", + "pub_date": "2024-03-04T17:35:02.192Z", "platforms": { - "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnQxU2FsYmR2NzRqWlJJN0JEUUhmUG40YXVuRjQ1V3dlbGsxbDlWQ3grRitucVhKU0dWdnRXOGRxdEJPL0c5T1B3THFsTy95Y2NibFhoSmFORzBNQlFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5MDMzMzM4CWZpbGU6cGhvZW5peC1jb2RlXzMuNC40X2FtZDY0LkFwcEltYWdlLnRhci5negpyZlVhWVcxZWZuSlBrTlNqNnhob21OL3Q5cExqTUNoZSs1RmJKVG4xZkRGdkljQmpPZHd4QUdlOUlaNzVpNzVtSUhyeUNXR1RSS0h2d2FqU2xZOFRCQT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/phoenix-code_3.4.4_amd64.AppImage.tar.gz" - }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnIrdkdnMGJPb1dwYis5ZkRLMkYveklkUTNBaHFFMVp4SE40WW1KaS80WUVQN25HWks0NG9OTXIwcmFWY2M4S0tYRkNJTWloVmdGeTc4TVJRUElncUFzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5MDMzNDAzCWZpbGU6UGhvZW5peCBDb2RlXzMuNC40X3g2NC1zZXR1cC5uc2lzLnppcApDWG9TV21lTVRwNG00YTVjTks4YTRiNjZqaVRIY05tcno4eFREOXhGSXNEUFRHMHNhTktXM0J4Vys3cnhxRDM0eCtRKzZzZDRtREVUWERyeHB1TTJBQT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_3.4.4_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmgrdFFUblFKZXBONHhCL0tiMTdEQ21PWXp3VnNpOHE1b1NpNW5yVGxucnJlNmIvckVNT2poVzUvSEV6WEgyRWRFUTJ6Z3g1Ykc5RFkwcXFkMmRMRUFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5NTcxNDg1CWZpbGU6UGhvZW5peCBDb2RlXzMuNC42X3g2NC1zZXR1cC5uc2lzLnppcApDRU9WUTFuSVdNMDI1djMxMk9KT0pXcnRLeWxhWjlQUmI3emdualA2MnpBTmpqZGhKNlhXazc2TGFkWnMxVTNFL2N3d1hxZ0NTS1RRNks0Qng3eWNDQT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_3.4.6_x64-setup.nsis.zip" + }, + "linux-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRmNVRTZXFrYlJCeGw1YTVIdTJpcVlZWTR5SnZaWkY5eXdDY01TaFp6MDUzQjBYUXA2a3FpTkZ0QVIrNmI3VHlaamhNdVZRc3BJTElnMTZ2a213ZFFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5NTcxNDg5CWZpbGU6cGhvZW5peC1jb2RlXzMuNC42X2FtZDY0LkFwcEltYWdlLnRhci5negptOXNnQUNYYVk5a2tDVWN5ZUZtUTZpank0eUdMUHo0ZlVxOVRoRnNhU0VvejJiMEJIbGxnQW1Vb1lacWJyaXI4Y24rU0lsT3J0Yk9FK1ZualhjUi9EUT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/phoenix-code_3.4.6_amd64.AppImage.tar.gz" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRyaS92SXhWbll4MEZUN1RwMEpHN0xuOWRLd2FDaklMeXdSZmo3VmNVWENPZXF4NXdxWUhaU1k1YjRmV2NSSC9YUkMyUlFCMkQ5aVBhVXJuTTZyRlFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5MDMzNjc1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKUlpoNUxTU0l1K2VqT3ZLd2tMTUpCQzdKb3Zmaytta0lyOVU2N01UVXFTS29TSnlEQkVDZlNHUWNkb2MvWWJMb0FlUXVEL3pnSC9xSkNrNlJFaTdpQmc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmx0RGdMYUxESUhrVEtiSmxlMndKQjZmWWZmcnRTYWVkUEt2YWlYMDVBSk1hVWZqOEI0RnUwVEVFb3JFaU5idUFraWFXSk5zR1hZNmNFRWp5Y3dqM3dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5NTcyNDczCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKU3RiYVdpcnp6aTFlUTVkR21UaERldWxwQ0FYYTk1eTcvSDFTYnlZUExlbEtMODZUREpwL3hYYnFqb3FUam9uNEp5ZlNGekFtNklSL3FIUWFpMUpaQmc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnV6d0F1WXNuaDhmcUVFemlEUUlGVVJFWkptNThaZjFiK1QxYnNEbkFYL0gyRFRvdERPOFhwdXZWTE9HY0x0eDdzVS9XeklKUjRnR1J0SjBvaUF0dVE0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5MDM0MzQ4CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKVE1IcTNHZDF3QkFjQ2Y0N1pCNER5YXkyT1hmYlZWREVDMUlKT01VZURvbEFmQVl3NW1DRmx3Y0Fsbi9kcEZRQ3lmY1dzcjZYRCs4eEhpNGpXYUJ5QlE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.4/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmltVU02SWdVY042bXZYQ1dqQ0JyUWRDbDF6VXY1d1BlV1RiL2xUQ0haR2l6c3RPcTAvMlVtWmxwT2VOLzZwZFFKajl6a2s1QkM2RStDMmZjOE5yN2d3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5NTczNjk0CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKZ1hVcmN1Ym5EYXN3U3dhbklZa0dyamNuTEswSzhNWG9XTlhyYVZKVTl1TS92NzdLelNKMFhiSkhyZzN6RVlFQTlqUzBEamFaaGJ5QXd5M0dtb3ZsQWc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 6aeae674df1dda5800e262ea15f1d55bcda3dbc0 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 6 Mar 2024 22:56:25 +0530 Subject: [PATCH 413/864] fix: download node binary was failing in github actions with auth error --- src-build/downloadNodeBinary.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index ae81f23c..1b89ecfb 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -57,12 +57,21 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { } const writer = fs.createWriteStream(outputPath); - const { data } = await axios({ + const GH_TOKEN = process.env.GH_TOKEN; // Access the environment variable + const config = { url: asset.browser_download_url, method: 'GET', responseType: 'stream', timeout: 10000 - }); + }; + // Only add the Authorization header if GH_TOKEN is set + if (GH_TOKEN) { + config.headers = { + 'Authorization': `Bearer ${GH_TOKEN}` + }; + } + + const { data } = await axios(config); data.pipe(writer); From 9848be29b0fda750351d173a9d926f3bfbaeb731 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 6 Mar 2024 23:15:05 +0530 Subject: [PATCH 414/864] fix: update gh workflow to authenticate gh api --- .github/workflows/desktop-linux-test-pull.yml | 6 ++++++ .github/workflows/desktop-mac-m1-test-pull.yml | 4 ++++ .github/workflows/desktop-mac-test-pull.yml | 6 ++++++ .github/workflows/desktop-windows-test-pull.yml | 6 ++++++ .github/workflows/prod-desktop-tests-on-pull.yml | 16 ++++++++++++++++ .../workflows/staging-desktop-tests-on-pull.yml | 14 ++++++++++++++ .github/workflows/tauri-build-dev.yml | 8 ++++++++ .github/workflows/tauri-build-prod.yml | 8 ++++++++ .github/workflows/tauri-build-staging.yml | 6 ++++++ .github/workflows/update-phcode-build.yml | 4 +++- 10 files changed, 77 insertions(+), 1 deletion(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index fccd1010..84676cbe 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -28,9 +28,13 @@ jobs: sudo apt-get install xvfb - name: npm install ci deps + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -40,6 +44,8 @@ jobs: npm run release:dev - name: build test runner + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/desktop-mac-m1-test-pull.yml b/.github/workflows/desktop-mac-m1-test-pull.yml index 26432218..f5be6ee8 100644 --- a/.github/workflows/desktop-mac-m1-test-pull.yml +++ b/.github/workflows/desktop-mac-m1-test-pull.yml @@ -26,6 +26,8 @@ jobs: run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -35,6 +37,8 @@ jobs: npm run release:prod - name: build test runner + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 276ea26a..df53d242 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -21,9 +21,13 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: npm install ci deps + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -33,6 +37,8 @@ jobs: npm run release:dev - name: build test runner + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index ea7a36a1..d24e9f96 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -21,9 +21,13 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: npm install ci deps + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -33,6 +37,8 @@ jobs: npm run release:dev - name: build test runner + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index 41349bd6..5f76a8e8 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -26,9 +26,13 @@ jobs: sudo apt-get install xvfb - name: npm install ci deps + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -90,9 +94,13 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: npm install ci deps + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -102,6 +110,8 @@ jobs: npm run release:prod - name: build test runner + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run releaseDistTestDebug @@ -154,9 +164,13 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: npm install ci deps + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -166,6 +180,8 @@ jobs: npm run release:prod - name: build test runner + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index 4b29e81b..fabd229f 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -26,9 +26,13 @@ jobs: sudo apt-get install xvfb - name: npm install ci deps + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -38,6 +42,8 @@ jobs: npm run release:staging - name: build test runner + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run releaseDistTestDebug @@ -83,9 +89,13 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: npm install ci deps + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -140,6 +150,8 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: npm install ci deps + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm ci - name: Download phoenix and build build phoenix dist-test @@ -152,6 +164,8 @@ jobs: npm run release:staging - name: build test runner + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 4bcc2dc0..d9968c1f 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -53,6 +53,8 @@ jobs: with: node-version: 20 - name: install frontend dependencies + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run _ci-cloneAndBuildPhoenix @@ -107,6 +109,8 @@ jobs: sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run _ci-release:dev @@ -233,6 +237,8 @@ jobs: ls src-tauri/src-node - name: setup env for mac arm (Mac only) + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} if: matrix.platform == 'macos-latest' run: | rustup target add aarch64-apple-darwin @@ -290,6 +296,8 @@ jobs: sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run _ci-release:dev diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 01b471e9..266b557f 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -53,6 +53,8 @@ jobs: with: node-version: 20 - name: install frontend dependencies + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run _ci-cloneAndBuildPhoenix @@ -107,6 +109,8 @@ jobs: sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run _ci-release:prod @@ -234,6 +238,8 @@ jobs: ls src-tauri/src-node - name: setup env for mac arm (Mac only) + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} if: matrix.platform == 'macos-latest' run: | rustup target add aarch64-apple-darwin @@ -290,6 +296,8 @@ jobs: sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run _ci-release:prod diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index bf4fa52b..0971d77a 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -53,6 +53,8 @@ jobs: with: node-version: 20 - name: install frontend dependencies + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run _ci-cloneAndBuildPhoenix @@ -233,6 +235,8 @@ jobs: ls src-tauri/src-node - name: setup env for mac arm (Mac only) + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} if: matrix.platform == 'macos-latest' run: | rustup target add aarch64-apple-darwin @@ -289,6 +293,8 @@ jobs: sudo apt-get install -y libunwind-dev sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run _ci-release:staging diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 8da5dc58..5a266cca 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -23,6 +23,8 @@ jobs: node-version: 20 - name: Update phcode and version + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | npm ci npm run _ci-update-phcode-build ${{ github.event.client_payload.sha }} @@ -53,4 +55,4 @@ jobs: if: ${{ steps.cpr.outputs.pull-request-number }} run: | echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" - echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" \ No newline at end of file + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" From fc4d1cb8021470e6e639cd46a3debb75c8dd9566 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 7 Mar 2024 12:42:09 +0530 Subject: [PATCH 415/864] feat: appimage remove from release --- .github/workflows/tauri-build-dev.yml | 10 +--------- .github/workflows/tauri-build-prod.yml | 10 +--------- .github/workflows/tauri-build-staging.yml | 10 +--------- 3 files changed, 3 insertions(+), 27 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index d9968c1f..6e35d493 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-22.04, windows-latest ] + platform: [ macos-latest, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -100,14 +100,6 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-22.04' - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - sudo apt-get install -y libwebrtc-audio-processing-dev - sudo apt-get install -y libunwind-dev - sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 266b557f..654eac14 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-22.04, windows-latest ] + platform: [ macos-latest, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -100,14 +100,6 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-22.04' - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - sudo apt-get install -y libwebrtc-audio-processing-dev - sudo apt-get install -y libunwind-dev - sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 0971d77a..2cd5dc4e 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, ubuntu-22.04, windows-latest ] + platform: [ macos-latest, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -100,14 +100,6 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable - - name: install dependencies (ubuntu only) - if: matrix.platform == 'ubuntu-22.04' - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - sudo apt-get install -y libwebrtc-audio-processing-dev - sudo apt-get install -y libunwind-dev - sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies run: | npm ci From 3a01dffe6788f30bf02b8a26bd04d65347962d32 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 7 Mar 2024 15:12:06 +0530 Subject: [PATCH 416/864] chore: prod launch browser only notification --- docs/appNotifications/prod/root/banner.json | 8 ++++++++ docs/appNotifications/prod/root/toast.json | 2 ++ docs/appNotifications/staging/root/banner.json | 6 ++++++ 3 files changed, 16 insertions(+) create mode 100644 docs/appNotifications/prod/root/banner.json create mode 100644 docs/appNotifications/prod/root/toast.json diff --git a/docs/appNotifications/prod/root/banner.json b/docs/appNotifications/prod/root/banner.json new file mode 100644 index 00000000..326f7bc6 --- /dev/null +++ b/docs/appNotifications/prod/root/banner.json @@ -0,0 +1,8 @@ +{ + "DESKTOP_APP_BANNER": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "

Introducing Phoenix Code Desktop Apps: Now available for Windows, Mac & Linux. Click here to get it now!
", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM" : "allBrowser" + } +} \ No newline at end of file diff --git a/docs/appNotifications/prod/root/toast.json b/docs/appNotifications/prod/root/toast.json new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/docs/appNotifications/prod/root/toast.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/docs/appNotifications/staging/root/banner.json b/docs/appNotifications/staging/root/banner.json index 45f2b5f0..3f30639c 100644 --- a/docs/appNotifications/staging/root/banner.json +++ b/docs/appNotifications/staging/root/banner.json @@ -4,5 +4,11 @@ "HTML_CONTENT": "
Welcome to Phoenix Code dev community! Click here to chat with our Discord Community.
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "all" + }, + "DESKTOP_APP_BANNER": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "
Introducing Phoenix Code Desktop Apps: Now available for Windows, Mac & Linux. Click here to get it now!
", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM" : "allBrowser" } } \ No newline at end of file From 88598fd570dea4a8c148dfc6f7edd6da5a1049ed Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 7 Mar 2024 15:17:45 +0530 Subject: [PATCH 417/864] chore: prod launch browser only notification rephrase --- docs/appNotifications/prod/root/banner.json | 2 +- docs/appNotifications/staging/root/banner.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/appNotifications/prod/root/banner.json b/docs/appNotifications/prod/root/banner.json index 326f7bc6..af561164 100644 --- a/docs/appNotifications/prod/root/banner.json +++ b/docs/appNotifications/prod/root/banner.json @@ -1,7 +1,7 @@ { "DESKTOP_APP_BANNER": { "DANGER_SHOW_ON_EVERY_BOOT" : false, - "HTML_CONTENT": "
Introducing Phoenix Code Desktop Apps: Now available for Windows, Mac & Linux. Click here to get it now!
", + "HTML_CONTENT": "
Introducing Phoenix Code Desktop Apps for Windows, Mac & Linux. Click here to get it now!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" } diff --git a/docs/appNotifications/staging/root/banner.json b/docs/appNotifications/staging/root/banner.json index 3f30639c..4688b4da 100644 --- a/docs/appNotifications/staging/root/banner.json +++ b/docs/appNotifications/staging/root/banner.json @@ -7,7 +7,7 @@ }, "DESKTOP_APP_BANNER": { "DANGER_SHOW_ON_EVERY_BOOT" : false, - "HTML_CONTENT": "
Introducing Phoenix Code Desktop Apps: Now available for Windows, Mac & Linux. Click here to get it now!
", + "HTML_CONTENT": "
Introducing Phoenix Code Desktop Apps for Windows, Mac & Linux. Click here to get it now!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" } From 1259aba49195488d8cd59481105305be124d4fe1 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 11 Mar 2024 12:22:35 +0530 Subject: [PATCH 418/864] update notification localise --- docs/appNotifications/prod/de/banner.json | 8 ++++++++ docs/appNotifications/prod/de/toast.json | 2 ++ docs/appNotifications/prod/fr/banner.json | 8 ++++++++ docs/appNotifications/prod/fr/toast.json | 2 ++ docs/appNotifications/prod/it/banner.json | 8 ++++++++ docs/appNotifications/prod/it/toast.json | 2 ++ docs/appNotifications/prod/ja/banner.json | 8 ++++++++ docs/appNotifications/prod/ja/toast.json | 2 ++ docs/appNotifications/prod/ko/banner.json | 8 ++++++++ docs/appNotifications/prod/ko/toast.json | 2 ++ docs/appNotifications/prod/pt-BR/banner.json | 8 ++++++++ docs/appNotifications/prod/pt-BR/toast.json | 2 ++ 12 files changed, 60 insertions(+) create mode 100644 docs/appNotifications/prod/de/banner.json create mode 100644 docs/appNotifications/prod/de/toast.json create mode 100644 docs/appNotifications/prod/fr/banner.json create mode 100644 docs/appNotifications/prod/fr/toast.json create mode 100644 docs/appNotifications/prod/it/banner.json create mode 100644 docs/appNotifications/prod/it/toast.json create mode 100644 docs/appNotifications/prod/ja/banner.json create mode 100644 docs/appNotifications/prod/ja/toast.json create mode 100644 docs/appNotifications/prod/ko/banner.json create mode 100644 docs/appNotifications/prod/ko/toast.json create mode 100644 docs/appNotifications/prod/pt-BR/banner.json create mode 100644 docs/appNotifications/prod/pt-BR/toast.json diff --git a/docs/appNotifications/prod/de/banner.json b/docs/appNotifications/prod/de/banner.json new file mode 100644 index 00000000..8e2023df --- /dev/null +++ b/docs/appNotifications/prod/de/banner.json @@ -0,0 +1,8 @@ +{ + "DESKTOP_APP_BANNER": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "
Wir stellen vor Phoenix Code Desktop-Apps für Windows, Mac und Linux. Klicken Sie hier, um es jetzt zu erhalten!
", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM" : "allBrowser" + } +} \ No newline at end of file diff --git a/docs/appNotifications/prod/de/toast.json b/docs/appNotifications/prod/de/toast.json new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/docs/appNotifications/prod/de/toast.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/docs/appNotifications/prod/fr/banner.json b/docs/appNotifications/prod/fr/banner.json new file mode 100644 index 00000000..5a4bf362 --- /dev/null +++ b/docs/appNotifications/prod/fr/banner.json @@ -0,0 +1,8 @@ +{ + "DESKTOP_APP_BANNER": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "
Présentation des applications de bureau de Phoenix Code pour Windows, Mac et Linux. Cliquez ici pour l'obtenir maintenant !
", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM" : "allBrowser" + } +} \ No newline at end of file diff --git a/docs/appNotifications/prod/fr/toast.json b/docs/appNotifications/prod/fr/toast.json new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/docs/appNotifications/prod/fr/toast.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/docs/appNotifications/prod/it/banner.json b/docs/appNotifications/prod/it/banner.json new file mode 100644 index 00000000..0d5a41bd --- /dev/null +++ b/docs/appNotifications/prod/it/banner.json @@ -0,0 +1,8 @@ +{ + "DESKTOP_APP_BANNER": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "
Presentazione delle app desktop di Phoenix Code per Windows, Mac e Linux. Fai clic qui per ottenerlo ora!
", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM" : "allBrowser" + } +} \ No newline at end of file diff --git a/docs/appNotifications/prod/it/toast.json b/docs/appNotifications/prod/it/toast.json new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/docs/appNotifications/prod/it/toast.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/docs/appNotifications/prod/ja/banner.json b/docs/appNotifications/prod/ja/banner.json new file mode 100644 index 00000000..4192b1e2 --- /dev/null +++ b/docs/appNotifications/prod/ja/banner.json @@ -0,0 +1,8 @@ +{ + "DESKTOP_APP_BANNER": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "
Windows、Mac、Linux 用の Phoenix Code のデスクトップ アプリを紹介します。 ここをクリックして今すぐ入手してください。
", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM" : "allBrowser" + } +} \ No newline at end of file diff --git a/docs/appNotifications/prod/ja/toast.json b/docs/appNotifications/prod/ja/toast.json new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/docs/appNotifications/prod/ja/toast.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/docs/appNotifications/prod/ko/banner.json b/docs/appNotifications/prod/ko/banner.json new file mode 100644 index 00000000..ddd01e81 --- /dev/null +++ b/docs/appNotifications/prod/ko/banner.json @@ -0,0 +1,8 @@ +{ + "DESKTOP_APP_BANNER": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "
Windows, Mac 및 Linux용 소개 Phoenix Code 데스크톱 앱. 지금 다운로드하려면 여기를 클릭하세요!
", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM" : "allBrowser" + } +} \ No newline at end of file diff --git a/docs/appNotifications/prod/ko/toast.json b/docs/appNotifications/prod/ko/toast.json new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/docs/appNotifications/prod/ko/toast.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/docs/appNotifications/prod/pt-BR/banner.json b/docs/appNotifications/prod/pt-BR/banner.json new file mode 100644 index 00000000..c86e06ac --- /dev/null +++ b/docs/appNotifications/prod/pt-BR/banner.json @@ -0,0 +1,8 @@ +{ + "DESKTOP_APP_BANNER": { + "DANGER_SHOW_ON_EVERY_BOOT" : false, + "HTML_CONTENT": "
Apresentamos os aplicativos de desktop Phoenix Code para Windows, Mac e Linux. Clique aqui para obtê-lo agora!
", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM" : "allBrowser" + } +} \ No newline at end of file diff --git a/docs/appNotifications/prod/pt-BR/toast.json b/docs/appNotifications/prod/pt-BR/toast.json new file mode 100644 index 00000000..7a73a41b --- /dev/null +++ b/docs/appNotifications/prod/pt-BR/toast.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file From 687d60d08f682fcc8c0a0350bc9fa209087053c7 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 11 Mar 2024 22:24:12 +0530 Subject: [PATCH 419/864] chore: cargo update --- src-tauri/Cargo.lock | 1223 +++++++++++++++++++++++++----------------- 1 file changed, 726 insertions(+), 497 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index eb704fa6..f1192ae1 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -58,18 +58,18 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "arboard" -version = "3.3.0" +version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafb29b107435aa276664c1db8954ac27a6e105cdad3c88287a199eb0e313c08" +checksum = "a2041f1943049c7978768d84e6d0fd95de98b76d6c4727b09e78ec253d29fa58" dependencies = [ - "clipboard-win", - "core-graphics", + "clipboard-win 5.2.0", + "core-graphics 0.23.1", "image", "log", "objc", @@ -77,7 +77,8 @@ dependencies = [ "objc_id", "parking_lot", "thiserror", - "winapi", + "windows-sys 0.48.0", + "wl-clipboard-rs", "x11rb", ] @@ -93,13 +94,13 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" +checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" dependencies = [ "concurrent-queue", - "event-listener 4.0.0", - "event-listener-strategy", + "event-listener 5.2.0", + "event-listener-strategy 0.5.0", "futures-core", "pin-project-lite", ] @@ -110,11 +111,11 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" dependencies = [ - "async-lock 3.1.2", + "async-lock 3.3.0", "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 2.0.1", + "futures-lite 2.2.0", "slab", ] @@ -152,18 +153,18 @@ dependencies = [ [[package]] name = "async-io" -version = "2.2.1" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6d3b15875ba253d1110c740755e246537483f152fa334f91abd7fe84c88b3ff" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" dependencies = [ - "async-lock 3.1.2", + "async-lock 3.3.0", "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.0.1", + "futures-lite 2.2.0", "parking", - "polling 3.3.1", - "rustix 0.38.26", + "polling 3.5.0", + "rustix 0.38.31", "slab", "tracing", "windows-sys 0.52.0", @@ -180,12 +181,12 @@ dependencies = [ [[package]] name = "async-lock" -version = "3.1.2" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea8b3453dd7cc96711834b75400d671b73e3656975fa68d9f277163b7f7e316" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" dependencies = [ - "event-listener 4.0.0", - "event-listener-strategy", + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", "pin-project-lite", ] @@ -202,7 +203,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.26", + "rustix 0.38.31", "windows-sys 0.48.0", ] @@ -214,7 +215,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -223,13 +224,13 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io 2.2.1", + "async-io 2.3.2", "async-lock 2.8.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.26", + "rustix 0.38.31", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -237,19 +238,19 @@ dependencies = [ [[package]] name = "async-task" -version = "4.5.0" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4eb2cdb97421e01129ccb49169d8279ed21e829929144f4a22a6e54ac549ca1" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -322,9 +323,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bincode" @@ -343,9 +344,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "block" @@ -369,11 +370,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ "async-channel", - "async-lock 3.1.2", + "async-lock 3.3.0", "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 2.0.1", + "futures-lite 2.2.0", "piper", "tracing", ] @@ -401,9 +402,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.8.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", "serde", @@ -411,15 +412,21 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "bytecount" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" [[package]] name = "byteorder" @@ -472,12 +479,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cesu8" @@ -507,9 +511,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.5" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" +checksum = "fa50868b64a9a6fda9d593ce778849ea8715cd2a3d2cc17ffdb4a2f2f2f1961d" dependencies = [ "smallvec", "target-lexicon", @@ -521,17 +525,23 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-targets 0.48.5", + "windows-targets 0.52.4", ] [[package]] @@ -564,7 +574,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bc2120eaf094b70a9c58bd1f8bb908cb74fbfe0c9793314567f7f8cea0be383" dependencies = [ - "clipboard-win", + "clipboard-win 4.5.0", "gtk", "objc", "objc-foundation", @@ -578,11 +588,20 @@ version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" dependencies = [ - "error-code", + "error-code 2.3.1", "str-buf", "winapi", ] +[[package]] +name = "clipboard-win" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f9a0700e0127ba15d1d52dd742097f821cd9c65939303a44d970465040a297" +dependencies = [ + "error-code 3.2.0", +] + [[package]] name = "cocoa" version = "0.24.1" @@ -593,8 +612,8 @@ dependencies = [ "block", "cocoa-foundation", "core-foundation", - "core-graphics", - "foreign-types", + "core-graphics 0.22.3", + "foreign-types 0.3.2", "libc", "objc", ] @@ -631,9 +650,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f057a694a54f12365049b0958a1685bb52d567f5593b355fbf685838e873d400" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" dependencies = [ "crossbeam-utils", ] @@ -669,7 +688,20 @@ dependencies = [ "bitflags 1.3.2", "core-foundation", "core-graphics-types", - "foreign-types", + "foreign-types 0.3.2", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", "libc", ] @@ -686,64 +718,55 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset 0.9.0", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-common" @@ -779,24 +802,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "ctor" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" +checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "darling" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ "darling_core", "darling_macro", @@ -804,34 +827,34 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", "serde", @@ -848,6 +871,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-new" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -919,6 +953,21 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading", +] + +[[package]] +name = "downcast-rs" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" + [[package]] name = "dtoa" version = "1.0.9" @@ -942,15 +991,16 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "embed-resource" -version = "2.4.0" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54cc3e827ee1c3812239a9a41dede7b4d7d5d5464faa32d71bd7cba28ce2cb2" +checksum = "c6985554d0688b687c5cb73898a34fbe3ad6c24c58c238a4d91d5e840670ee9d" dependencies = [ "cc", + "memchr", "rustc_version", - "toml 0.8.8", + "toml 0.8.11", "vswhom", - "winreg 0.51.0", + "winreg 0.52.0", ] [[package]] @@ -970,9 +1020,9 @@ dependencies = [ [[package]] name = "enumflags2" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" +checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" dependencies = [ "enumflags2_derive", "serde", @@ -980,13 +1030,13 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" +checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -1015,6 +1065,12 @@ dependencies = [ "str-buf", ] +[[package]] +name = "error-code" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0474425d51df81997e2f90a21591180b38eccf27292d755f3e30750225c175b" + [[package]] name = "event-listener" version = "2.5.3" @@ -1034,9 +1090,20 @@ dependencies = [ [[package]] name = "event-listener" -version = "4.0.0" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" dependencies = [ "concurrent-queue", "parking", @@ -1049,7 +1116,17 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 4.0.0", + "event-listener 4.0.3", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +dependencies = [ + "event-listener 5.2.0", "pin-project-lite", ] @@ -1070,9 +1147,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fdeflate" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -1089,14 +1166,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "redox_syscall", + "windows-sys 0.52.0", ] [[package]] @@ -1108,6 +1185,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + [[package]] name = "flate2" version = "1.0.28" @@ -1130,7 +1213,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared", + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.52", ] [[package]] @@ -1139,6 +1243,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1160,24 +1270,24 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1186,9 +1296,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -1207,46 +1317,45 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3831c2651acb5177cbd83943f3d9c8912c5ad03c76afcc0e9511ba568ec5ebb" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" dependencies = [ "fastrand 2.0.1", "futures-core", "futures-io", - "memchr", "parking", "pin-project-lite", ] [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-io", @@ -1379,12 +1488,12 @@ dependencies = [ [[package]] name = "gethostname" -version = "0.3.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" +checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" dependencies = [ "libc", - "winapi", + "windows-targets 0.48.5", ] [[package]] @@ -1400,9 +1509,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -1505,7 +1614,7 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.4", + "regex-automata 0.4.6", "regex-syntax 0.8.2", ] @@ -1587,7 +1696,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.5", "slab", "tokio", "tokio-util", @@ -1632,9 +1741,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1642,20 +1751,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "html5ever" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5c13fb08e5d4dfc151ee5e88bae63f7773d61852f3bdc73c9f4b9e1bde03148" -dependencies = [ - "log", - "mac", - "markup5ever 0.10.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "html5ever" version = "0.26.0" @@ -1664,7 +1759,7 @@ checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" dependencies = [ "log", "mac", - "markup5ever 0.11.0", + "markup5ever", "proc-macro2", "quote", "syn 1.0.109", @@ -1672,20 +1767,20 @@ dependencies = [ [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", - "itoa 1.0.9", + "itoa 1.0.10", ] [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -1712,9 +1807,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1725,9 +1820,9 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.9", + "itoa 1.0.10", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -1749,16 +1844,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -1798,15 +1893,15 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ "crossbeam-deque", "globset", "log", "memchr", - "regex-automata 0.4.4", + "regex-automata 0.4.6", "same-file", "walkdir", "winapi-util", @@ -1814,14 +1909,13 @@ dependencies = [ [[package]] name = "image" -version = "0.24.7" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ "bytemuck", "byteorder", "color_quant", - "num-rational", "num-traits", "png", "tiff", @@ -1840,9 +1934,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1886,7 +1980,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -1905,9 +1999,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "javascriptcore-rs" @@ -1954,15 +2048,15 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jpeg-decoder" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1979,18 +2073,6 @@ dependencies = [ "treediff", ] -[[package]] -name = "kuchiki" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ea8e9c6e031377cff82ee3001dc8026cdf431ed4e2e6b51f98ab8c73484a358" -dependencies = [ - "cssparser", - "html5ever 0.25.2", - "matches", - "selectors", -] - [[package]] name = "kuchikiki" version = "0.8.2" @@ -1998,7 +2080,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" dependencies = [ "cssparser", - "html5ever 0.26.0", + "html5ever", "indexmap 1.9.3", "matches", "selectors", @@ -2012,9 +2094,19 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets 0.52.4", +] [[package]] name = "libredox" @@ -2022,9 +2114,9 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", - "redox_syscall 0.4.1", + "redox_syscall", ] [[package]] @@ -2044,9 +2136,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -2060,9 +2152,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "loom" @@ -2107,20 +2199,6 @@ dependencies = [ "libc", ] -[[package]] -name = "markup5ever" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a24f40fb03852d1cdd84330cddcaf98e9ec08a7b7768e952fad3b4cf048ec8fd" -dependencies = [ - "log", - "phf 0.8.0", - "phf_codegen 0.8.0", - "string_cache", - "string_cache_codegen", - "tendril", -] - [[package]] name = "markup5ever" version = "0.11.0" @@ -2152,9 +2230,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" @@ -2180,6 +2258,12 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "minisign-verify" version = "0.2.1" @@ -2188,9 +2272,9 @@ checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -2271,12 +2355,34 @@ dependencies = [ "memoffset 0.7.1", ] +[[package]] +name = "nix" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "cfg_aliases", + "libc", +] + [[package]] name = "nodrop" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "notify-rust" version = "4.10.0" @@ -2301,31 +2407,16 @@ dependencies = [ ] [[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" +name = "num-conv" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -2336,7 +2427,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.9", "libc", ] @@ -2424,9 +2515,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -2449,13 +2540,13 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.60" +version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg-if", - "foreign-types", + "foreign-types 0.3.2", "libc", "once_cell", "openssl-macros", @@ -2470,7 +2561,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -2481,9 +2572,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.96" +version = "0.9.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" +checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" dependencies = [ "cc", "libc", @@ -2520,12 +2611,12 @@ dependencies = [ [[package]] name = "os_pipe" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" +checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2589,7 +2680,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", "windows-targets 0.48.5", ] @@ -2606,6 +2697,16 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap 2.2.5", +] + [[package]] name = "phf" version = "0.8.0" @@ -2710,7 +2811,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -2789,9 +2890,9 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" @@ -2799,8 +2900,8 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ - "base64 0.21.5", - "indexmap 2.1.0", + "base64 0.21.7", + "indexmap 2.2.5", "line-wrap", "quick-xml 0.31.0", "serde", @@ -2809,9 +2910,9 @@ dependencies = [ [[package]] name = "png" -version = "0.17.10" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -2838,14 +2939,14 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.1" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf63fa624ab313c11656b4cda960bfc46c410187ad493c41f6ba2d8c1e991c9e" +checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite", - "rustix 0.38.26", + "rustix 0.38.31", "tracing", "windows-sys 0.52.0", ] @@ -2910,9 +3011,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -2937,9 +3038,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -3004,7 +3105,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.12", ] [[package]] @@ -3031,15 +3132,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -3055,7 +3147,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.12", "libredox", "thiserror", ] @@ -3068,7 +3160,7 @@ checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.4", + "regex-automata 0.4.6", "regex-syntax 0.8.2", ] @@ -3083,9 +3175,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -3106,11 +3198,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "0eea5a9eb898d3783f17c6407670e3592fd174cb81a10e51d4c37f49450b9946" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -3128,9 +3220,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -3199,17 +3293,26 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.26" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "libc", - "linux-raw-sys 0.4.12", + "linux-raw-sys 0.4.13", "windows-sys 0.52.0", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -3218,9 +3321,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "safemem" @@ -3239,11 +3342,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3303,60 +3406,61 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ - "itoa 1.0.9", + "indexmap 2.2.5", + "itoa 1.0.10", "ryu", "serde", ] [[package]] name = "serde_repr" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" +checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "serde_spanned" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -3368,23 +3472,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.9", + "itoa 1.0.10", "ryu", "serde", ] [[package]] name = "serde_with" -version = "3.4.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.1.0", + "indexmap 2.2.5", "serde", + "serde_derive", "serde_json", "serde_with_macros", "time", @@ -3392,14 +3497,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.4.0" +version = "3.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -3507,9 +3612,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" @@ -3523,12 +3628,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3640,15 +3745,21 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sys-locale" version = "0.2.4" @@ -3664,20 +3775,20 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", @@ -3702,25 +3813,25 @@ version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" dependencies = [ - "cfg-expr 0.15.5", + "cfg-expr 0.15.7", "heck 0.4.1", "pkg-config", - "toml 0.8.8", + "toml 0.8.11", "version-compare 0.1.1", ] [[package]] name = "tao" -version = "0.16.5" +version = "0.16.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f5aefd6be4cd3ad3f047442242fd9f57cbfb3e565379f66b5e14749364fa4f" +checksum = "d22205b267a679ca1c590b9f178488d50981fc3e48a1b91641ae31593db875ce" dependencies = [ "bitflags 1.3.2", "cairo-rs", "cc", "cocoa", "core-foundation", - "core-graphics", + "core-graphics 0.22.3", "crossbeam-channel", "dispatch", "gdk", @@ -3780,22 +3891,23 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.12" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" +checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.5.4" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd27c04b9543776a972c86ccf70660b517ecabbeced9fb58d8b961a13ad129af" +checksum = "f078117725e36d55d29fafcbb4b1e909073807ca328ae8deb8c0b3843aac0fed" dependencies = [ "anyhow", - "base64 0.21.5", + "base64 0.21.7", "bytes", "clap", "cocoa", "dirs-next", + "dunce", "embed_plist", "encoding_rs", "flate2", @@ -3806,7 +3918,9 @@ dependencies = [ "heck 0.4.1", "http", "ignore", + "indexmap 1.9.3", "minisign-verify", + "nix 0.26.4", "notify-rust", "objc", "once_cell", @@ -3869,7 +3983,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1554c5857f65dbc377cefb6b97c8ac77b1cb2a90d30d3448114d5d6b48a77fc" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "brotli", "ico", "json-patch", @@ -3922,7 +4036,7 @@ dependencies = [ [[package]] name = "tauri-plugin-fs-extra" version = "0.0.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#cf0090029888efc6a1f4d178cec773e6cd4c5b69" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#adbc333a0f233334a97cbabef266bf3fa6037d17" dependencies = [ "log", "serde", @@ -3934,7 +4048,7 @@ dependencies = [ [[package]] name = "tauri-plugin-single-instance" version = "0.0.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#cf0090029888efc6a1f4d178cec773e6cd4c5b69" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#adbc333a0f233334a97cbabef266bf3fa6037d17" dependencies = [ "log", "serde", @@ -3948,10 +4062,10 @@ dependencies = [ [[package]] name = "tauri-plugin-window-state" version = "0.1.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#cf0090029888efc6a1f4d178cec773e6cd4c5b69" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#adbc333a0f233334a97cbabef266bf3fa6037d17" dependencies = [ "bincode", - "bitflags 2.4.1", + "bitflags 2.4.2", "log", "serde", "serde_json", @@ -3982,9 +4096,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cae61fbc731f690a4899681c9052dde6d05b159b44563ace8186fc1bfb7d158" +checksum = "067c56fc153b3caf406d7cd6de4486c80d1d66c0f414f39e94cb2f5543f6445f" dependencies = [ "arboard", "cocoa", @@ -4003,16 +4117,16 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece74810b1d3d44f29f732a7ae09a63183d63949bbdd59c61f8ed2a1b70150db" +checksum = "75ad0bbb31fccd1f4c56275d0a5c3abdf1f59999f72cb4ef8b79b4ed42082a21" dependencies = [ "brotli", "ctor", "dunce", "glob", "heck 0.4.1", - "html5ever 0.26.0", + "html5ever", "infer", "json-patch", "kuchikiki", @@ -4053,15 +4167,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall 0.4.1", - "rustix 0.38.26", - "windows-sys 0.48.0", + "rustix 0.38.31", + "windows-sys 0.52.0", ] [[package]] @@ -4077,18 +4190,18 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thin-slice" @@ -4098,29 +4211,29 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -4128,9 +4241,9 @@ dependencies = [ [[package]] name = "tiff" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" dependencies = [ "flate2", "jpeg-decoder", @@ -4139,12 +4252,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", - "itoa 1.0.9", + "itoa 1.0.10", + "num-conv", "powerfmt", "serde", "time-core", @@ -4159,10 +4273,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -4189,9 +4304,9 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" [[package]] name = "tokio" -version = "1.34.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -4199,7 +4314,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.5", + "socket2 0.5.6", "windows-sys 0.48.0", ] @@ -4250,14 +4365,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit 0.22.7", ] [[package]] @@ -4275,24 +4390,24 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.5", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.5", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.5", ] [[package]] @@ -4320,7 +4435,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", ] [[package]] @@ -4362,20 +4477,34 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "tree_magic_mini" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91adfd0607cacf6e4babdb870e9bec4037c1c4b151cfd279ccefc5e0c7feaa6d" +dependencies = [ + "bytecount", + "fnv", + "lazy_static", + "nom", + "once_cell", + "petgraph", +] + [[package]] name = "treediff" -version = "4.0.2" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52984d277bdf2a751072b5df30ec0377febdb02f7696d64c2d7d54630bac4303" +checksum = "4d127780145176e2b5d16611cc25a900150e86e9fd79d3bde6ff3a37359c9cb5" dependencies = [ "serde_json", ] [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" @@ -4385,19 +4514,20 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "uds_windows" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ + "memoffset 0.9.0", "tempfile", "winapi", ] [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -4407,18 +4537,18 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "url" @@ -4452,11 +4582,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.12", ] [[package]] @@ -4537,9 +4667,9 @@ checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -4568,9 +4698,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4578,24 +4708,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -4605,9 +4735,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4615,28 +4745,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-streams" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" dependencies = [ "futures-util", "js-sys", @@ -4645,11 +4775,84 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wayland-backend" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40" +dependencies = [ + "cc", + "downcast-rs", + "rustix 0.38.31", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" +dependencies = [ + "bitflags 2.4.2", + "rustix 0.38.31", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +dependencies = [ + "bitflags 2.4.2", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +dependencies = [ + "bitflags 2.4.2", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283" +dependencies = [ + "proc-macro2", + "quick-xml 0.31.0", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -4742,9 +4945,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "winapi" @@ -4771,15 +4974,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -4828,7 +5022,7 @@ version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" dependencies = [ - "windows-core", + "windows-core 0.51.1", "windows-targets 0.48.5", ] @@ -4851,6 +5045,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.4", +] + [[package]] name = "windows-implement" version = "0.39.0" @@ -4906,7 +5109,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -4941,17 +5144,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] @@ -4966,7 +5169,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75aa004c988e080ad34aff5739c39d0312f4684699d6d71fc8a198d057b8b9b4" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", ] [[package]] @@ -4983,9 +5186,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -5013,9 +5216,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -5043,9 +5246,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -5073,9 +5276,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -5103,9 +5306,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -5121,9 +5324,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -5151,15 +5354,24 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] [[package]] name = "winnow" -version = "0.5.19" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" dependencies = [ "memchr", ] @@ -5176,33 +5388,53 @@ dependencies = [ [[package]] name = "winreg" -version = "0.51.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ "cfg-if", "windows-sys 0.48.0", ] +[[package]] +name = "wl-clipboard-rs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b41773911497b18ca8553c3daaf8ec9fe9819caf93d451d3055f69de028adb" +dependencies = [ + "derive-new", + "libc", + "log", + "nix 0.28.0", + "os_pipe", + "tempfile", + "thiserror", + "tree_magic_mini", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-wlr", +] + [[package]] name = "wry" -version = "0.24.6" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a70547e8f9d85da0f5af609143f7bde3ac7457a6e1073104d9b73d6c5ac744" +checksum = "6ad85d0e067359e409fcb88903c3eac817c392e5d638258abfb3da5ad8ba6fc4" dependencies = [ "base64 0.13.1", "block", "cocoa", - "core-graphics", + "core-graphics 0.22.3", "crossbeam-channel", "dunce", "gdk", "gio", "glib", "gtk", - "html5ever 0.25.2", + "html5ever", "http", - "kuchiki", + "kuchikiki", "libc", "log", "objc", @@ -5245,50 +5477,47 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" +checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" dependencies = [ "gethostname", - "nix", - "winapi", - "winapi-wsapoll", + "rustix 0.38.31", "x11rb-protocol", ] [[package]] name = "x11rb-protocol" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" -dependencies = [ - "nix", -] +checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" [[package]] name = "xattr" -version = "1.0.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" +checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", + "linux-raw-sys 0.4.13", + "rustix 0.38.31", ] [[package]] name = "xdg-home" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" +checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" dependencies = [ - "nix", + "libc", "winapi", ] [[package]] name = "zbus" -version = "3.14.1" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948" +checksum = "675d170b632a6ad49804c8cf2105d7c31eddd3312555cffd4b740e08e97c25e6" dependencies = [ "async-broadcast", "async-executor", @@ -5308,7 +5537,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix", + "nix 0.26.4", "once_cell", "ordered-stream", "rand 0.8.5", @@ -5327,9 +5556,9 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "3.14.1" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" +checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -5341,9 +5570,9 @@ dependencies = [ [[package]] name = "zbus_names" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9" +checksum = "437d738d3750bed6ca9b8d423ccc7a8eb284f6b1d6d4e225a0e4e6258d864c8d" dependencies = [ "serde", "static_assertions", @@ -5363,9 +5592,9 @@ dependencies = [ [[package]] name = "zvariant" -version = "3.15.0" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c" +checksum = "4eef2be88ba09b358d3b58aca6e41cd853631d44787f319a1383ca83424fb2db" dependencies = [ "byteorder", "enumflags2", @@ -5377,9 +5606,9 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "3.15.0" +version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd" +checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" dependencies = [ "proc-macro-crate", "proc-macro2", From d0f087c2504f9378073f91c613dcc025ec6d5beb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:58:04 +0000 Subject: [PATCH 420/864] chore(deps): update tauri monorepo --- package-lock.json | 178 +++++++++++++++++++++---------------------- package.json | 2 +- src-tauri/Cargo.toml | 2 +- 3 files changed, 91 insertions(+), 91 deletions(-) diff --git a/package-lock.json b/package-lock.json index 60dcbb9a..2146ace8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "phoenix-code-ide", - "version": "3.3.6", + "version": "3.4.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.3.6", + "version": "3.4.6", "hasInstallScript": true, "devDependencies": { - "@tauri-apps/cli": "1.5.9", + "@tauri-apps/cli": "1.5.11", "adm-zip": "0.5.10", "axios": "1.6.7", "axios-retry": "4.0.0", @@ -22,9 +22,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.9.tgz", - "integrity": "sha512-knSt/9AvCTeyfC6wkyeouF9hBW/0Mzuw+5vBKEvzaGPQsfFJo1ZCp5FkdiZpGBBfnm09BhugasGRTGofzatfqQ==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.11.tgz", + "integrity": "sha512-B475D7phZrq5sZ3kDABH4g2mEoUIHtnIO+r4ZGAAfsjMbZCwXxR/jlMGTEL+VO3YzjpF7gQe38IzB4vLBbVppw==", "dev": true, "bin": { "tauri": "tauri.js" @@ -37,22 +37,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.5.9", - "@tauri-apps/cli-darwin-x64": "1.5.9", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.9", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.9", - "@tauri-apps/cli-linux-arm64-musl": "1.5.9", - "@tauri-apps/cli-linux-x64-gnu": "1.5.9", - "@tauri-apps/cli-linux-x64-musl": "1.5.9", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.9", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.9", - "@tauri-apps/cli-win32-x64-msvc": "1.5.9" + "@tauri-apps/cli-darwin-arm64": "1.5.11", + "@tauri-apps/cli-darwin-x64": "1.5.11", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.11", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.11", + "@tauri-apps/cli-linux-arm64-musl": "1.5.11", + "@tauri-apps/cli-linux-x64-gnu": "1.5.11", + "@tauri-apps/cli-linux-x64-musl": "1.5.11", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.11", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.11", + "@tauri-apps/cli-win32-x64-msvc": "1.5.11" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.9.tgz", - "integrity": "sha512-7C2Jf8f0gzv778mLYb7Eszqqv1bm9Wzews81MRTqKrUIcC+eZEtDXLex+JaEkEzFEUrgIafdOvMBVEavF030IA==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.11.tgz", + "integrity": "sha512-2NLSglDb5VfvTbMtmOKWyD+oaL/e8Z/ZZGovHtUFyUSFRabdXc6cZOlcD1BhFvYkHqm+TqGaz5qtPR5UbqDs8A==", "cpu": [ "arm64" ], @@ -66,9 +66,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.9.tgz", - "integrity": "sha512-LHKytpkofPYgH8RShWvwDa3hD1ws131x7g7zNasJPfOiCWLqYVQFUuQVmjEUt8+dpHe/P/err5h4z+YZru2d0A==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.11.tgz", + "integrity": "sha512-/RQllHiJRH2fJOCudtZlaUIjofkHzP3zZgxi71ZUm7Fy80smU5TDfwpwOvB0wSVh0g/ciDjMArCSTo0MRvL+ag==", "cpu": [ "x64" ], @@ -82,9 +82,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.9.tgz", - "integrity": "sha512-teGK20IYKx+dVn8wFq/Lg57Q9ce7foq1KHSfyHi464LVt1T0V1rsmULSgZpQPPj/NYPF5BG78PcWYv64yH86jw==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.11.tgz", + "integrity": "sha512-IlBuBPKmMm+a5LLUEK6a21UGr9ZYd6zKuKLq6IGM4tVweQa8Sf2kP2Nqs74dMGIUrLmMs0vuqdURpykQg+z4NQ==", "cpu": [ "arm" ], @@ -98,9 +98,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.9.tgz", - "integrity": "sha512-onJ/DW5Crw38qVx+wquY4uBbfCxVhzhdJmlCYqnYyXsZZmSiPUfSyhV58y+5TYB0q1hG8eYdB5x8VAwzByhGzw==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.11.tgz", + "integrity": "sha512-w+k1bNHCU/GbmXshtAhyTwqosThUDmCEFLU4Zkin1vl2fuAtQry2RN7thfcJFepblUGL/J7yh3Q/0+BCjtspKQ==", "cpu": [ "arm64" ], @@ -114,9 +114,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.9.tgz", - "integrity": "sha512-23AYoLD3acakLp9NtheKQDJl8F66eTOflxoPzdJNRy13hUSxb+W9qpz4rRA+CIzkjICFvO2i3UWjeV9QwDVpsQ==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.11.tgz", + "integrity": "sha512-PN6/dl+OfYQ/qrAy4HRAfksJ2AyWQYn2IA/2Wwpaa7SDRz2+hzwTQkvajuvy0sQ5L2WCG7ymFYRYMbpC6Hk9Pg==", "cpu": [ "arm64" ], @@ -130,9 +130,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.9.tgz", - "integrity": "sha512-9PQA1rE7gh41W2ylyKd5qOGOds55ymaYPml9KOpM0g+cxmCXa+8Wf9K5NKvACnJldJJ6cekWzIyB4eN6o5T+yQ==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.11.tgz", + "integrity": "sha512-MTVXLi89Nj7Apcvjezw92m7ZqIDKT5SFKZtVPCg6RoLUBTzko/BQoXYIRWmdoz2pgkHDUHgO2OMJ8oKzzddXbw==", "cpu": [ "x64" ], @@ -146,9 +146,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.9.tgz", - "integrity": "sha512-5hdbNFeDsrJ/pXZ4cSQV4bJwUXPPxXxN3/pAtNUqIph7q+vLcBXOXIMoS64iuyaluJC59lhEwlWZFz+EPv0Hqg==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.11.tgz", + "integrity": "sha512-kwzAjqFpz7rvTs7WGZLy/a5nS5t15QKr3E9FG95MNF0exTl3d29YoAUAe1Mn0mOSrTJ9Z+vYYAcI/QdcsGBP+w==", "cpu": [ "x64" ], @@ -162,9 +162,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.9.tgz", - "integrity": "sha512-O18JufjSB3hSJYu5WWByONouGeX7DraLAtXLErsG1r/VS3zHd/zyuzycrVUaObNXk5bfGlIP0Ypt+RvZJILN2w==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.11.tgz", + "integrity": "sha512-L+5NZ/rHrSUrMxjj6YpFYCXp6wHnq8c8SfDTBOX8dO8x+5283/vftb4vvuGIsLS4UwUFXFnLt3XQr44n84E67Q==", "cpu": [ "arm64" ], @@ -178,9 +178,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.9.tgz", - "integrity": "sha512-FQxtxTZu0JVBihfd/lmpxo7jyMOesjWQehfyVUqtgMfm5+Pvvw0Y+ZioeDi1TZkFVrT3QDYy8R4LqDLSZVMQRA==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.11.tgz", + "integrity": "sha512-oVlD9IVewrY0lZzTdb71kNXkjdgMqFq+ohb67YsJb4Rf7o8A9DTlFds1XLCe3joqLMm4M+gvBKD7YnGIdxQ9vA==", "cpu": [ "ia32" ], @@ -194,9 +194,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.9.tgz", - "integrity": "sha512-EeI1+L518cIBLKw0qUFwnLIySBeSmPQjPLIlNwSukHSro4tAQPHycEVGgKrdToiCWgaZJBA0e5aRSds0Du2TWg==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.11.tgz", + "integrity": "sha512-1CexcqUFCis5ypUIMOKllxUBrna09McbftWENgvVXMfA+SP+yPDPAVb8fIvUcdTIwR/yHJwcIucmTB4anww4vg==", "cpu": [ "x64" ], @@ -1399,90 +1399,90 @@ }, "dependencies": { "@tauri-apps/cli": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.9.tgz", - "integrity": "sha512-knSt/9AvCTeyfC6wkyeouF9hBW/0Mzuw+5vBKEvzaGPQsfFJo1ZCp5FkdiZpGBBfnm09BhugasGRTGofzatfqQ==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.11.tgz", + "integrity": "sha512-B475D7phZrq5sZ3kDABH4g2mEoUIHtnIO+r4ZGAAfsjMbZCwXxR/jlMGTEL+VO3YzjpF7gQe38IzB4vLBbVppw==", "dev": true, "requires": { - "@tauri-apps/cli-darwin-arm64": "1.5.9", - "@tauri-apps/cli-darwin-x64": "1.5.9", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.9", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.9", - "@tauri-apps/cli-linux-arm64-musl": "1.5.9", - "@tauri-apps/cli-linux-x64-gnu": "1.5.9", - "@tauri-apps/cli-linux-x64-musl": "1.5.9", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.9", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.9", - "@tauri-apps/cli-win32-x64-msvc": "1.5.9" + "@tauri-apps/cli-darwin-arm64": "1.5.11", + "@tauri-apps/cli-darwin-x64": "1.5.11", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.11", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.11", + "@tauri-apps/cli-linux-arm64-musl": "1.5.11", + "@tauri-apps/cli-linux-x64-gnu": "1.5.11", + "@tauri-apps/cli-linux-x64-musl": "1.5.11", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.11", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.11", + "@tauri-apps/cli-win32-x64-msvc": "1.5.11" } }, "@tauri-apps/cli-darwin-arm64": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.9.tgz", - "integrity": "sha512-7C2Jf8f0gzv778mLYb7Eszqqv1bm9Wzews81MRTqKrUIcC+eZEtDXLex+JaEkEzFEUrgIafdOvMBVEavF030IA==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.11.tgz", + "integrity": "sha512-2NLSglDb5VfvTbMtmOKWyD+oaL/e8Z/ZZGovHtUFyUSFRabdXc6cZOlcD1BhFvYkHqm+TqGaz5qtPR5UbqDs8A==", "dev": true, "optional": true }, "@tauri-apps/cli-darwin-x64": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.9.tgz", - "integrity": "sha512-LHKytpkofPYgH8RShWvwDa3hD1ws131x7g7zNasJPfOiCWLqYVQFUuQVmjEUt8+dpHe/P/err5h4z+YZru2d0A==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.11.tgz", + "integrity": "sha512-/RQllHiJRH2fJOCudtZlaUIjofkHzP3zZgxi71ZUm7Fy80smU5TDfwpwOvB0wSVh0g/ciDjMArCSTo0MRvL+ag==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.9.tgz", - "integrity": "sha512-teGK20IYKx+dVn8wFq/Lg57Q9ce7foq1KHSfyHi464LVt1T0V1rsmULSgZpQPPj/NYPF5BG78PcWYv64yH86jw==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.11.tgz", + "integrity": "sha512-IlBuBPKmMm+a5LLUEK6a21UGr9ZYd6zKuKLq6IGM4tVweQa8Sf2kP2Nqs74dMGIUrLmMs0vuqdURpykQg+z4NQ==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.9.tgz", - "integrity": "sha512-onJ/DW5Crw38qVx+wquY4uBbfCxVhzhdJmlCYqnYyXsZZmSiPUfSyhV58y+5TYB0q1hG8eYdB5x8VAwzByhGzw==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.11.tgz", + "integrity": "sha512-w+k1bNHCU/GbmXshtAhyTwqosThUDmCEFLU4Zkin1vl2fuAtQry2RN7thfcJFepblUGL/J7yh3Q/0+BCjtspKQ==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.9.tgz", - "integrity": "sha512-23AYoLD3acakLp9NtheKQDJl8F66eTOflxoPzdJNRy13hUSxb+W9qpz4rRA+CIzkjICFvO2i3UWjeV9QwDVpsQ==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.11.tgz", + "integrity": "sha512-PN6/dl+OfYQ/qrAy4HRAfksJ2AyWQYn2IA/2Wwpaa7SDRz2+hzwTQkvajuvy0sQ5L2WCG7ymFYRYMbpC6Hk9Pg==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.9.tgz", - "integrity": "sha512-9PQA1rE7gh41W2ylyKd5qOGOds55ymaYPml9KOpM0g+cxmCXa+8Wf9K5NKvACnJldJJ6cekWzIyB4eN6o5T+yQ==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.11.tgz", + "integrity": "sha512-MTVXLi89Nj7Apcvjezw92m7ZqIDKT5SFKZtVPCg6RoLUBTzko/BQoXYIRWmdoz2pgkHDUHgO2OMJ8oKzzddXbw==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.9.tgz", - "integrity": "sha512-5hdbNFeDsrJ/pXZ4cSQV4bJwUXPPxXxN3/pAtNUqIph7q+vLcBXOXIMoS64iuyaluJC59lhEwlWZFz+EPv0Hqg==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.11.tgz", + "integrity": "sha512-kwzAjqFpz7rvTs7WGZLy/a5nS5t15QKr3E9FG95MNF0exTl3d29YoAUAe1Mn0mOSrTJ9Z+vYYAcI/QdcsGBP+w==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.9.tgz", - "integrity": "sha512-O18JufjSB3hSJYu5WWByONouGeX7DraLAtXLErsG1r/VS3zHd/zyuzycrVUaObNXk5bfGlIP0Ypt+RvZJILN2w==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.11.tgz", + "integrity": "sha512-L+5NZ/rHrSUrMxjj6YpFYCXp6wHnq8c8SfDTBOX8dO8x+5283/vftb4vvuGIsLS4UwUFXFnLt3XQr44n84E67Q==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.9.tgz", - "integrity": "sha512-FQxtxTZu0JVBihfd/lmpxo7jyMOesjWQehfyVUqtgMfm5+Pvvw0Y+ZioeDi1TZkFVrT3QDYy8R4LqDLSZVMQRA==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.11.tgz", + "integrity": "sha512-oVlD9IVewrY0lZzTdb71kNXkjdgMqFq+ohb67YsJb4Rf7o8A9DTlFds1XLCe3joqLMm4M+gvBKD7YnGIdxQ9vA==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.9", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.9.tgz", - "integrity": "sha512-EeI1+L518cIBLKw0qUFwnLIySBeSmPQjPLIlNwSukHSro4tAQPHycEVGgKrdToiCWgaZJBA0e5aRSds0Du2TWg==", + "version": "1.5.11", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.11.tgz", + "integrity": "sha512-1CexcqUFCis5ypUIMOKllxUBrna09McbftWENgvVXMfA+SP+yPDPAVb8fIvUcdTIwR/yHJwcIucmTB4anww4vg==", "dev": true, "optional": true }, diff --git a/package.json b/package.json index 25c8cdde..3388545a 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { - "@tauri-apps/cli": "1.5.9", + "@tauri-apps/cli": "1.5.11", "adm-zip": "0.5.10", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9292a986..1b28954d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -20,7 +20,7 @@ percent-encoding = "2.3" regex = "1.10.3" clipboard-files = "0.1.1" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.5.4", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } +tauri = { version = "1.6.1", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From 95931559ae7e58a141e419c3428559c418f6e29a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:52:25 +0000 Subject: [PATCH 421/864] chore(deps): update softprops/action-gh-release action to v2 --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 6e35d493..be8c5b57 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -310,7 +310,7 @@ jobs: echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV ls - name: Upload Release Asset - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: files: ${{ env.OUTPUT_FILENAME }} tag_name: ${{ env.GIT_TAG_NAME }} diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 654eac14..0350ca74 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -312,7 +312,7 @@ jobs: echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV ls - name: Upload Release Asset - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: files: ${{ env.OUTPUT_FILENAME }} tag_name: ${{ env.GIT_TAG_NAME }} diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 2cd5dc4e..d85b7fd7 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -307,7 +307,7 @@ jobs: echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV ls - name: Upload Release Asset - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 with: files: ${{ env.OUTPUT_FILENAME }} tag_name: ${{ env.GIT_TAG_NAME }} From 5d8eb436edaa862e69ddd8c1067fe78cc8bc8c41 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 07:18:05 +0000 Subject: [PATCH 422/864] chore(deps): update dependency adm-zip to v0.5.12 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2146ace8..9440ceb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.11", - "adm-zip": "0.5.10", + "adm-zip": "0.5.12", "axios": "1.6.7", "axios-retry": "4.0.0", "chalk": "^5.3.0", @@ -210,9 +210,9 @@ } }, "node_modules/adm-zip": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", - "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.12.tgz", + "integrity": "sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==", "dev": true, "engines": { "node": ">=6.0" @@ -1487,9 +1487,9 @@ "optional": true }, "adm-zip": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz", - "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==", + "version": "0.5.12", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.12.tgz", + "integrity": "sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==", "dev": true }, "ansi-regex": { diff --git a/package.json b/package.json index 3388545a..7e38af38 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ }, "devDependencies": { "@tauri-apps/cli": "1.5.11", - "adm-zip": "0.5.10", + "adm-zip": "0.5.12", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", From 6fffeb4953c6761eb25f5071eb65eaa984534385 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 16 Mar 2024 22:32:33 +0000 Subject: [PATCH 423/864] build(deps-dev): bump follow-redirects from 1.15.4 to 1.15.6 Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6. - [Release notes](https://github.com/follow-redirects/follow-redirects/releases) - [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.4...v1.15.6) --- updated-dependencies: - dependency-name: follow-redirects dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9440ceb8..0662beb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -523,9 +523,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -1726,9 +1726,9 @@ } }, "follow-redirects": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz", - "integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true }, "form-data": { From e989983b686681336d9bedb7e3e9b44e2b7e0ea9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 19:43:30 +0000 Subject: [PATCH 424/864] chore(deps): update dependency axios to v1.6.8 --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0662beb4..73fee4fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.5.11", "adm-zip": "0.5.12", - "axios": "1.6.7", + "axios": "1.6.8", "axios-retry": "4.0.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -259,12 +259,12 @@ "dev": true }, "node_modules/axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -1524,12 +1524,12 @@ "dev": true }, "axios": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", - "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dev": true, "requires": { - "follow-redirects": "^1.15.4", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } diff --git a/package.json b/package.json index 7e38af38..257b4892 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.0", - "axios": "1.6.7", + "axios": "1.6.8", "axios-retry": "4.0.0" }, "phoenixRepo": { From 351289e67abad4f76c217d96a0e86a42929c3da6 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 18 Mar 2024 15:11:49 +0000 Subject: [PATCH 425/864] ci: update phcode version to 3.4.8 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 257b4892..f3e53383 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.4.6", + "version": "3.4.8", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "0c5ca39380f0c7ee74d524006007040b28cf5bcf" + "commit": "1cc7bb17d2542d660c1057b9c3d7192a86c793b2" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1b28954d..57f4df3f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.4.6" +version = "3.4.8" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index aa7b3e69..a99a31e0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.4.6" + "version": "3.4.8" }, "tauri": { "allowlist": { From 4c44196ca5906baa6355969e95862219cc1abb59 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 21 Mar 2024 19:13:00 +0530 Subject: [PATCH 426/864] feat: add untar-unix command --- src-tauri/tauri.conf.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a99a31e0..b5f53015 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -106,6 +106,24 @@ } ] }, + { + "name": "untar-unix", + "cmd": "tar", + "args": [ + { + "validator": "\\S*" + }, + { + "validator": "\\S*" + }, + { + "validator": "\\S*" + }, + { + "validator": "\\S*" + } + ] + }, { "name": "recursive-rm-unix", "cmd": "rm", From 80215a3a864bd5a06fedf008dc41fe89a17df4b0 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 21 Mar 2024 19:19:17 +0530 Subject: [PATCH 427/864] refactor: rename untar-unix command as tar-unix --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index b5f53015..3a7df5fe 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -107,7 +107,7 @@ ] }, { - "name": "untar-unix", + "name": "tar-unix", "cmd": "tar", "args": [ { From 6b3c2e5e413c65cd664167e0e508f116ee75b6d4 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 22 Mar 2024 11:15:51 +0530 Subject: [PATCH 428/864] feat: add mac-remove-quarantine command --- src-tauri/Cargo.lock | 2 +- src-tauri/tauri.conf.json | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f1192ae1..b913bad5 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2843,7 +2843,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.4.6" +version = "3.4.8" dependencies = [ "clipboard-files", "fix-path-env", diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 3a7df5fe..da3f588f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -106,6 +106,17 @@ } ] }, + { + "name": "mac-remove-quarantine", + "cmd": "xattr", + "args": [ + "-rd", + "com.apple.quarantine", + { + "validator": "\\S*" + } + ] + }, { "name": "tar-unix", "cmd": "tar", From 4e2f51a44caab1df7e41c71d5cb70c198a9739be Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 21 Mar 2024 22:10:19 +0000 Subject: [PATCH 429/864] chore(deps): update dependency tar to v6.2.1 --- package-lock.json | 18 +++++++++--------- package.json | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 73fee4fb..2732730c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.4.6", + "version": "3.4.8", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.4.6", + "version": "3.4.8", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.11", @@ -18,7 +18,7 @@ "execa": "^8.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "6.2.0" + "tar": "6.2.1" } }, "node_modules/@tauri-apps/cli": { @@ -1278,9 +1278,9 @@ } }, "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "dependencies": { "chownr": "^2.0.0", @@ -2254,9 +2254,9 @@ "dev": true }, "tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "requires": { "chownr": "^2.0.0", diff --git a/package.json b/package.json index f3e53383..fb07185d 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "execa": "^8.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "6.2.0", + "tar": "6.2.1", "axios": "1.6.8", "axios-retry": "4.0.0" }, From e04bd88ee7c2270f7047738280897aa013421fc4 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 22 Mar 2024 16:19:48 +0530 Subject: [PATCH 430/864] feat: new mac icons for apple design spec --- src-build/ci-createDistReleaseConfig.js | 10 ++++++++++ src-build/ci-disableBundleConfig.js | 11 +++++++++++ src-build/createDistBundleReleaseConfig.js | 10 ++++++++++ src-build/createDistReleaseConfig.js | 10 ++++++++++ src-build/createDistTestReleaseConfig.js | 10 ++++++++++ src-build/createSrcReleaseConfig.js | 10 ++++++++++ src-tauri/icons-mac/128x128.png | Bin 0 -> 7989 bytes src-tauri/icons-mac/128x128@2x.png | Bin 0 -> 21030 bytes src-tauri/icons-mac/16x16.png | Bin 0 -> 634 bytes src-tauri/icons-mac/16x16@2x.png | Bin 0 -> 1337 bytes src-tauri/icons-mac/256x256.png | Bin 0 -> 21030 bytes src-tauri/icons-mac/256x256@2x.png | Bin 0 -> 54467 bytes src-tauri/icons-mac/32x32.png | Bin 0 -> 1337 bytes src-tauri/icons-mac/32x32@2x.png | Bin 0 -> 3254 bytes src-tauri/icons-mac/512x512.png | Bin 0 -> 54467 bytes src-tauri/icons-mac/512x512@2x.png | Bin 0 -> 138135 bytes src-tauri/icons-mac/icon.icns | Bin 0 -> 390922 bytes src-tauri/icons-mac/icon.ico | Bin 0 -> 4286 bytes 18 files changed, 61 insertions(+) create mode 100644 src-tauri/icons-mac/128x128.png create mode 100644 src-tauri/icons-mac/128x128@2x.png create mode 100644 src-tauri/icons-mac/16x16.png create mode 100644 src-tauri/icons-mac/16x16@2x.png create mode 100644 src-tauri/icons-mac/256x256.png create mode 100644 src-tauri/icons-mac/256x256@2x.png create mode 100644 src-tauri/icons-mac/32x32.png create mode 100644 src-tauri/icons-mac/32x32@2x.png create mode 100644 src-tauri/icons-mac/512x512.png create mode 100644 src-tauri/icons-mac/512x512@2x.png create mode 100644 src-tauri/icons-mac/icon.icns create mode 100644 src-tauri/icons-mac/icon.ico diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index 59821a08..d5fbc9cd 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -92,6 +92,16 @@ async function ciCreateDistReleaseConfig() { } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } + if(os.platform() === 'darwin'){ + // inject macos icons + configJson.tauri.bundle.icon = [ + "icons-mac/32x32.png", + "icons-mac/128x128.png", + "icons-mac/128x128@2x.png", + "icons-mac/icon.icns", + "icons-mac/icon.ico" + ]; + } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); configJson.tauri.updater.endpoints = [ `${UPDATE_NOTIFICATIONS_BASE_URL}${UPDATE_NOTIFICATION_LATEST_JSON_FILE_PATH[phoenixStage]}` diff --git a/src-build/ci-disableBundleConfig.js b/src-build/ci-disableBundleConfig.js index dce1fe53..84350a4b 100644 --- a/src-build/ci-disableBundleConfig.js +++ b/src-build/ci-disableBundleConfig.js @@ -1,6 +1,7 @@ import {dirname, join} from "path"; import fs from "fs"; import {fileURLToPath} from "url"; +import os from "os"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -11,6 +12,16 @@ async function ciCreateDistReleaseConfig() { const configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); configJson.tauri.bundle.active = false; configJson.tauri.updater.active = false; + if(os.platform() === 'darwin'){ + // inject macos icons + configJson.tauri.bundle.icon = [ + "icons-mac/32x32.png", + "icons-mac/128x128.png", + "icons-mac/128x128@2x.png", + "icons-mac/icon.icns", + "icons-mac/icon.ico" + ]; + } console.log("Product name is: ", configJson.package.productName); fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); } diff --git a/src-build/createDistBundleReleaseConfig.js b/src-build/createDistBundleReleaseConfig.js index c88572b3..81ff86e8 100644 --- a/src-build/createDistBundleReleaseConfig.js +++ b/src-build/createDistBundleReleaseConfig.js @@ -27,6 +27,16 @@ async function createDistReleaseConfig() { } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } + if(os.platform() === 'darwin'){ + // inject macos icons + configJson.tauri.bundle.icon = [ + "icons-mac/32x32.png", + "icons-mac/128x128.png", + "icons-mac/128x128@2x.png", + "icons-mac/icon.icns", + "icons-mac/icon.ico" + ]; + } patchTauriConfigWithMetricsHTML(configJson); console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index 5942311b..f94e66c4 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -26,6 +26,16 @@ async function createDistReleaseConfig() { } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } + if(os.platform() === 'darwin'){ + // inject macos icons + configJson.tauri.bundle.icon = [ + "icons-mac/32x32.png", + "icons-mac/128x128.png", + "icons-mac/128x128@2x.png", + "icons-mac/icon.icns", + "icons-mac/icon.ico" + ]; + } patchTauriConfigWithMetricsHTML(configJson); console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index c26042b6..3693998b 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -28,6 +28,16 @@ async function createDistTestReleaseConfig() { } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } + if(os.platform() === 'darwin'){ + // inject macos icons + configJson.tauri.bundle.icon = [ + "icons-mac/32x32.png", + "icons-mac/128x128.png", + "icons-mac/128x128@2x.png", + "icons-mac/icon.icns", + "icons-mac/icon.ico" + ]; + } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index 582fb3da..64c4b7c7 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -26,6 +26,16 @@ async function createSrcReleaseConfig() { } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; } + if(os.platform() === 'darwin'){ + // inject macos icons + configJson.tauri.bundle.icon = [ + "icons-mac/32x32.png", + "icons-mac/128x128.png", + "icons-mac/128x128@2x.png", + "icons-mac/icon.icns", + "icons-mac/icon.ico" + ]; + } console.log("Window Boot url is: ", configJson.tauri.windows[0].url); console.log("Writing new local config json ", tauriLocalConfigPath); fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); diff --git a/src-tauri/icons-mac/128x128.png b/src-tauri/icons-mac/128x128.png new file mode 100644 index 0000000000000000000000000000000000000000..2f36433cf44dda0b54cb24e9b4bcf415a4d00bc7 GIT binary patch literal 7989 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 literal 0 HcmV?d00001 diff --git a/src-tauri/icons-mac/128x128@2x.png b/src-tauri/icons-mac/128x128@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..66c2541b4eba397e9295956dc949bcbe8d743f6c GIT binary patch literal 21030 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 U{{0H4N&o-=07*qoM6N<$f@)AGQUCw| literal 0 HcmV?d00001 diff --git a/src-tauri/icons-mac/16x16@2x.png b/src-tauri/icons-mac/16x16@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0c361e81785b9b97ade2eb895b6aa8415cbef113 GIT binary patch literal 1337 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 literal 0 HcmV?d00001 diff --git a/src-tauri/icons-mac/32x32.png b/src-tauri/icons-mac/32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..0c361e81785b9b97ade2eb895b6aa8415cbef113 GIT binary patch literal 1337 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 literal 0 HcmV?d00001 diff --git a/src-tauri/icons-mac/512x512.png b/src-tauri/icons-mac/512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..0f8d30fd5fd76c7f2a7aec12253299406bfd6ec3 GIT binary patch literal 54467 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 literal 0 HcmV?d00001 diff --git a/src-tauri/icons-mac/512x512@2x.png b/src-tauri/icons-mac/512x512@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..09ea5da0881bf1270bf72dec292f0e64c8f4b8b2 GIT binary patch literal 138135 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 KRU!fQB}n8Ml?_ONDa^ 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

*Qdq%p++f*3 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%0Agr~vp>JT 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Âs7y@T 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

8}9NIxHxGO^l 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 Date: Fri, 22 Mar 2024 12:50:09 +0000 Subject: [PATCH 431/864] ci: update phcode version to 3.5.0 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index fb07185d..ecb5f28f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.4.8", + "version": "3.5.0", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "1cc7bb17d2542d660c1057b9c3d7192a86c793b2" + "commit": "cfb7020b271d30fa0bda77c6874156fdee691ea7" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 57f4df3f..d6c4a7ff 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.4.8" +version = "3.5.0" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index da3f588f..dfb62eee 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.4.8" + "version": "3.5.0" }, "tauri": { "allowlist": { From 7f1e4e31ce7076998e7b88724d717d392478391c Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 23 Mar 2024 03:44:36 +0000 Subject: [PATCH 432/864] ci: update phcode version to 3.5.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index ecb5f28f..9a6c36ce 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.5.0", + "version": "3.5.1", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "cfb7020b271d30fa0bda77c6874156fdee691ea7" + "commit": "7d7704e1de9e3be00f5c18110f4cbf6ca8786423" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d6c4a7ff..3a04d535 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.5.0" +version = "3.5.1" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index dfb62eee..3b376d6c 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.5.0" + "version": "3.5.1" }, "tauri": { "allowlist": { From 9ac6deb68ac3974db829eb5a96d8329be80f08c0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 23 Mar 2024 03:45:59 +0000 Subject: [PATCH 433/864] fix(deps): update rust crate regex to 1.10.4 --- src-tauri/Cargo.lock | 6 +++--- src-tauri/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b913bad5..2d663039 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2843,7 +2843,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.4.8" +version = "3.5.0" dependencies = [ "clipboard-files", "fix-path-env", @@ -3154,9 +3154,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3a04d535..10bdac66 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -17,7 +17,7 @@ tauri-build = { version = "1.5.1", features = [] } serde_json = "1.0" once_cell = "1.19.0" percent-encoding = "2.3" -regex = "1.10.3" +regex = "1.10.4" clipboard-files = "0.1.1" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.6.1", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } From a66e94a0c630bb932b90096c3dd1e01b1eb62f85 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 23 Mar 2024 06:14:06 +0000 Subject: [PATCH 434/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index e3189163..f4c2b67f 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,23 +1,19 @@ { - "version": "3.4.2", - "notes": "## Test Update Pre-release 2\r\nVery updates, much wow!\r\n\r\n![image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/70cba226-cf7c-4879-82b6-679886c6f1df)\r\n\r\n", - "pub_date": "2024-02-23T11:29:55.983Z", + "version": "3.5.1", + "notes": "## New mac update test pre-release\r\nThis is a test release\r\n![image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/29cf6ddf-d0ca-4cc9-9694-9a17d7e65ac7)\r\n", + "pub_date": "2024-03-23T06:00:26.784Z", "platforms": { - "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZ1cG9mRzR2T1JFYTBGZ29NRFJzRnpMY25RbG1XbUVEN01zeDhla1NsczFFeEdsc3ZPZlJ2QmVMQlNCRTFVNTFZaitLMFQ1YmtnUVluOU14MXprWEFJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njg2NTU1CWZpbGU6cGhvZW5peC1jb2RlLWV4cGVyaW1lbnRhbC1idWlsZF8zLjQuMl9hbWQ2NC5BcHBJbWFnZS50YXIuZ3oKb0tjMjhYaVluQndWZVViQXovUzd2SXdvZk9kSm9VRm5OZzErZFVmQWVQLzlQTXg3a2R0SVNZamVaQjlGL096OCs4SlBXMFBpQlVuR0lLb0NEVzIwRHc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/phoenix-code-experimental-build_3.4.2_amd64.AppImage.tar.gz" - }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtabjlDd0xaQnYrZVFhN3F0c3hmQ3hqQnJSa09jMy9jMW9GVFUwZjNoK3JQdFlEamp3aFpNT1R5YWxoWEdKVWdYYzlpRTI1bjQwSFZMTVNrZTRXS0FNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njg2NzE2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjQuMl94NjQtc2V0dXAubnNpcy56aXAKR2lXNUFXbWExajNuaU1DcnIzbmJwOThqeFc2TjBoRm1lU1BhRHJVSFRVdEpmb0VoZkJHeGhJbTFDNkoxaHVoQ2JienB5cFVISjU5TDBRVG5Hd09TQXc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/Phoenix.Code.Experimental.Build_3.4.2_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZWSkZmOGZFcHhZNEc5UkJpMGlmeWp0ZTlVenI5UDlZZWxTV3ZUTm8za0dQU0MvRXJpUHRzbTFpM2p4NlZad20wUnpQclVkV215c0V4cXBNa2UxWmdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMTcxNzQyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjUuMV94NjQtc2V0dXAubnNpcy56aXAKN0FpT3ZPa2Z4SWNWbmxmYlFLZWJib0I1c3VGcElhY3R2NHAvSjkwWEQ2TlRlaCsrL0ViZW12enNTSnBsYkMyOCtCZ3cxcExvd09QR2doY3pVUE1EQnc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.1/Phoenix.Code.Experimental.Build_3.5.1_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm4vNFlZMnd5R3dCT0U5N0lxRG5ra3lTeHJSM29iYXRUTGFpWFArVm1oMDRyemJHY0FMM0lxMlFwdzgzNDlyWWIrWUdmUnRVRmhLdkcxeFB1enVicXdZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njg3MTk0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmxTYTJQOWIvdGI3SlU1MkR6TUo3V3pSWVhGSGJ5SE5nbVhXaFoyN2FpK3BnbllsRnZTR1Zicko0dXFqUGkzcm1oMCtwcVZSWTZLM0k2cEh3T1pBVEJnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmcvK2FXbDdyVFdCSnREMlk2QmhlY2pucUdzRkpmMVdxMFBGb2duNVhPVkFXbXZZUW1VSnZzRWdXZ05sd3lCdE4vRk1oaDFPUG5UU0g4SGxnN0Nla3d3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMTcyNTk4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cnc5Yjc5M2lBVndsS3dYblNwaDdmU1pPOWZ4TXdmQUZKQUNObXBuRm5YTkQxNGt3WlJ2QlhrN3p2K3dhd3JqUUhpVVdFRnhBRlpDQ1l0ZjcxU21MSUNnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhaaENVcno2QTdCZDRDR3drSnlUVWpoMzZvVHljZWRWWllEaWNnTzI5SHBGOHZ4S1kyK3AyMWJmbHUvQldnaVFEcXZxZ3ZUbWxNYjlYODZzOEIyNVFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA4Njg3NzkwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClhqamdjaDZQMURRYjg5bkJJNVpCOVRKaUJQd3FOSWdBeXJTSnFOYUk3T2hTak1rZ3pSSE1lbWxrK3ljV01xKzJKVEVNRGtVSHBPSWplVGlReDltUkJRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.4.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnJncytUNi9pa2ZxdzNaSXBoOWZWcjhXdG5aZGZDaWtyeXBqVmJCUXFxenlpRHd0NHZuajF2cFRmYmdPRTl5NDFGZHJLSWE3MWtMVmo3ekNaZzdtMXdBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMTczNjIwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmlVaHpQclJlNGQ3b0M3cVZUWVhXRXh6YVVMNVZSbVI0WjgyS0FsTUM5NXFxWUZCMDE2YTNZRlorcEpoM3FCVDdCNnhxM1lrTXZqbkFEMjk4aWNTbEFBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 16d3d626d721c065bc9ff94602c55016af5c8e02 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 23 Mar 2024 18:38:01 +0530 Subject: [PATCH 435/864] fix: mac icons are large compared to other icons in dock --- src-tauri/icons-mac/128x128.png | Bin 7989 -> 5868 bytes src-tauri/icons-mac/128x128@2x.png | Bin 21030 -> 15019 bytes src-tauri/icons-mac/16x16.png | Bin 634 -> 532 bytes src-tauri/icons-mac/16x16@2x.png | Bin 1337 -> 1056 bytes src-tauri/icons-mac/256x256.png | Bin 21030 -> 15019 bytes src-tauri/icons-mac/256x256@2x.png | Bin 54467 -> 38092 bytes src-tauri/icons-mac/32x32.png | Bin 1337 -> 1056 bytes src-tauri/icons-mac/32x32@2x.png | Bin 3254 -> 2414 bytes src-tauri/icons-mac/512x512.png | Bin 54467 -> 38092 bytes src-tauri/icons-mac/512x512@2x.png | Bin 138135 -> 65104 bytes src-tauri/icons-mac/icon.icns | Bin 390922 -> 251075 bytes src-tauri/icons-mac/icon.ico | Bin 4286 -> 4286 bytes 12 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src-tauri/icons-mac/128x128.png b/src-tauri/icons-mac/128x128.png index 2f36433cf44dda0b54cb24e9b4bcf415a4d00bc7..1b3823d40b30b8951d3ad58238c72bd99018786c 100644 GIT binary patch literal 5868 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 diff --git a/src-tauri/icons-mac/128x128@2x.png b/src-tauri/icons-mac/128x128@2x.png index 66c2541b4eba397e9295956dc949bcbe8d743f6c..3d2c0774c40373b2ede81e58794b055e90ef61f1 100644 GIT binary patch literal 15019 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 literal 21030 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 delta 610 zcmV-o0-gPo1o{M!BYy%xNklMYAR;>b|$Xo=`pc1sGmO%?$w6ax&l@!*PV1WrHV~kNV1Uluv8hvlxyD_iQ z8Kysea5v|i?|dKUoGSn<%L;dObzN+3ZjPF!8PZx8!U!S!ynohO3&ZqdtMke4Z{DTH zhA8o+|ki-od3WXK94>55To&2 z!5LLmRgpj-AY?2SYxy@7oUuOgFK?js{UrZJG#YI&JkJwl3^aOr08!UOer^nJ{0h{! zp&E{rR28^}>wmhsjE}&Z>POx_g^YwD?84!*sESZYmFv2$f%ZxocwcAmW(JXqY4AX# zRuE}WJ0_u_ObJ5-wt&u|XCB}t2l3J`U~L{_aS5z~P2e-gTX6_2!NDE~Y&emg{SC6u z$-V8zUY^6<+KRL540hda$O1MH@-fPNb-q$cmQBXr1L(%n z=&MiAy-#s1(0A_RqnM@{o|u@J-qdF*LNb|5S(a7pizuZkJ3Bis#A30S wX_}Qq%P2J@1U6#z^{dhG>wSH_xm<4f2Uqws{{0H4N&o-=07*qoM6N<$f?IYcbpQYW diff --git a/src-tauri/icons-mac/16x16@2x.png b/src-tauri/icons-mac/16x16@2x.png index 0c361e81785b9b97ade2eb895b6aa8415cbef113..38b29b57fe4961a39e7aa6334a04c97049aab2bd 100644 GIT binary patch delta 1036 zcmV+n1oQj33ZMv(BYy+uNklq^00 zhqkV;2^+o%(kb+z4}*?9^ufm=J_tTk1#whXe2|GKt}iRm%@?I2P1%FlMi;QNO^a<8 znz35Co8^UIOH0ch zzu)g;jBz5eL(HZ!pNc`ULqsGD!^p0ztSral@%Z%g^mWO=jmE~t#_{p-%e0NeVzG%( zC=_z@+(K1VEtyOvx6`~tDwRt4{eHh>TF%JG$Y+wWUd$|s%xy=}*x1-tl4%K#$Kx{$ zBQL4y^`Cf;tbc`Hr0*q~nwoZ%Jb8Hmt*xyudA(jus;myoA5MZEq`~+0xQaSDIy$$G zygU#Jg@RIct&qUxwKEWZ#-P1(wW=r(2m~ApP!vU#vTMQ0V>31YYwjoT7f*uk>#Ztc zj47q}M~;AqxRmWgHuIk*zXmfl0I?hg^X&$I?lnMZaDNaz;{!qOY1q|T!3*G)*lxk?o5F0-vJt$0AH}s>o779;NW=x;^AWzL!1L*4WKXI1$+B0 zaCBH&x)SFCm;kw32f!wBb^w;ZWZ7LVA)C^KsV-qeQ!uwH!8cJwzBQ( zR6h;xp%Bs@z}x_o3_!a8miPzan=hn%H!2H|rW{w87ds;D*wObUG9O-ru?eVih0}xh z@qaszo33~jZ@pI*P)#TE`Umj$o=51&ajaeZ4eQ|`)C~YXPeNo?rS!)ZU>HVD%C5$N zKHyosa2oAXKTKwG15w_2wuwfg z2PN|oQ&UqnB}JXwC!*zZXDFYP$FiB3nSXi7w4Cnl?mkKN1Z3^eESHmnJv}{dNv4(b z_xGQbl-t1I;Nbg}UaoD|*4B1pXlUrHuIsNvB9Uf~$J0+9>!hC(67pfPG{YBqVj-extc7-PnKKHt@?TerUK zaBQ=C_wHS@>sYD4@hxhg{!K@JU0vNrKP z0A8>6nnUA$GJik!p$dG48a%mOg&oon48v%%ed|RYnF0373!T}8x^@8O zYW^H(0&k`u-%M@KY#%&tWSb zlLlZJEtuDjV6`^DKs(Z%i^}yt=LP8Rzw11<&3^~}1-^bCQy)fK_p!t7M0Bk1xGuBp zY$Ri=?JNZDAkuOnFAlN&i?Q$bj$eDR;AUarm5?wRl;FqY5Ca5_KX*mw( zk$(U*JsAiv(A|m1E<@zKgi;om0WgCI%XT>0Oe~j+RO366y1KEny8)<}^&osE!_QP; zK3#xn{fCr09k?b7z#O=x?Bb<8yEoFIVuZ2Ro6+C4kMNwO=-+OG)HpL?(`nC^2iL|u zOmox4ea97ivW{%6``@NJeyk=pXT!X)m9daC45Q1@ogjL2=fvWkmyLF;iNVdABCA{eaB$Kxba!`m zk)NNx+;L@{1^h~>-gkDWVf$P?a(_6kL666?CK5?wW8SVcue<+ys(*4A!!Xgwfy?%WywvaojT+RBE8h6@kM zabsg+Q&m;fi?KfA9@B+|g-;Y07u%ob*}5KiT}E!O_kz90ZA{Y)8irw9xgc_-rKP3i d*Ksz0{{cM*U4+>j!+Zb$002ovPDHLkV1m+7jxPWJ diff --git a/src-tauri/icons-mac/256x256.png b/src-tauri/icons-mac/256x256.png index 66c2541b4eba397e9295956dc949bcbe8d743f6c..3d2c0774c40373b2ede81e58794b055e90ef61f1 100644 GIT binary patch literal 15019 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 literal 21030 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 UTm4fE0|Guy_AYj>Y%eAK532@OIsgCw literal 54467 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 diff --git a/src-tauri/icons-mac/32x32.png b/src-tauri/icons-mac/32x32.png index 0c361e81785b9b97ade2eb895b6aa8415cbef113..38b29b57fe4961a39e7aa6334a04c97049aab2bd 100644 GIT binary patch delta 1036 zcmV+n1oQj33ZMv(BYy+uNklq^00 zhqkV;2^+o%(kb+z4}*?9^ufm=J_tTk1#whXe2|GKt}iRm%@?I2P1%FlMi;QNO^a<8 znz35Co8^UIOH0ch zzu)g;jBz5eL(HZ!pNc`ULqsGD!^p0ztSral@%Z%g^mWO=jmE~t#_{p-%e0NeVzG%( zC=_z@+(K1VEtyOvx6`~tDwRt4{eHh>TF%JG$Y+wWUd$|s%xy=}*x1-tl4%K#$Kx{$ zBQL4y^`Cf;tbc`Hr0*q~nwoZ%Jb8Hmt*xyudA(jus;myoA5MZEq`~+0xQaSDIy$$G zygU#Jg@RIct&qUxwKEWZ#-P1(wW=r(2m~ApP!vU#vTMQ0V>31YYwjoT7f*uk>#Ztc zj47q}M~;AqxRmWgHuIk*zXmfl0I?hg^X&$I?lnMZaDNaz;{!qOY1q|T!3*G)*lxk?o5F0-vJt$0AH}s>o779;NW=x;^AWzL!1L*4WKXI1$+B0 zaCBH&x)SFCm;kw32f!wBb^w;ZWZ7LVA)C^KsV-qeQ!uwH!8cJwzBQ( zR6h;xp%Bs@z}x_o3_!a8miPzan=hn%H!2H|rW{w87ds;D*wObUG9O-ru?eVih0}xh z@qaszo33~jZ@pI*P)#TE`Umj$o=51&ajaeZ4eQ|`)C~YXPeNo?rS!)ZU>HVD%C5$N zKHyosa2oAXKTKwG15w_2wuwfg z2PN|oQ&UqnB}JXwC!*zZXDFYP$FiB3nSXi7w4Cnl?mkKN1Z3^eESHmnJv}{dNv4(b z_xGQbl-t1I;Nbg}UaoD|*4B1pXlUrHuIsNvB9Uf~$J0+9>!hC(67pfPG{YBqVj-extc7-PnKKHt@?TerUK zaBQ=C_wHS@>sYD4@hxhg{!K@JU0vNrKP z0A8>6nnUA$GJik!p$dG48a%mOg&oon48v%%ed|RYnF0373!T}8x^@8O zYW^H(0&k`u-%M@KY#%&tWSb zlLlZJEtuDjV6`^DKs(Z%i^}yt=LP8Rzw11<&3^~}1-^bCQy)fK_p!t7M0Bk1xGuBp zY$Ri=?JNZDAkuOnFAlN&i?Q$bj$eDR;AUarm5?wRl;FqY5Ca5_KX*mw( zk$(U*JsAiv(A|m1E<@zKgi;om0WgCI%XT>0Oe~j+RO366y1KEny8)<}^&osE!_QP; zK3#xn{fCr09k?b7z#O=x?Bb<8yEoFIVuZ2Ro6+C4kMNwO=-+OG)HpL?(`nC^2iL|u zOmox4ea97ivW{%6``@NJeyk=pXT!X)m9daC45Q1@ogjL2=fvWkmyLF;iNVdABCA{eaB$Kxba!`m zk)NNx+;L@{1^h~>-gkDWVf$P?a(_6kL666?CK5?wW8SVcue<+ys(*4A!!Xgwfy?%WywvaojT+RBE8h6@kM zabsg+Q&m;fi?KfA9@B+|g-;Y07u%ob*}5KiT}E!O_kz90ZA{Y)8irw9xgc_-rKP3i d*Ksz0{{cM*U4+>j!+Zb$002ovPDHLkV1m+7jxPWJ diff --git a/src-tauri/icons-mac/32x32@2x.png b/src-tauri/icons-mac/32x32@2x.png index 8961457262f713e5f4547bc7e4d4291b64884a26..91908bf6d6a7f7c32745ea2328aaf43b40f64814 100644 GIT binary patch delta 2404 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 UTm4fE0|Guy_AYj>Y%eAK532@OIsgCw literal 54467 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 diff --git a/src-tauri/icons-mac/512x512@2x.png b/src-tauri/icons-mac/512x512@2x.png index 09ea5da0881bf1270bf72dec292f0e64c8f4b8b2..969b52aa2ac0922fb46b7dd1557085935a1f8441 100644 GIT binary patch literal 65104 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 T%h-`3Oe!Wu76)?nQ$qd+80r&y literal 138135 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

C^=gv&<`wkL?oEJ3(d%g1wZ05|1H)F;T7k<% zM{q-H%{AvOZex9pt&~1{g)+rN(^J6#;r&Mf?-Fl3v_g-NqAI7b1TmynfmLB2*nQS~ z3U10@i9syK#$yd>>7Q-}7evo|X{vF93+@o5sVHRr{OQne|2uC%#e4GNQt( zwj0S~v$gEss;H2U%+JeTSU2DJK)9ja4%=9q1sLwKaDZ@q(g`Fv?1ZqcRG?GhJMUGnn16J{J2%JxL^@XwV|aBo2RF~daX24Up_Xb0=E!U2 z=N+akHtV<@*|bn`N^uu7g=qJx8*AtM&&Vd^5u*z;8`pAT%Lf4E^7RGmPNryhF+8(} z*_zotQz5g#;;RcqWW>o+hfLjYad!51oxY~B5DyBJ$#TNIc-1H>CgF_16(Sch^ZXY- zUl|sEmL%<773Y*8n+WOinsR6r`4OdAXyvjhJhTFPc)+r{Dxy)#PHmC?oWPAvMiRLF|{WQ6t9DCdD557Op7!#6j3q`(-&NDEZO1s{{;<@U8|M*5hsDeI<4V z3uX@UMbg(_h-<^R5sZ=Q2KtGT_Lp{}u*QB2A>0CkjTJFAm3>j`KZhh-VLWV*Q$!iw zWVL<6MUyz(6vY%7;b58G3l%2uXvv>bWDb>TTkZT%tlH`B6V1?)O>mPd zV(=O#4bJz*9GxL}{CV&_moMCgcV0C0N~f>n?NCSfQa~+a7t>@Hq+3>-+!860uIs5| z?I(pjLtEK=Gq?pO5HhN*2lrbouBr;$(Bf!KGld@u&UdxC-O|zscWzOz9c&aggK08m z@jn)p>$1~kPr3!ewtoGwTa!3I(mbb@^at$Tc+hOMo*gkbE-k$J+#-S!(-s^YcFd$R z+(u5)iUhg#Tj>;w*Oih#WVG|RUR_&${Y(rRWs>nRhP2kZ;B8%n_#TD|^#bD#A^voa zS|UtxFTkU%>vC+1GppU;ZGZnrqN@Ur0%ygO)Q+$)PP9NTDc}(LkgkdKL@=zXX-;_I z4{L~uaa~2l@LWSiv2jEiySsd(jYo#CoEPd7@dLxivr*a~wlFOIrobUyNzzY^+C{KM z)k1nfnuyix^{PDuiL@&9AIIHo#^`pZNIkasYYFN}d&>8bh_A{#Ga-Dw@Vo2z$qt>g z<&dl*M+pZ{ih03hPRC{&iRc~s`_!)_ImTW&avk|H0I&6^Tzc4i;{$*cHvQr-g~h!F z;e>GEHgNnvR?i}(OSIKld~D*9g`~tFMm*wYqQgQ&`m2+Qnt}vQ*m}xazmNN`s0e&t z9r=1V(uIltsc=i|VQ<}k^;*#Gw(TIJlDpS?UD1I@s^wNgcO#sXjBjw!;P4xJO%=bn zhv=iy%3mv(&j^O^W^H7kDIz}b-l^%ATSZ+th5E7XIqna8JD?dd%9$U z`O+_?RkJ8;G2*U2Soo4!kx_4%hID&`@_R5^p~&++wVmv9=j$}LT#OopI~Hzzap<(E zd66t$I~=$p&Lm0Gs}uPV|0SW&jWl_lHm+1J#@5R)1QWydwF= zf93n+?R?;|$Xhx%3rD%prkW(?IX3Qs(?r5{BGZ%m=HfAKaxQ32cCARN1?mIQB!?yX z0A&3O-evRXCo%n-v1&?*)IuR;D}B1-Elnlh@Hwu)*H7fYaj+Og-qAre-^cQ)ai8v# z`}_`%7z~!=ofPk}dCg)`o7dA4&%W!p8_-%I{hI_!?)njuf*PEgnd4&FV4v83+B)Wy zXP!u9^?N^^t<@P!jJXBh!4&W1d>?2k(Nwfa#Yi=d@bed{Db*xO&)wzMxCc$IZOf|k z@Hx55i6Smf^kj~;sA-MOc{6qV_|K6rn5c+Lr%Qh2;*T-p;oI~H6+!4T6(lIa&VEaW zp*421sgGv9II->qP$MK-)poCY?u4U4(c`)4B=>W^2_5C2)GACv7t+TMjGZJgP8~bkFZZ5z8z>|Az z-_{r-t>FZh5+@3qPqtpo%zx@Lzw!`ev^yArxYTR7E_eAz==K+}52G6{?_inazCWe) z9Ne>VXM7C*CR%@SrN40B1x@?^e*6FB7CgEN#mg}X!cp!4IXeLOP=2WXpy0l-pOvYg z1OPN^e$Z4`q9kJ`1OG*-{OG|`0Dyuop#TXH__XgfbOJs>oSrJ(2MT&vSHNE$yndl< zuBHa?fUijaNU#+EyLb!u!wmj_%AX1W2*78^#otn)|NAc#NG15cuP@$6jx7!R-`o&4 z$a*a?(oDzYhL_>9rOo)2_Isai+)8^7`wYMI2>Q@3@)6#S<^~BDssFj@i<)}M8H2*n z!_Phx)`E=wq`Yqj{2U+L@`rX@>R?t*XHtv2ap1g}xe4w+4G#s860aoHPIIdJdjpOLHq6KDG7Y{A25{ z$S-h|>?U7-mljX9O-}@}Dob!EE-p;^jlP*m4~-=w%v|9`^{n4`TcHWc=D=^PwX$*+ zC@Vb06l9jg)UkBvtT(024KLW#fOi(DlsdJQ^P(cc=)0G#bW8v2mh*hIReUvswy(to z^-cFv&V$s6vO6srh@)Vm0>UF)I@6_W_?twDz=P5 z3%=C9kX)1tCK)4kp=v0UABib3x|{swEM(^m{e0uGZ(p$2NrR>y=A`5#!G@#+3dPwe zS(Sc(OlMy;jy^f3BM;fj;@I11@~V1t_wb`mXzv*d3FPRyb?PhKCm%UAl|3t^PyFAV z$Cap5+ft?*m2GREK#Zqu-$+tdp;?I1_`W+UP}=^($${+LaCRlm*tN{c7S@wH{iwmxG}<)w)h<<*{Di!0dDiGFT4`rMU2wh(IL!l3rU8JNB9o#Lf` z*7#hdTEcqr7(6$1(Uud&got-HoX=VQhSwNP-CTboNv#9wJt-1b?gCIb16_esmuP; z5MCsL_{{2-+vEzeTacO0BDv8BmbGn(%|I{_51QaY%XPj6R?t#UJvk=xsiPM{xLpc< z6|`c>raxtXd!MDrZbKk8<)S2B$xixCt8e#q5czpAjn|3n6%02FN=&-CyH(I(xQRr%A|e-ngNd z;<1|j$#b*Pf&!QBh1T$d?GWv(L$`pGV0I77Q3Ka$k8?}qA`g92~P?NL9w>t{Mh!!on>&-5fl6lt||_pNDR9vpAU8lE;@YA~mO zC>T@Gr1r5-)_NY1_>@bfG1fE^*U!d+X!Hc%1*l-&mmqIfak^QZQh$CpSw43pO@XWU zw#(8uD`E4DNINb!e@B19#kykRdt-F#y6yuMJza5J{_AHj-=`Z5f^zy+qnQaZ#OM8r zx=+R~;B8(I^I6wvz!ZTj+9py z;?G*bSW>X#y*`K1Z%&55VhHxy{Q(uD08e4XyM0e?pO^iBAK4J9oyR<{j;jw!kWm5k z4DkiYAEoy5ohG6*KD5eet%>7WppRKqRTZrE$Q>ldX3}bFYj661z^gd4_H6Wi9|uuT z9W+7ruVKTIsKU1kgO><&^c{XqzfCKn}u=E(iwKX$1bfT;Hi%q`vi~f4-@y>DN2;T2(zQ^w@}ANqK4w3@RuE)tyg;s_%j?fKELh)-nb?La6!&7Ut_5^`KE zy;wjC<w3qZ=5S5UHus`^R^Yn647Ry5BTcnq~yL4vSaqLFMf zZiLQP+*f;$;?7SJU-86eDBcGh3JLd9M9WV}7I*$!RPj1&`5aZt1=zT4`Hj9gNw^CG z#WvNKrmY4$AEJXpgCv2(l}m;=kje?C>u9kF^3tZ&ypE#ZFVM@STgoyq9|a)vk|K{f zKEIdeq%u0G#68aKHv86II$C#FYH(4`fZw793H2ob{fh09xc%g4y#(S*NyE6#&vAIi8tQ$8(e6}M)w$;^o+`^J3DLRp*yJI1py;cRV}BH(@v zd%@ss>@6X1OAM*42-!2L=Kpr*+Ep4^92O&o8!4|lnBMYQk}7A&B*u1QBq1!cahNO5 zOoUs1Tjs1|1iz=O^>P4VWO&OT_HD8b<$dcVDD+dQL1?&XK-1{rA!i3N`_KH<& zkaLkc-;=}d6}Gmfmv(Iq0WlEfcL7uE^%v)sn!iCJd86M%>UZ9p!(L3lh)WnW(oBwe0@a&Hf?hnFaNow|3x9{BT zzpGv%LHqa{olVc4PctCSFdVZ+KLiCh=1u@ISHuHOb?~5b`p-hSm%!osBKPjW^i6uB zqciiNMxJLB9KU_Mk6RIEtw*Nn>r3LvM|eLDf&RPyq`Q-|$ZcnyyXgBd=7OHBVE{|S zj=(yQrSCAhGmnL$h`@IlL$g`Kv+HEEnkLVj&<%$1Ay?OYVqq-v_+4B_*BOzfrZ=O=E1r73|(ca+M7p^dr3riyXRWw;X zSvn&NjlF}@G|x8a=R@4_t8g~&{eCMF9De75F59CJ{<~5nmmobPkGcZai(BuN4dDww zz)9-!r`?<Xu;~HM`mv5Rh zbc#7pF7*crcL`nS1B&Lok}+%fW!&#T219IELxa4dy$zrQo$3dwj`Kwx0-UO&KhR%o z&z^@Y&42ex7D(mA4$Jt3xG$_3;ZJ5$NAa_Il(%vV|CuFuz#3X0gFoAobJ*(^t4BJE zhjpmO%m|=)2)>3%LD5wrQ*WsuI;rmRijpK1;{DyRA!V|3C&DGie(J_5v%d8glpT`S zO~V|?1TO8uCgjkL;WY638VnfY5~C}x4jX&WX;65&XnlKK-_gn~zw>c_eVXM9Ey6D!6e7H5!4ie@H8!bt z+nHQ4V#wR8N4iq4ZTXoOPvR%#QGg@ry~7Fi*2W=rW$|9<-U*?Ona|vMaW5`6uB7X) zwu64~E6Msq=~~$ZGjU!%{ciHcwT9ombSInI$V04)Hr(kc;(IqgXR2QpFwO#@KV<$^ z@+#9$PO^W?rO?x$7wjRlk0(V0cE0_4zi)z3euU)el^|=3KR(!JpGvnFD6}*lE3&4-{GP)o7ZnE*<#Po{=77OS2EQ%Sd z&8eX{^7}8(ht$4*;5}EW-~TR9i#eUe%Nn6x|EI^sBwd%F7v5AypnCn60GHIe7Pp_w zQs!r}dwTiYB`4=WI%Zxk&-DgG1rLR*BM7ZzbFTI0pK7++fB$nTcigUlGt+Q(V)~a< zc8Nmce9lMWEs~G30(pZ@BkOH1XS_o5UvdsHCnxX?64=*AzHHyXz+Z9+|x1OMmHw$(R(-CO!qd;IwketSqu<9r!~0zxbw!viV*kk^r=i_j-T_>%cd6l`bR zkoZW>+k+o#l{Igy&o+eQUMTrBHs4?lA1ngXg^UOd-z{^|g7R2tu+0<%lryw9GxWlg-=RB6(N7j zqr+z3^3P<>Ju0x?uhx(o-Pjc_t$s!il>Z#gZ%m5oixB8WUzBK^3xE;SBziF>`Xc_j z&`xGn-zI9gv!Q3X&uiU&)9XxyeA`XsJns>6YquzO%l`pj1)zlWWQd980D&&f#b}RB zkc*R=n<0+)pLPdu+IQV;t#Ru7!Y4NCxmDYn+O{b#|B@h_q+%E4!mFV*ng86RzAob# zc2I4uHyQs(PfzdNV5ZtApYE>(zSQpjpoMGHzHAredr!(|eNKt!yxG}jZaiuzTq5Yp zbjTvsca<$s#^-EX53I)IU0Ew2gG_t<0Jdp9tpABM!iikQ!5jY>?DmJob829<wNCCk)V%C)Ot)t{)& zS(NC17CzD*_Pjvfec$JFqkIRXUTcV-&3OPF5FQv0H9GOt$72nX$CCY*Vjgf;9%SeR z)>TQ|5tg=_saXe`=C^`duoD?#c`>v9#Kf2kIu5#go5DJ9-`Rt=yrlb`1=hb9Q1_8F zvDat1JFc0@vYDl5t zOOxJet4HNrrJr;qTn00tg3kR98EQ!<=J1{He^CV^v^yAXVX<^~dHGypNY##F;b@kP z_T6hD$hOsqNSM{32w;oJ{*?|!YQebR=Xo#saV&A#Jj1iXeAe{;iRc(PB$3W-_g=5G zQ#W^n^sY3tddHp*DQmx3DvFBXrm$lkETLB*uXIV*K>F95tg+)tK_C|0FW{q47Kx6Ct+`)^6$&t8bE}sv2(@ak#z&X1c}5`a-z@hekPd zQpVF&oq7*nQbgV8zlB>$z$PxjYypNhNrBzrX&qz}(GhjhzB+r1&nw15MdKzTC*tx1 zQql;h#8dHEa_1}b_LF>w?n9y%-hZ|72jKfVgn^?Dq`sv#tGDWIHuMns7JNuJ(m9^r zy*@In9V5?Magde}@y3Df%z2Q#;$$_q9*Ob6liB|73*`FKBmH*jvQ$ zle|622FRMsg>rz3G9CyW?(NjH601Y=*Fx_NYdlps+tH+IzMadz5c@H#h|~V{jVSk3 zurb$@=844B_1^Q-+c{o4=a-el)E**h^cboR`VHl5WUIHpvdFEPoiMu^#{c{I;V3K? zJJ=a3AopsiCn=hi&8^}Fl3EF(&85j=*!`0;GR8(U-7lq#%zI*eW6Nj5+Q?Hd03X=> z+$#4!Z*}43mzTw{7X{VF?`495xiJN-X_I0OKC&83gKAGmQ`blQZM~=55j+rr3YHVS zik+>?l(Rz5;ht4;oN~)Dv&Drju%CZgNUnrF zMm;9IvTk(b#pmBai+X4u0*-A-t^%{?d{sOl&56D?`y=r> zJ+nEkOLrtQlE?KX1|I;w=I8Hgt3#Gaesx@tduBv*JV&W^(*R=MFdU?*7l>yJa(>Ej z+@|#QPkqRjN=ncV+LD-Y;KbUej;Sy0-}#+^ktRV{NV9bDza@Xzkz|w3WzWiBLZrEls?I{ zw0QdGqY*`nTpglm@HfxUHlY#(1J@x$iUuM|-t1j8s&U**yZ>Afyf}C|>i8@^-E8YT z>+E^`yF1rX){lz~8F3twT-o%kCNiiTGo6xl6~t!cl21`?Zio~_aYs}AY37fsfQ8w- zS!B@lM)hCNRG|8PiqGR>+ol(1DK6RJOFX_wt4Ai<0DKgQPv%Kb`WRK&hi&i|%=cW{}+>!Qd! zOG{Cwj4n!!%2OyYPkSINH>~n8ykvC|Z0&Ypxx3<0x(mt%+@CA5@<8DF(HLTZ`cT=_ z#E7w5+T(lkHh%dX>7mTs`dfYEBENQM+`v{w4=P(yv!zdZ&{D1J-Ih|8!fpC5w^qmi z7WuF$t75|@Vh*qE9Mf=#AWzAEVS%O|Ot3lSxI63m(a`rx`&$w1N_V6_(&O5`oZ__D zK9~JQl-l^8WR~@US*AMG=(Z+j2VKnFu3?ub^$g{2P)!QA6Kn2%_SOcun@!0nZC`%g zzgRKmY9vc+SE1bP%B6yKa=eUnxM^osEk65quyWC^%g?#R@i-EAP~u#)>g&)BHKQxX zC6`O@CcXUBa>wBKDXl%;BpW_{;72^-N7TVx;G8 zl$P}37(eN^N_+;wF+}GllLFY`QJ&O4-maCHxlW`R-^5eB*(@KqQ2q&(+pnnUSyEl? zxzm0#HlUn=Iap5Wbc{IX97hfuBUQY^dkPwEwdY=6-PT-H&Dk)tZia z?6)XR@0AKQa6u@?R=r)RoZKAul-{cOF&14V zJe^0KLKA|Y>3dIKBm_qA;Mo);!J^8G6A{X`lcqEa);ob|Xn~t&?a<^q>Uce;m%BVR z*TZR0_u+4+-!G5}IHh_$(N)mn5RbBW5ud>f)xd}mvD`MWEP3C6`|EfG4PcGF2cIh! zp`@+_om+deYsi#Kw=F7;5HT6gQ(pSD`!O^5`cp|RH-q*zLP=~_8%~dXW8JTOv*+3~ z(9nzoX?o_>*CYOX6|sI>X)|xA#9PGG_ktuqD&=7>9{Q;v_NqL)CrYFLD#Iae%c+LM z4kjG+2O4Q;htZYL}2brzVz`q-%tnRN4pW`MtM1@WHQkhzjO} z{zh4#haxGLp_;=#>6){<9A7RFw3lA|n@1zm6Yn3LF*-J1-yv_U+B2N1!{Ptgp(j{K z>vfp5n0Z5IG>5nw_`O>?%w^W zp>GP;$AY!m%s+<${KOuV9lhj>Q!YTX)EjN0+esu+AIOl@B?F(fZ?0M-xm*dh{)e?_ zia_U7TsxX6Ibu2eH#}2S-}f=s1;9^uXQnI?1i{U2K1fl-O0k?D8oQKr5(w|{h* za2bfLJcz%>1CSMw*Hn#*lZT7Xzi*2EPj+}7avsg|2{~X=9vZo<7=$OwNqG$lPMyx) zHF|2@`&H2_WWbVSe}A79>GayZJ3SQh#9iT7+4Ys$XL^9pU=0<-*!r8Gfw{d%qF$gy6MYwNBz5LMf!dLHI9`U49Pq5cDl-4|S9IWXMV&{BU+N=MDO1Av zL-*D7u=mLG=rP0fWe0_~W|S#Vw~%j~cwApl&Tb4)8g*yf0vzC%Eb;B%pJo$a;<|e; z0&rh(n4`v-zEHUjKl88H0vr<=Vj+?VJVV*L=ww#?YDAM%woe5E8hL-bk_8nj^C9o~ z03AR$P3ZY?b}pEsAZ%gxU%uyCOVf5fcd7mCuwJFF_ECUqop$xGT_N3`Cti!!P+-7R z>eG?m%?5U2b~iLc+>o7l-jE!k%iEFG9G`I;{4U7636tJksl|tbuwi~CaO?4fSB5`< z{i62P5pu=(!{~XV}wnRuA-&{x9}$oxXxOrUmmf^4}n^}z^FHW|{d zTd_~lY;a}&{uI=b0k|#s_eyu5;3>>ppff`p+xTqMmeS(7NOcIauCQOrK6gWe#+%7pR}-0ipT8|iL8xJzSz7~u|i$h=owRaNn<>0jvd zlSFgdV(XM>amAs^$kTNrKu*!Osh{nVCN@jTbWgO`jN5+9B>1O)dlFFK@cPr*?Dpoh zWKH>^^I*6}qWfYzZz^moZITi{p$nn(t(52VT$)um?B|%%M|iakvWd{)erVXM4EmK8^@@ho6CNY~BtI{9 zmJ8fABA<)UFmnFBHRCn7H#dVfxO7M2vETQ?WW!5Wa_4AYlvvV+2PFy@oINS$-CtQ6 zh@xfr{Ru{h`u!0(aBIw+Mmr+V zPdraC+*`bT%-pX}k_gg5(RV2Y#&{pfkb+T{cYc)0V19&gNDJ9(p??TLK}YY@K2v*s zwYndU03i87KCF-B9`9njLdPG4vc*}i#@d3hUuV%+jTpKA$DH*i|A(fl42$Z0+PljF zOE2B9q?DATq;yJ3cXvoj?9w10-6$xjh$5n-q;xmZ9Rh+h0?YsKd$0Es*To0U;W;z+ z%-nO&JQCi1S{=-7Hbo@9G;?G81AluMJ!w5zRQB)lX%&ABLD7)sAC5i`#PP)5)v3F5 z?H!9^)0}E1$SN!M2ug-lAP!>;sP#XzWFBR_w4A91(g)lRb8d-*W{{urdH0YaTM29q z<;dNW;cZ@cuza#z{?20J%MSjQ;LdH~*zXF_&|86_=0F=8h^aC&ChBZ6q4c@RqS~Y8 zx0=P=piD?^Cz#;JETmVS=D$D2&4Q{5%-!S7S}1Gc-$sH`Rvb$#Iv7=xiPUkgN&?S5 z=awmfD2E=JH3teD=KWO$nHfLp$*%f-BmxjC(^;TBd8FUOur<1sR{l{L2o4;-YyvZ! zu$6~&#+uTkm~~%!Uw=6o{5#`{#S$+b-`iSmK_Cmg(~$v^ig*vA>^~Fm0xilF}uH> zy+%5`epItT3k|pWRbwydibWvPrA_$W?4{j!#wZqBS_$Y9-iY$SvwA>=x{^*G1G4DR z8(0(upMnosAM#E<%t8JVW7^A2R#*L1hSin#5K+w(zZ|F-l<{Z*Q+BqN`F7?V{e#h$ODAiElP_%rHme=}Wmf0J%Y*iYZc-gG6b zJsldi9nOQK)_e^LE=4P2SO|>G&|kM|jfbWM^Mj#Y zBnTpi3+}`Y3#d!hKr=yv@eRhPP?GM)@hwjvTfY4Axz(86nJ2Q z)#;11%hda6)`u}|smctyuSE3FtkXcAfLP%@5_hsUk9Wu9t_K`MKT7sb!yfBNzLt7h zWk{3v@rB#PO|dQokRk*}sMI2w-@T*NOGf~cjV}E({ZGvgw2U|Ui^Uq5TniO2+b~~{ z=yQNBnSopB@xvW}D0y0%)^H`GJ{nGFMEUgg4e2V8Z^MPmR80Qeu!})Ol?5BT%^4+$ zTTh?N1>z0(81kH&rtkHsFep8bVi*jpT~T`R^&?M=ECF$^6k4zE=FcJPP6sv5zTZgZ zk>l&?b;P$FZJcxQmKfpMlC%iWtAcV!QOyLwdpz#aXJ}H3YxD z^XC9LmuT;ysaCxp@C?=l%+_xtwCNcUy+`RP0hhO z7_EE`k;^S~Rb1^Ui{S!5T|HC1SX&jho z8q&`G*(_$DEnhSZ1Gt8d0MDQsfq7l*8bLf=trI2V((fL7*^KQv{L$~*!yi#h+BtWI zmOHwIB$q#-(RVYd%6_sLptwlC0J(37#zjtLi=&dqYu4Huro<8meuFuy5fAr_ViON@@XsCs17$mq|M68Akz=NuF63_VbinBg-&ZlM~8wzIvQ5Y{xPEdMQU z=Jc;i{BQ*z)&LiSpTW^hZ+fclXz<^O)Er^|G%ALlerj8lDStrX$?awNai z@H=OW!0c@~mbTx)!wA452WcQ=|8iY zUkQqti~m{1`C`ZkzBDvS=BK)0Y8Nd6?MJ{pkhq;_#vbE;Mw&82J=Y>HMr1w^oui8j z+UFkiPYy?z;)DD1%6240lSVfh+$EDG9(W#@dUCNP7l)It3*ycv24-m zNZkdrV>f&@67@-Iemz~=kmMVc<){yVZ2vTf^^~C2MieL|wu0@~{w1*fWP2P>f~G?= zF0!|`cn(@BO-@$XW#)q+@dj9FWuVIr85hxWw6z;S8~&0_f(vYtCVZh=!VXe-i$PaR z>qYpwXP3Rp>aex;Vs`1Sq&7R##{|Zz3HIVvwMXc}5I61wsD#7@f^cyq#6^dvSMNx9 zwH5A*pob2Cmu6iyS);7lpOH!`gEnPrhrxQZiEFj^+|&ik*HOPBZ6!OQ9IF>On*`fboY zeIBAvX$h<1$BnL+lH_Q2pp-4kOsPIS&mdey67oyAh3{8zOT?QKUE*^z>6Z~1LVvpB ztgcNN*WoxkAsKlT%xkiNQ{xd#lO9|h{5XFtvsR6jAbcNVIcq=EGWpeD=J^s74~dWw zNMw0AqvkS|pEiweU?E@R0!r2uM8w~sO}={DtS*mnf6JY+XB=R z98DFXzF%<1;MVzfG0o(86qMVtu4lq5MwXOi6dxD#*w=9p zH}*n?yv>o^ZfU|gwqiFA@~*WuoIKW>5e8{L5h=cyvdH(f2OKLuoBa(&6_`O!3LCDz zrUjp?!R~Io2_J+#A7Z}oSts#*SX+!Fy|OWRTb>}BMggX%Ean1hjuUViXr72dx8UG{ zq{4>3T5P}&9nL?ZUc9@qUj)%V?pS88TlaICZ63w)n@-2HxiP1l5~E<19WrOc%;A#6TqZ)Ew`&!h#-U%AL zia{mFiq&We&X{vF3|-jFGWwuXoxc}S1HtCY1#%OozRBvXX{Zk^L^D}7O&K&R_V{l3 zl)#=`283kj+#NE>Z)6s_k_gXTiGES5@YNSR8nuize zHRF@ka9%9OhB{dr@@muiOR+YDyyqS=IzGj$6;Rl~gjgV|bYQ1$|LVuo5T94F^#}1c z)iTj*l5~gjgHp(MLqG25PuRY7ze2x0$sWPwe*k0kgSM4{w>JE~XylWJd+o^^9sS3Y z98+EkH611MqQl>Py%D}AqmA>Ye%r$`6xx(PY8|%WF|yIHX0OcNuQH^4i7)rB9a1rt zxUDZ5M5*;6-CSJ5Ide2{uB9er_)lE@>j7t=_ThRIEodH%hKDH8y_Wz{Xw!k1fZ zkxQE?2_I$gat2j|##2Qwi!f>CKNtaF^(mOFGWm)Y0<;%?_IWqZ9Tt&LQ!nu5Vz+YD zY!dFX#P&cWC1w(C{?LwJ{u~VsOsDAruH2(X)RRbB1NW2$@D;y8c zu}!S~AGTh|0EtuTo6?G})bd5b#K5}?&o8=2VL&TD3TmM7UI+Ff%w`Doi(xK_tIFR$ z5A;`~d_Uj4FX59g*PSUyQ1|6cB0~{FS*8o}y?VZqxCQIaDb>lU1}Q|W4srM@m%tU| zH+(EQ9+RVr>2koZ=>nZ{d>&(Y1T}1yOjdBNPwf{1DETLVXYISOM@IX|AN3}~6vFkP zmjmx+X2s6)Z1WJo3B92bY$1OHbBzMuL9q*2cG0(6r#HW?COic~|E8%}GWt^9&<0Zv zfRxxoJ@1-tMpjb_RI9Lt9Rx__(@cD;OU@QT-Yfvi3;lic-Exq?|2Io~ht zv3*-t#ZfKiXG<|8aws=D8^*-d99?30{|(4%m$Xg)B_#t#khH91(19h7_~p= zWC`yKS?a|V;Z?-FY8NpBtf9NXtj(upeUg84#M zpQ_7_qVxP;v3?XpIEkb!{mwt0N9vvl`9vcKgb5*9$XCffvu;Pmp(e!O*I2zagoylT z_~sIlm#5guP<~hQ@za+Rg{_hbsl+@ubo8mie`!m6Z1SV{ELeUi_Ne?Ts!QN8!HapE zt8@X7(cXm2SF+9J7;H;lVlI{gWC~JXAY*FnG`ImO7Q7W-(8TT2qNT7uA zUk5y}9>@XDd7yk3z5CU6xXE6OID}2>NM2$DAjo18q$ih?J z>-gRkQo)wHV0**)mhn2@Z@vNE94#>pb`r;Q-DGXe%<)^9sL5W69WL=cUP;IV#_V>S zVnqBiNR936pL%@dyEi%|!&`tbn*y?QY3cfG$;B0>p8!-iLRUH^W41Af z&H5iSHSd{M8ma$Gm`Su*+VC;#kgU#DN44I@lpw=CoGx7%j<;O-Q+G0VFqITe3AI0F z>Abqb|CT*oh=Sum^;r09^H(~rI5D`u>E!u3I1b{1F?VlIOAMMBaA*3Bhv#b^L1{?C z$6L|eJYO^W;W>Ixec&o;v<}K&_VNTyZ&>Z>xlBImQNQQl9zxSs#&i%YV!`ch7^3jJ zHLzSm@>H*n$^6s6#ji@NC_Rt{N7qz*sb&c@@t~I*yrZbh0*=>%)Z4SLw9ieb8&1m+ zgj2}1m4QquzEpkilS6S|aOKjLPk#EzFYY#yfJGZ4pdll~v)Cl6cCmwnQ@6zX%U(HQ zA4#LcK=^_6Ti_cV4Y0zdwZo=nuP}JMsl@%d(}>iIRY|hClqrvpgRzcDtUH!%3W+#J z7mmZbzQ|EQl2G?HJc?@&^OLDf2L%s4k02WcuNX86%I^k0OL;zX(A`v9$x$8oswz@U zAD&Gh#c|vlIsP4AW`4$uXVv;Jo!;EFq!L+rs^6r9!j-)mzMHg>$4QBAZzidZQv*@( zvC83a(A@@)N)#D+^OfC`fCz{Prqy9M6Tdt3d0K}!XuOUwifOA`Jo^y$5O>1w3^mJP zSM*_67^0q{NKsC-boLMjdCI=qttd@T>zSpq@uMkE7_xw6WW0@ZNgdaQR0kIkxI!Z0 z!K=NpowWG3%BHk41ye_g-yk%QukpbD_ci|e<`fwW3Vt=zm9BJHSaa2vEm-4?Z8nO@ zysqZkXudwqTR5QiR-&!e|00IA^q^l$?T^e7o9)F7$DFZ>R8;p6*WuS~KFXiZq#$rb zCF$W^h79b1^uduY{2WY!CA$So<+j|tfJiLJg zo;dYk;_<$v`%WznS%FOkuLJkjnDnyw@=UEx^So9ovnPW-aT^Ui3Jfna=Cbc-r(p$r&v(RY+?Q6z zzggw_u6Gow-bP_ldQ-~srx(iL#@j{)iD|#+Dek@D$7#y8eu3JC){}$8v)LcCuJ~nC*pfT92n*HF%-(KBR_9dkW;CJ#w^s z1`A&YJ?*hgl6@@7yL*j(7J-y81m+X{cLR?k1Z#q`_Z1`;G^xyENbS5Lnd*3ldl66G zz~ef;9bC$zA6tKl&Y50|pe8R-u}d6H^gg`%LUPo>eoy}LV}|F3fy-DOqL@axfFP)> z1~Nc@!-S*oh!i}jNCIu&tG ze}AERFe(96je%IHz`R=YT@>Peu7|TD`=R{H^bNVgSp{dt;-N} zh$Dd*C0su9*jjxA?t}}~06V>Os8t)pg3RsBG#{&h0w7*O%`&YId9g7O9>M0sOr}3g zzsA*Z?kvWsRWj~&@a5yJ*so*lzHpA*|9Z*5!O7PL^XE>X=&&bpAl6&F^E$i} zQLU1~cp$unz`Xw!)s(<1>|@3UQ9(+HM^jNw=)&S1DhP~oWAr2`5!ZjlKe{Hrc|g8S zi~BR}*1z{n1w%JiuCaonPeh+~lO~Rzh_szX@b;bh4_L83e7&pvSl4=LfI5W)A6JzP z^nj(zUj~m>t?dTm#IIjRJWr7gbr4=tGBdZn*8!6szh8pLQBDLP)-W2Wt?xnCaaK*g?1)x_=8A` z%5-;_V;AmTN&TJ5d8z0^XIsGd=;AhE>~x0TclJFjYW?!jW8T-ZJUM@yvh_zFk~a7k zyc^&o^j&N35lbC!YwoAUwRFS7j}cX)B}>$hd9h){V-&y!Qd1h8O1?tUqWNYND3<16 zIgru01J7@O&gJ~yS1OSUf|2d*f&jbO6Nlt{BIs60(U~)JYN-AP(xKz|PwJUgZHG_9 zJA+SE>e*O~KN1dFC&`X3v(;n4VzFb!qkq!+7wDkWfiPSxuIr981X&TcMvs z@BO#cwbs{ZCP5KUJfaVNYguoY0NFh7bp0Xc%-m2Y0zZhbEn>>Zr1kml>LzZpUH?sU zx`X2;^1ngP+Bv!pyQ?OvoE1B7M=5i#V{Y}w)I0*2=cH%970GvRe^Y-@8-<#H z1okJxv~hN_CVQtjR`=yNz+<5hN#Rk<((#V0HTiY{nsgH%6Ha!#M}RsMVTFtOffduH z0Y{z6Ga8SdcwK5zzUnAl(Jz+!MyDxVXc*nxedb(fdF5iS$4gl@(n-t#mNzz@3%|NX zurw)2Y}gNCpN_bu{~6Zr0`5d|pMBBG66cMSUCaQ%?utAu^*}CX3`UPNfosMeEKT~= z_ESUrfyg}UmRS1Km<6S>CF?^YTndlXt`1=Ux#5@yr9GxpBy!f zC2hK{9}uW>*JuOfQ3P$QoWT(&1$1V5I+3`C@4+JtE$TUo*?*~=O26FJe6P|ukq`1 zr64&QI8^sh@qeLM3??;#$NfQ$3=^w*Qe_POTNM1_)9m#M^hd2tpi@y9%5lncGcQKM zAKrvhL^e2^D9>c<3sV9uiLICL0GL63UvZL~{Q7Mq3Vruf0FA#M_v5X=$7DWH!$Z8; z-K>vBl=E7xWJCPG%-UBo-m2zLjCDj24@C>oS2hKVYY8~q7_4ajm%WSAnV{JJ3rzgTn!4PMXuUR|IW$e@2+c3%Ojhgqvy3O_ez|B889=o!Gqf( zpZV_6y)JNWt8-ng?M2&9BMvb$Z9%%%*!glPTDZjT7D2W~q(?9c*dG+hXmNwSBS5Y9 zNX}nd(z|pouHC!N8XxLes|ZXMo1^tzSq|bXLAL!vN2YbD6M!^ zlawQ~M`ALO!jSxGk(IvJf-PaNm$FZ>y!o{$dT?V3$_q8$oArpR-BEgf`TOA<38-^)W~z`f7_sEA%?onScv~qr z?sskNEp$71>FtLbiJlPPAT3sMWVV;vRkbgnJYg39NKW;~t+FAyeWi`%BHNgMqC`c?wKe+|cY8AJ`q zMDPbOf`V(s@Hv26yq}0-PazbaRlkUsWKnlqf5ffXu2na#(dCz2T)Ap*G9kdj(!#4F z5R2;hB(Uq=$q=53Lrr^-mOVFLQulx@)Li>bwG!g7Htd4z#ANe3eX=ThEO%D0cPk{> z=*{zbISuQY+3V#dxpCL0$v8rMKt9Y7gVF?($#>rngbTuUR6y?gk?G&Bu2rhnP$4|$ zCFW1m8!fsGVQWrX^s4J}OfMU5>-)?7bWHc&t#`R|{;B$-LUrR!Cd^<<2X8%FbHaB(UMAarF)T;@`b^e> zlSBT5-Rs3@w{`BUB)jbo`tk1{)CDDt;j#D|-H-XDK+!HU>9dL{nG4OrSMrhXf-otj zg-7Z5yR3rm%ryqxVfy!hDs$D&ET+u@c4UK~ncGDq-5wf$wCDC_DdH2lP!nKcc=R57 zLsS`3y`=@k!?=b>?w}pLbH^35n(Qc6DLSM>vL1h_Lg1NUzX7vkpjvJPLQn@#9R+0^ zD#kQ2-doj!fah{;Uja8uiUb~(G(lmI24$9A9nk^(fv9-b)0mE(3%0cJC}!i@b^wLk zdFPtbKk`JzXSXc*$KP1xQx$H+cn=z-dMgP2e-{At>!6jr&Z@`=A85T&5xpza&MB`pZ|*u(}oG-iuYU!j^gC~KBW%LTlifra`LW;>LA8BWRp#E zeIjUi?lwuiFzg1``w*c~O^*jTI`#ji+S6h#*i5E}LH~NZZVyv+H6-Xw$+Gn|SrG$mciAPzfD~bhN_4Z~;|K>{Fm;HA==Haiu zOD_5GE1A__dZw3TF>tom6mt*u%>r3jn_?Roh>`$cM#&MfZy68FFM`BL;JS}H>UA}D z<+RDVy-KP7(8vsyn=jdT$RIblfytO!_08>=G2mQ(KC_tn#Kaz0ji=qwUT_Li!cZEU z=xLYh{NYS}VE*8Mo1L|3#5%2izorYx>kqUzKPa@3p}4@0&bQW;0wEf1`nXcES_1gXF%2pl@B^|E73xXWp|&^tt?(0`&T+H|5ER5o8aki^UJ zIjghOT(r|17`rw5rt=EbgZIeOjU2yT2}R38QMbwyzHNWqR&mO3(K8-!8AJp0Y5}(* z0dKoLv)8Z{z3;ZxpFQc5@`>KCXvXZgBgg6X=3ZPm8S_6?!7~cUfmS{x{dK6x>^l7O z2pu6MyhVs|s|}JmjD5Dx$qU+_ClcyG|B7DhWH>uFfASk|?s>C^S$4K@y>-d0*FSQN zc!WKt`_~1JurMjJyxa!r?k>NH=RwA}rJR=nO&#`-_Tj`R39rc`4-IU(27Cs09q$PK z&nSVs|C}Empm(@B`|9%mN!Y)9rc1u;qf!aBpX4=9Mg(!T4q~r&y@lPeJxbQU)WSJx zZdGwarDI&fS~+XHlAzbkPoi+!X?Pyzx6+^wt{h=_Gu<(7L8tAExUxdz{N((Z_IjZS z+L`?6v5-uqXpc89@Ak@#U%k?@{}ZC4ETZZ=&+O(#lCpwbnC(9QU1dAACF&pw6Kn3j z6rLFX&I(= z`VQG;h3c*({pxdm*S_!h3$tst6a(10wU(2Lol|3z)tf@{V&-VJCg{wFe#Fj!5v{o!%oHg`NAJ|5jilYWZjf`w z7oGm$n;oUK#P(jfNOr#o%N1i~#4>An{>+)8ol|MU-+AkB;-7>=MSR?NVK0dNVfbqQO0*0oBRq5gTmd*(J&?(lsr;&8BkHV9 zIP%Z#0PDhYMx|ZvI1Qrhi1L$3{X!54Q;rWU4GPTYoTet zw+)LhsQkt2oxgl?$pt=FTsmAIF*4%d+kLU-32eeGwz|B}s3g|5LqV@E6%~~+D0Q{3 z40Ik#`*1euQ$3pS`t}V3%+zsdRk_P(m2&P6B&7jZ*jF5s4LWyM@f2fX$;s*)#A6Np zWoc^-qVRolc0u#sIA+`vzz?Xj2P?l2!vZ9uuWl<@FFKM){=6W>?k<`czP&KJJs3GO z)X4<7f;)zz>#GRW2OE|(0x*7-v@bf0Me@4BqsGQ+cOxuWL#3X4%PvY#{c6K!>6KNS z%Rf+TubYn!Gs{k1<>lKI3qLqX`J5P^w3f~GYWi3lM`8H&dfI_g`e4MB7(d6uUzO-5 z081G0_3n#?D$gw3$sE8Hr^WADW<#Bt0qW8qtKdkko z%i445r(kUyn39OC!rL1HpHvdikI0x(6>BO4lBUQr$VboK{YDdlBn>L zJsa#X0U?a$ustap@A-I=AN4Bp$K86gYuY=Kqff}bliB;}(wuwa)?49!M-0e}0;IMs zyuC)Yf~(buPMQmr3tK4^pY^>v*H9nvt*7$x{?&!bkl+eFj*vNQ*8$&DJHT~T+cirt^S$(txd;mE71 z8aNTaN<~W+w4D5{7%=7iXHFW>ZYJCj5c*YKBichq>K1VZy?L zNw!c_0{FVRBLrstVuR8V7m|GJb^JCmhIArYCp^wzm5TUMKCiiUy<B=?6#tR!i?6 z4OH+SJ=LzMC0JNRfn+*>obinx2ribw?Ho9&Wv_wxoZFJ8@C#X$bql~glznXe&8xVr zt~=lA5oUrVgT1LU|2bAGT`Ndfb39NAvOpvDw?D^@!e7nwablKt$+%PNW&-QYt-aU* z@dMGYOD;FsHl2}sXKN#b)C3d>06O%Am0jnMY1rNy45!01f zMpQr15_AwK>Mv5kv6_SHH&XG(T|Rp*PTdnI{&q_I8;EA0e5y6a{38#Yd_ZT;C-p~C zg=LmiiGVTjW)UfydAY9a@N$4}Uyn!2ZJjAvkVJ(IAG3+|Un$|V1myK9f9~>6y6Vyu zM9LT0!vXzTmhLH?2 z=b_Gva$UhU>8Jb@&zTe3-O}_o%1BT##w}zIM9@zokW$7Q5wu?d;L38q(g+i(d#J4c zyZ!NZF7e=@k2NFFpCCk9X6i~$bufD30J-ScRMN{RSC9aH584<|z#;Xl#^e7@uH1Ro zFV`A@+)%8enbB;0UfW$+YR;o&@U>`A;TQS(L`^*q{8l%eG>a)j`d`0p`=KF5oiaD8 zO;`yUMeslhdlgIFehK0fB8@gImpIy^MXgsspFM#&(OPx@BWoR+MpUah+mo&mg1i8O zKfoD0T!&>ZZ3b^$T%=L?=njUI(P6gvx0#tHL+e%f8{xg2gxfa_)1NEeB1&}_#xrpZ z3THH9Jw#uN<%MAu|Kc|Pb^w5n1AAWT+#tuRnTJgS>S3aZwTw?&b=mv*GWJ2=q2~ap zE?oEsuWW9;luQ?h4kG-(yPPx_-Yw36|@fY*f?m)J@SW zMt|cS5qhbe&Qbci{XNw_glbWcOX7=@Z;%#^x>z+8oce@(AbGUyNiy4jqD8pezbaC; z`b&pId^+RwHDl%&*)({?eq~k(jj=H;R`^0f-Kx!-0k)>U0rkS3h}NVL^I1b5PUHCx z*bBrcXOtII6iQ)?zq3u%x6`MH3agM$PmPEpN>ZN~Deqf9Zv0_?+*o@oK$t|Ul(#BP zbUWp=q-JRAYBp3%Hsrhb{POIm)7*mKyY04-P2>y zI_)x|n_HHz8HZ_4fAR(4B~6(Ai~4|@FH^rIJH84f_7y}rsuykgJ}xt=A!2g#;;sJN zw}CFU&(a$6ey$dI76K->>a$@adPcWxx{L6Ghj;z1!6z)}igifA5#nn@W))x3{aq_n{Moavs>VZJMZ?TK{G3HWe(KVxb8=WA zd*QLmjjmA8Z}*s*wDw)pFTw(>ovf~rY&BV#43xPxq$QvX%Gjd6G3pb_TTBpMc3=IJ zxlRA7)UUtAaa&*Sl59=&S_v{6j9fYn`S@{*KTsF56@&3J&akzB71v^<#qFg<0+@bU z^}z_wnrd6Bc1bmlgMNxjy;dc%;NS#c%<2AJb)@(<)O&lsEY(8FNEQ08|Fhn768*F{ zEhs2$A@xgux3iv(qwXD^Be1T*DY5tHQ-zT{n-w?%wP?zE(=Newxn3AYcZN1HI03XO zIKU^&doS$xg|{L5PX>JZWLsn@T>SVTc;qm9-+##FiDMo)AIxPh$sY>sq)j#XTbM}5 zNA&8YuicR>6(IM1`8I0K_W~b>4yw8=#Bi1|z%6 z6E@YXk`{h~$Xib4-Mab_l`Bv%)Ji6W7FIEBopqUEZNgGzfQwxyKcAidd`B`GtAyvTa+#js<;$Oe5)FBwRo{Rg z4(wthL$SM#HtIY2mMcWu8RMU=+b~$9JmRK2nJg8YdeH9-dV||L0gj9ZPqr4@G4H!? z)gLcW8nM|vgIDb8L1PS4Zaalg$CO{+Lr-nmU2rdCZwf~?JV_+aTFKT$kn)HzfKW@>*{bwh z?R>pgT|p#QNO`g!BGQ=iU}qkiQJKLn;WGenC)tsy3E+ADjKOqp&zOXM7>xc6B+l>d zD4uTY=s9h#%BY5*OO$c#wjjU)IgEY0w3nYjx}D@`?9Z?`x727m$j!P{rNzvdQvShh zdz^K2e3#d%di0SmBhdzs8<7CQ8$^7S!M0#*{^3Kw)_dOb@?$eRHhVI*PYNvW z_<;5U^Wl}pFQ;xmsE!FZW7@dx8Q1nt_}0be&MwLNRL{N0OR+NClk0@PZ(m)T%v2(h z-gsE3Z9b-4?{28#;JMDY+=iw15ra;pG1$)2{DmtXB*$E&8#L3!)kM_8wYmJ?Y4)1o61F2(wGG%aF{%tpY@ z4sq0ghY}Q{!HF|Nyu^91+)8H7qj5W>gbt=Aum#~!_Ix!gfqZ7HBdY@T;+=9Ux*Ca_ zPIzBUn)6z6*#u@Qe<8HG=&$AZ-EAYgKrYLF`BE7}C{KwqUrm+~mNG=z zmzrcnGLl*z(Qt3^3*Yk%`Z}{2JNRXQG>}@VI2)Jp?-d_1;e_%b$c$Qq4%;EVvQ#!xKvWT^9VzqP`TTTYL) z*--#Nh-ouYUHyfJ?=qYTs!J;r0kkeVdy7Z2NDa;uR0fKI$N&)Q>8gw|T%VcaeTKC% z)C6u6eEYE-PGI1@5(cWJVmL=v(qLLOuxwJX*bQW&n4YG6w`uUfga<PRQzcX?dta!dxOAH7aj;B6+Ja1>JntSyEA-bIZfpXn}m z!5s5!!(5BVaQ{|p#B=WUaeI@~MMTxErPn3+_`~8Q~U$ zpR+srw?!a8PUuQ&O1wJ1%?K#-H~W>7E$tz8Yc>beKCUz--7e1Ews|2~)ucs~c%VR0 z*;77Cg{-e@T__FDaRhTFif!l0)8xTwomR?9hpB9^n>t|0u@5VYaMQJw%q62>vqg-WQV+K;~JeVOgVMT1qeCak$GLZ3fcy2whc zq&GMmyLHzn>3i)<_xT^^=W+7cXNrGw)yGOZjCcvkhp=buyP;m~>F4KNVT;q9gR4A_epu4*y%qiK@&4KJ`lEaN)s=;QY{h2c` zcigQdf4e>EkUHnhk%Dh$UrQSN&s!B|A2qmoE6JQ6wcdEu%80jx_@;EfIjvBiKv^#D>er5~?_fU3 zaY#+2r^4*DgqIu((3?vW^}S~>VQdWwF}dph^+}tzYp>k$B`-x8`csw1P!nBMNXx-Y zXL)E?=>R~DPbBe~dr-}bd9%ykYQZYu3 z8WKgIG`PUq(R>hpNy)zO7e7k+{IJ!lI7(vL`cB%TY;T^(lK<42T<+uJL=CJpIc?j%9xCI!Wxgblql8JZyjx1-{i$;U889}eP?`{XASgs zfW3S!H(qD4^q4wYZ`z7vzC(t4$cCtn`v2yvxctHL8t3_4Lc-6e*7m201bwtfa`Tss zSs7W)(S%6_@wu0i`NW6CHwP(r{>kNz!j;XT<}@4pN+EEnUhW^Sz*ErzQ=o)Cxm-7k zwhF;034Kg*S%6*^XXyR37|s*9!es6vl{BRF_H%bA{aQyxwg@?Ksc_32P1){M?eSDU z?=u4#qU;&KEql7`LwdK#GEj8gXpDvVk5j(s=fwt^dN?_;?sf9>Y|R_;B#EmeZ)cFr zzwLM;n6y2CW2_MEm?}vo{r7yfi4iA^?$-dfV~`gS<;5mjT-c`%s*{0xFF~xqgs%L$ z^7+L++nmNshIUrWDF;mu<2cvN`AhEnrxRD+8D-VQrp^YVeunCXwAs7a0%2)i_QRys zcAgirhbi$MG`&squ0V#&*W;J#jZY-|fcbG#IyhuC%RmciTiQn!iG-LH+4+oz5K4^iBiUxy z({}iWkYHujgdjRE(P{gqxLIOPws0$IsGqgVKKZ@1jcc&AJK-U|w$|v}(9A>PJOfmk zdfe;TO>_rY3C%+A%U=hig3_PmUr<;>K><)70fYl4^P^uDLC+nK@1ef7sT?E($SX>1 z2tSF}95UZHk76EP!2~b^lkh>8blf^=_}RJ7o@b_)6Y184K!zleAdNHRmy5KAnLAEW zD;;D3LRBImK!C!FhzU@F6v{!5ksrK#qcig>a5?9GpRae1dC*ws^HoS1e{#!^n1lc?L;hp(_bBRm%F@^#bIEP1iFm`<*;N^*oQ(gLuD#A5M`NV|b%! zffKlw?eZpx%?YM~4ft$Xu6&RU%^`P4k!fku6j6; z286a+2x515Nyg0z4HE3)NS@=W{ZAvMSpk5qy_-yK8sG;ZCZu{zWJz})h5KWSc>kj8 zC{r2uia;K=oR|<~@iU~@d{9s7WnX-1hfN!g7UoaLu)crX8e=q{3JJLjSF_PWOOC0= z4`KhLtFErlfGA_)1&2A$!?Vw&=Db=2hNdS5dG@gxBm2Gm?=Y$Nt5sF~@ma)R+rJ3x zSkxDR_Yr!UWcFR9qX`+li~6c49U|UuSGd+_?SVt7Sd_ce*ogK>VBW#p5Lsz^Q_h#Y z-@P24Xstt4_qPG>`Zs#>0@rSXhpCN70xP|N!paUo^K{q}7PbHE(n(b%J54AoN6Ynb zsatpMr@tpY&ND-&17jZ4Yk`YLFPdK8d~uU+R1y$;l#vQfTq@C;`da5E}A#nD;e zv*cODn32U1liw&7dz@3J4iGyI#Noz4%Z_iQZ=6TG3jDB2qYQv9hGtk8av+q%=4noZ z<>MKI4n>mEfuub$pD3J6LFJX}_XMuxvm&cIOTU%G5oSZSobKUaJ^G6#3t2 zqs;j{_>@y)!kC6m=S~@?q9JLPR@HZ;F!Hkn`0=VS9YMjO5IgBWF?HKP= zg<3}#tR~mX{TXlD&h{Q%Z`ROlgTi<0WD8bNyA0Gw%m<*dFV}d75D%Bc#Oud_5NAQN zph*W%kU3_=eQ07w(j8o?$$xqdli)Kb4`|;A(Byuxaq+-kJ^PTLe(ftbV;vyU%l_&uI&o>uY!$jNiqe zl0h@gIl1hRhS*j<($*^>!s8(6`|`Z&$BNhwKE9js+zLf?0NyS}6p^VvJKo7ykkaMW z=sFQr{?4wVGq={cwc|=OkPvAFNmq%l4p6?bDaRtj>`($Z_xw!~Bjs@EPzf+>X`JuP zQ0p1DuRmP(USNf>S#6*AjZ6vhL*szpIT1qCF?Ns^x=*4yG*5&V@AXHtv~533yv+D{ zf`Jw^V#ls6%uTpc1*8NmbFa`EC5sy0sITQ4%`j*Q`6%@_W4hMNv{Q(nwDKF?Uv9PT zs_gt^Mq}r>-v(%#S_w5di^AlfN=D?ToLp4`$5J1D7V%eDZCdHtB11JTBG1?BY;hjL zX{Y0F_AxkAtS2j4s7-%Ae0Bd?p5fNWThYMGMMH18IU$P)wHn+W>9I`TY zBGVDt0=}9*mdRyqb$!ip_LS?!U0luk$NCM2&sRA6EqG;OTur68`k`}xFf7GSA#;V5Hqs5F+Sjm z%QO#VQ6I9TZU%<=r_n@se;U`F&Wh=6sY1Kid5M>`oc~ADSB6FTeO=!(4BevAoe}~= z_aM>@N`oNX-8G1UN_R*~OLxNnN`rK#bc1w1|D`p4GT#4d@$Fe zJ&hrK;k0U&NN|z-5hnr0`t07a=z?e#7VNfIf)@lr zESS1)UR1qJVPScK`im}Hor^BdR0Cu}7G7M(N^|U*fW=DTFw0xABJdXUf`v6Ec9rEB zh2mT34(xAlU<=1`@3VJieBus2_m20IqmH*9zkWEgGYhU$sYTWcLEFq#B^T>Gq8u5B z4O}!TiVMh97yZ^SF|Eb1428%_G{ec0K)C~?nLP!3ZAVAr>#lpN-fU zSp9ky2wh<0yvui2V96{UVq2ul1To+u+Mk?Cq(_8WrR>-5fT}Ati<|sHxi8f&`;E( z+WsWud@BXerMOo>wG$5c@QY8OT8Gt**Px3vTk+(^B-Mx%sfqOOBiT<%!C#vP1??{K zq{#dpcCJ4!o0-k5Tvec_**K7^^nBXnd1F;9n;Yk5nCFAwvPTVD)Vcj$_sJ5f=hKj% zE6j1LsHviHtGh3AKk?B&5zD$w6k_BlpjCSZ$ydm|*?fC6aV^iKi4!De{OU?M!#xCF zn{es4fCR~g1Q>j_EEU;>#s7oa6znaqWZ%38Y`GN zEm;UFZ-YEKjYz@WPNOBNJO&LI)3awcQdr(ta-T~L=G1YjouWQP<6n6XEz6n_cPA8O zOrg%aYAU-K@bgRkFzyeNVTzoNCjr;-^diXagswS7o4@1hM7{+fGw(?14~ z3a_+2Y1e)1|riMx#8JzQ1QM1^1#`OT1*vR+|XOyes)IyL7; ziL$X$x_{`jowLfT{YwJo`=?u{N?K#`@q&NAjU9}XxutWG+q=W6U#xxiil%6+#M~hx zO*AwO+E=;k`y+Mqv~i7mwEwT%^KQ)7^`8AWy+l1dT**%)y+bqtb=8zJ>lB+$c!`kh zV~pBM&a|m&cVyR2p$i+ME%cjM4-L-#9?FWRPS#1<<7(vZIu`Oxc6|Th#T@9Hc~1LL ztc8z4l|Ubp>9BTvR4eqkkiN9)Freq-w_nFw4&4OFJP^TN8d4QU<1MtOk!}`pO;8aA z!Sg^lkCT8-wiV_i3ab}}Cejkm6dW3E*vkJF9-KbUnG9_5;JdcgJ=Z2B*1nIQ&Rc~3 zXur9xx#@aIxbEbwQlpQ+C8rOD25h-Q#Xs|iH++uMl(aw!`Z8IhPl3tPlMOyoj6p)M z4nSbM2!o$vz7PdXk>#Sa#O9#<-B+t$Sibe}Hbd!0L-xY@92?u8^j>_3^#`@Rcv)6N zPC}Hkwcp(Ncnw|m-@xQI(oB(~NtOLM8{<_^b0(KL;Q84B{W;b}?Y5@IEF@miQ2aZs zkSyRM320>wpB0pk(Ev+nP9Z=RAg?^OoJgfN55QA*%qyBE&_EdvNu3qWWJw@r@>!NC zlw6~8e$pMgxSl$iC|>PIDYENMMzL73sh$Osn!$D9=0b>zemUfdYdCeFdvF+C>R2`>h(LRTmvp z+}iDYTr4bi@3=Y-yS;(=T}pJ4Y(s4cGiTf%h(?USyk$DSLBNedwf4RRvJIy$(jTK^ zU~n@zSAkQe-ek}^Guy)pn+cAAFE7)j;Qn6I+Zyi6cr@}9ZtzC7B9mhQ%WDHqu$rGW z>k>MJJ_?~C3R+tY=a@YdZ;OXxFU$wb+i?1@QG~obWWVM55W}1iemtmZ+$Pc$3r-uF z1f-kD0dly-QwP|?f~nR`-eaXTdlzdq$pd?ds`rzs*9jMPnTyyN3ODAo5zN9@N7u59 zr_eh44^yjwk&qc)#2btV1#u+7WoXAOMZ^6FF9s?uRacisM}x*Uy7NqzwH1449b?MA z-1$suJEg3LiEv$n+glb5M~W!`jHIX<9LjIUDicY6tLX6+8JWm1`Cf`agKWL&(~G$t z9XkU(=0;so{`qQ>4O=+snPlKy54>ehjvwnUnbceiCmWB;%F3wtY8e!(>;{5ATCRbD z(e3OIC>{I|5j0Uig7X+WY&!UrR4XIjxa`8u*ma2R4rP1DmxNqjaF7nOpM@yD1Zosa4OM9DE7wJ)4 z(`Ni&(ImG;E!UpW@4knU0P%)8`E(gv)~Av0LG&ZE80V=^^SG(aq7%H8Xg5}B zxH!!+!mh)de81A^;>G_OWEUw@VflEiW6Z*X-^jr{NZv0hFn}jC<~%s3)#qqLkKz+} z><%Lfq(;L4xeD!Iya`5$9z%bc>)RkK1Rf6q!XcD^AcO?`c@u25%aD_qS}byMpy8RO zg0a6Bliw6SSf<)nJ%3}aT7D?Q<6DNa-F?>R!ol@&k_<7r?(%ocDlyIznoTuuJ26XL7;!k$;Pjixdag<`9dHNE0=93>e-b7S4qQ}G1{J-|BBKCS@*;)#9X(wj`NSY$ zV1>RrQwmg+Hu3u#n|r}yk=faDYEhp&r3?UlF*}(Ow^hHnKDy{WrkTSAA*&H0yUURh z@zl}QQ=uJ1i9{s2a;NxcS@EV^=cncv(M)m1d#BG38TSbHwcW*=okWBdD$3xyGH1av zAGL77@*cp|)nAL_lf3-}!sO?WPAa(76B;J)`|585jc~*`>>X*apGUf#TT;^vovBa>_~FIVS+%y zU@p6kBAWA=ix|8y@ORwY%B65w5n^N z9NYmyj{p6E8Y2-4HOImV7rr`!ch7w(2nf( zbI`4uW~%n3^@m~X&*BQE2fwYlNAu?eS$R?iv7$QFm1dt>xBz%9_C%moZ5JjQgc0EMk(VER zY|3wQoy{G(GOHmlQq&6YX%wiwN0SVNjL?r1o`P>eH2&UYwBYa$$EMEWq9CFxsupK9?e`*vu6y|4hWZN_+oe^k&COm&W z4}AIpufvEE0n5u~=}`cpZ5{DNxyxkbfqb+GD&Tm|K+DFx@7-p^QId~gvqt8ytQZh6 zxBJ==#>-963bL8t;xsn3)N9IBA9Hmp%JRYDh~yRL(El)W zkZb?D?FwQ&Q1SNf4uZWE1a8#cKZA3kQ1noD;HUc`N1DK6K%!nLuE@4QAA~dnCMeIr z#w4(NuseX&;_PLF$e#{1(~fdrF<55zMc>VnC|7|CW2q}Pq}g)3U${61=StT z-B_xX)=?vvh+UKi9gFs0Vs^sAy-mnb+@-i~G_Ck!$lB=6acGU>WzY+fL*VuCm8v_9 z+A}lDpMggOB@F~FUVo4??S(4#$yM+0N3Ol#p>9-`qWIZ@x}%nIlU%}7bY~TF zin}vkDc|+=yqK}ovcPN)YZ>j>2>v(wJS`ytE&?R@2ex>;{S2f5qFz>6Q)%wihs0UK za22$l%vRj!a5fa^+%!IOmP$Ix8QHo^lLCwx&tZ3{7wtY-ZD>Jwv=o9B{LbzG%t^w_ zrireC6+v~bIb<)^>C@9^a=(9KGUsLfi)**kdj~V7l>BvpS-2ATwPPf5V6q!z0VH=r zd3M801R^0W^`1bf*ymj&Rg-uQF)deR0EeO=gqQ&-aD>zI2~DdZ3p2}h2i@sH6*v{K zzY>Pr2u&xqF@;asVE@P`s9V-Z9V%2jR`dC%jnFENkJcMbo2w@|eS^ePBJn9v29;Bz z&-=t~qRpn;DU_jqWP?VqSJshJCP1D*Yyf)e!xw4b0-gLZceuf5%>RbN$Db_62-x7d zvAPbP-kXCd;r)b4=KlUMw1)+{FLCnKYuY=D>%?_eSLB<@>Qd3wmrm)9f~wV=AV<2U zSXH@8&t?yvR+c$WcdU7_pN8~2k1Oh#S0DJ@KF8EJRQ_xeg!3EZgbt?>QiX!A!bF6? zkqBN|0wItvPIPL{w+FLkcWQX25fDR9;QqMB1+TkX#hH+elr%8{_;GC13XI*0yxwy1fp*)qC@SOXMn;*IH zeeu}+@#0uHo8b2YGJib8Hi>WKS6LcsJXn!sMwH#J;KOHb5Io71^~>F*>K?@()ip&>kz|$@^WXFv%ckqWXcZhK>27irAY8EN+LrLl`j=V(Me=*Av6aHr6HZdL8OKq!X=J_HyxRJ_HC zse`H|7{*G5?(9_EO1YNkRp8=9PT=oHsNsU(PgFtS7niP$D_H?rBopaB61Ln@j05T% zs28%(xAQ&B)zgAL5=p*lO30293AtVyv!8qOYi*arNLGi~H+(5kNwpwXOM(u?{x;{3 zR1i>!gvAmTqM^g1xV>YKLZ|(i=qs*p1H}1K<;MQE_r$*C7BbYwIZ3g6vrzyda3~47Q6}C$Smyw*2!-P z*~D7%j}KEZlTpd&@PF?WVbBjJVB%`c6t>~v!gM0;osKkI7Z@^Ed41W2o%TNKIv&5u zkp)c5T(Yoq=)7nUv?JNza{?}btUPf>eUVAR?P0kaD?_HjCCRhdlK0&X>m}&2-SJ|B z21+4I`3bR#dD%ZqZaOBZ+jEogcZ5>WUq>$A#RlX%XX51V$!vnQZ!Pb(j-OBjy^zUb zrGT3Zo)Nmc{HtJUCEL+lVje3>MAMSU>Lpa8OuUwkLrEY`#ANM>hLb&_*_TqyNUNRh z+;raG(|v1po9>XVW)#!*g>V&f3|oEYwpAtXm-O%E2=SW^Cmd<7j-y|}c=Hr&8K_elK4n#S6m8RS*nzRy zVXg|BAkX@0B@T~#D_aa%fn-_2uGtrrFDpwE8es z#Qv;f2!aznBDlB0CRTw-T zg~So#f%q+Gk%(-Jv=hmg>(fcDJ)E{D5M~;zZB!Bu@OOFmF2o6gCKc)L0wuGJl!$?J z4LQflM9``7X#;q;<)-=a#5Z$&*Ct1mnDA3B6{P z9A*nS*Pm9jI5&mz^5$mZXc;H?Q6U)M2hu96;K>yrcjETqEf9AjaMD>o5u_W&;Qsfm zFsYj5(KAvs<8))56PhkUI1vFZYT@?^r3x+_I48Qy03<;`dYM43&+dSB=9_Y#PrB2H zkYc-x&N?~xdNdr$_JnLr!^I$Vl2#?9W#N?TU2oSO#s-(f#_?S>ugRj~*lngnQU`51 zN>&`yj|%8;$zXu|=l}sryC_#Z@Yu7S)275Agsw0tLBs%UIBI-8A+=>kV}BZ z1+6B0TOYhj`P2s$>l7ur4WK649qKDyOx@XTjPWE8ljlWbpRgH5R2GDY;URHFwK(tG zFS7}FPX+&=zEXahL8K!}O}d&tN1D8$1f0&;m7v|tIh~t z*4PiDq(RASmXuEHKyP?E(2*qI3=AK~{Je>}tr_VJjD~)sV+OiVx=vAeOVvZss~Y1) zt2vobur1|%DjjIUR{{2CHS@L|(RwIisV2DN=f}=O{mAoDw^i><;b{KT*>EM7%fbBD z%VK(-A>X?GmIsGlR&w~9f}rI8&=%@H))D)maeADPg*@o#CitwgFy2w;Sk07$W{wT$ ze%A`dK{xhY=?wi?@eU^04egLgC;5CwdG9?tqEDZG!`E>Z)1*{UxuUl2{`5P`r^%|S zMBS=6eohsFerZ)bnO6q7*)QXD+0XbnTJRDk-^B{wv#8w@UCKW$88(Tk3Fx@2sY243 zAxO~o#3iRCmFH=Y!0r^n^_#n|vAuO<(Dw{rh*}7x8`;DOck210q%W$KPcRwJ zJkZVxB`4V_%6PCh%lSl#8rr;-s8WD;kC4fc%Tg-#@eg&cMFu-0NAnF1*Hj7a;=ZTN z>Em~F%M#Mcd9gn}GR-FDd2i64o}4wz|%$G{rx8*`$d3M`l~{%r?iR=&HQ4F*aV6eYwWnqwN3s z_D3MB>bE%4;*E2b6@*rM1|NZh9)ldm8cftd3_^hPC;|t@D59s!Th5G(eNrnW_|L)@ z3D7orWMWRV*M41tu5z88j<99PP@jUKwbv|ErB4d`WClQ|1@|d~`d+zqx^8tP%_}^y zZGU}=Mx&l?o_qn5bydF2i~iQrP3ozipWAQNd6NLB}hqBdH|T*qq?2vK1n(x=AuW=Y9m{0bo|uY79p${ z7-Upc>#{)$$kGUZMbn`SBD1f2zyHp3mxjiOp6_b&zLJf>x7(L-zE;zvTHow3t-c@6 z9WC+VQt<#AU$L%MISD8AG-MLfJkEV^^d$ZnRhVsklNuhI!;LVh~1Is4{HTR+tzN~%)eDi8z zwTOvj^ZK(ZT97!JK!@Kvqo+Syf7owjL?3zRGkanYvPVf7Z=)2Zn8A9vq8Y$HE`?D3 z%PI_Zsl!7tM$g=zVM5Vc7yLxy0y$$YT?BvP5~bjpd3mmwq_8L?plDd9xVyXS1~yLL zet?Y?K7UN{ml_K=n9kkY42*7Z2o?DQ`53|KzE&@*Y{Et?8X}2ID+-C$~ft<}R5jSX- zFi^8@k^wcN_)6e@&(<>nGf{!pJ@{5@cuqxVcn)G&_g>220cr3iC7CU(2?ZuiHgY`? z^GnPm`Gcf(X1*|DMXCo3_T^PItJyWP(q)WUH?obGpVnWu$$6W#J?$M9X`3QqaZKn| zoZhZL1ckr};s2K5=h@;A371|`GJNt`9lo%Nk2>?`_?Z5+6gb#0R+me5_vO{ciQ>^x z?XKmK5rR)X8|UZe&|-0VL;Lc9VZZ8@fZ_AlrqyB%-=$x%-6Wk^&mq3(!G?o}zew%% z6vf!-`c0P9Ub<5yntN9Y&x)G7W_AAl|9b(5iZaEAo)!-!ZI+UoO^vH=m-g*af!g?- zF!BZxzWiI9_q!IY|3aomY44vLH+ic3KT(-8&dcAa2@`T;_K%IT;gRf(ffrr}Poz8sNgEI}?dW!~Op&2^Op>FXTidLgY#5%p& zG<%WeBT3~QS8gqz(GI(!-Pnjcm_sl|1B1#V`+&}m$-Cb)YGgQLkO@&I9q(PpPc(Sk0b z#%~WQV?8eu?w)ge40%>tzbBP0zP9Vs;pWc9?W-rj(R3`h_ zq!J0Ik0yacife21ykog`kNP?|K6KL~GHNGhd0aH9YIv2>dEA<)oimU2{dUg7L{o+g z!$q&TiDwsrGchfHSygS`RU$B;-V|Qpd|VK_c%O=>XK}-R9r`q2=5Ib0hil}mrsWlF zTNf=>oKSd3X+VCcxz22NOnb83UddL6ec{0jr@N{I6D4khhU?EiR(t^02O{H2Grlwt z@Hn#3k9EeO-qkfFNH)t4vgBoIg1O`+kS_Tch^(4ha*F9aaU>U#h!7JD0TYbS8~cKg z!HtrvcVg!l-X@*u{$#aD?4W9Ift=xS^|yje$K5OMG$H~^xl%mm{`HbkBqLOQN`2rb z7wQUnMFF}6ZU1dw@(pAY)2}Z))m&SA#QLIXj#O~aY5d->k=vK2({m9bVP8NDy_+l| z;GXHg3*(#R`-=zEOsW^3x~Vz*(UAJ4D|iJ17KQl%d-ru+y?bA(G_k@>`=g4DieM>H z#qf3O7Avh|jL_r47kp)9C6#jR#Qp`jA&JuWB;GpvlA(LAKEL5-o0SdZr1bTWPA3z` zU!nQK|3oPCuR3v0 zc8=?Zh6HE37ojE%qP&D-5v!bB;|7ZAqe@CdH1zAU%Qvk z34-@(<)fl>q?mp?K3oiB)ri-x{%Yh7ImTKs@oURY4&&cvvBvwe*s!kOZ^3EUFg$-v z)0{yEn`mNcFEx*$ceH}ap)K)1!0`XdCyaPY>f z^Pc|YjgKLI-6%&9@P>+7UhiCX$NLXqAM0~!uN%p-LTStG zDxV9aUxvoL8@=|KW2s(a=q`6t5^Oi^Q8Cv+OBcQ4cpg60o=y&51%?S%)Fe+!EM{Bn zi$zc8_`T02_RJrjWyYUz%YNM-(fmH=bvv_5@9;te&z=9#>rZw}J#?6~f28uIoGC>* zH>Vh9I;S|>;wX1f%sns@_FX8ABIqkD%O(U^fxLlyH^M}!Fa%ymI(7MoZ~u1B3=!@i ztNjw!ZRg3Wp}-}M4JyJ7Q%(T?{iTGNAUe%9ESm6WaupsxX(RVrmxf%$ry!U7TdsMZ zVXW^}RIDrtDaWRbw~O-*mXw3Gie6o5(ga)uYvKz?SnWHePs+_#I`Np!K#Cx18JZ$I zSZxb5|N7!~hbRKEV9MY=*38hpOH9`k6{t%zJfe#1L{t>^Xka$1ZrbKY!ezTpJCEQM z2IPtB zZPBt)r){y=U-Z_E=xlY2)9Ho)CIt7+VEqp!8c7S`lqE?9-(0t$`R}{0Wp*)=xIg*B zWk>O(q6=(531m#2948u-yY2RToZ_YCYqagsZ7;l* zNRR*GP$xg3PjjxAyQcmv8g=WtkcsO)Hu0q!PNEhwv#$2KiJB2JgHKb?9XuF>x9KrK zu$F~;#aEg#$eG^hPqTESusk!$Zf=_t8KdM5*TT%jcsvj38dET5(PN8<~rXj}xaZ^1V+yxV}$O1f*TIwCv9d|SS@Ap%AoDqVrF!6^&orpqw(iJNKrKy3q> zsyoVGE|iHGtspn>%$y}Y+#QT{;*&C|!#OYD7;9J^l@N3pC|{T6TIxpWA3ia)=ljeT z6_HsPlE87$^}|F>s}j0@9nBo?ZD3$%XSDc?AX3R@TE%*=26>)Q7;>L(V>JPSXGhWF)S0FtyfeQlQr6?C z02nF&WzhRm&8^>3mey-rAG);5bx<` ztz+1$$f^KEs_xeYK3?MN=o96v@2OyqbwjaZdwD2oQ(we1f6>8d;Wnf$Dn0^e)RJca zmr-RPMR_tkmo>)rmRF8?Uqd7piKX3b^Zsi>KUw40&tjl;CqR$^$cdVg@I@!-DF{8k z4X)yfOFCdqW40~3E176JVv^tM?-niKJMPPOlrpt7Hy}Fy94aFeugmoJ!+xc+OT0CX zL{l4U-f1lQ(QT=l!;+Wr5&aQ}1m$x=in|vc>iDTYapr2k`$Yvt z@w&}*GWuZrBG<$*^JJfE6-*h}>)S=bVm8fK9HE>xsdksgDPmW!j%Qi1`%X{Bex7f5aok%R^2(&7+@$R z!B9RVq;+BRC{5aQ=OfRV>S=ttGMeGk5-HgmYHYqO&mMYRh;B*d9^ciHO+kf?4m+J- zJv;SuNZ@UIn#}p8S6Egw;&h!R>oQ6TxC>=0_$#R#w+%p&2*fsp7M%xufmdb*8M+v0 z=O%`0fQ+bJAJ2YsjXwFdxM6#p-1nHnXh%pH~Br_8564qo^M(PZk3-FeP zcGZjJV*!oRqVnA*)EpQf8BZt+dwo1bl7;(co~*K&9j61N^0RM4I&lz}lUsQ5`E>yU zT~^mn1)l-hXNjhJbcWs7e=5+5_ko7ezOvkeL^qp$BL=&ezDCau`=h@wJd*N}z~{1v zP$M9ttUmMo_Y+xF;Lpl7Y8DSn7U<55gz?HEKe45a`Pvfy>`6$y{GvbrJD*~d@UgB5 zna;pL?I%a@Cb_9E2YYwMpJ=b-6zB!S>w?=la9?sqe(wfWisB1kwf2U_uYbjog&mQH z0NcPDFMCC8PHR`-tD$mPaWS?%gjv?ug5K$u#8Xc-bxFHXVeL7{8tx?!S>kg}~SC~T{Qu`WHrIBEn75BgVGsKs;iH+m3 z4Ny4DM|Au1zE+no#EtefkKz@tSEzB7`d-v;p>J$Zu31GeLInr{!d+|8fp4l_zP8oJ z#e}RWfg#u45FHf;l1;IUrbVa{QpX=T~?j(WTbyrS^zqC02wRlL<47M-BLwUKH5)5=^8mm*#&)iQ5QT%V?kd+6Em zJ@l$>Ag|86t&E`XE0vkiM))7$RX^BcW<$`Iqc&1S=D9b^W*@?OIQ-V}io)7-D!vr{ zCxQ!tr&e+V0Fde9iibF$jXhyPM42xAE=Pu^d0WT(q7%P=h2xQ>)=`J)`rM~7r;YL} zpmFHDN{->k!FDQrFaQr8g3LU`E}?M! zC9$aw7XkXb0$LIyVG}688oDL$TE$9G0MS3&0g~VA`FIm4V#v?iE+091bjWWW$QrC~ zG`7aKrL$zgJLeZ1&XhwpIG~Uadw@|njM7`b`*ToYi4%7*J;o8<2)v*KXY>4|OV<_$ zqoAPNC!=TaP3j^uCzYbm1fM)FoO4|l^ehd>=;;B%&r(3QYUX?|M(0WnI{bAgutS4G z`C3>I6x>=>S*vZs*`%T(Xj7E?a6b?`SKWMUZE|M)-0$m$4!j7rH+nmnGg2kN1g*|B zILBPo2`OdnV+j!&&6ZK@3-z)$H3Ft`FIGD-1DQ|?NSa7CJ2BbNdQb*X_zs zGpBKxzCCTioduuJkDi>)zDsA(?ylm){^kxZ3;o^L6&Y zr9s8kkKDf=D4+QoqTejAHl^lhmB|QzcS-q@ES(@oKrIcZ0H0k^X4n9+P#~+z6M}^& z6>)ZU(SOm}3cW2Q?!O~{RDf=$`yXQV9V}#1V~lpX-TD7?I(?=b85g9`mpA6c{#Qp6 z5Hs^-U#gkYO$$5|D!Q+Br}ys>8VpvG1*W&+aUe!MJB(+1Cx;(+GQzRBYLyi5VOL%$ zil4u~xF=E5E_9nka-P^vFauRsB`pYt&^TpfKVQasCkWlla)6ue-8KGB``vx4evO=l zRgOuS2RD|iV_0kV_17)^&s7{rJt5Zd=Q?R+GU>6`w;tI17!$Y~vOa(x9~`y1YK@WX zTg!ZcKPcZrejl`w6EZ-vVtxM{Xo3EFEaU{iPGDmKsT>Sh;G+=`J;dXCVQ0PA_Eyic zAn%@Iy1%IUd2j5pziO4L!&Etg%_j7l@WsZH^q&tOzr?GjkEB#o^$|-?mnS?BXTF4hi=bGVKpzc5{X68H z0Sqc{uZ|td4DbBvf`Wqjq9SXp8@~Q;J?OQ`{NG!clgs*~DN%YG2wmv-@8vfMGt}=olWtEft-F;T zVZsKVATAH)r}HO2qC{UErXnq6e(PhxJk{D_)zd`Bk0(euI1*t(V@!#(m@P2V+ywyX za5Q(Y4Yxp6f$Y>YufkTdW8z%-UGv1t6wcbFSP^8B=!enjg=jK*g=hWQ@`>Wk!e!I? zI69M<4=2LpjywODU=gk1va*M2zP#Wg3WAie1av@X=G&8E2bi6ZEW6wNT^3IVeC8`piCbOdhxp}F2Zf$~OZ^?_W1gM9fRV8^QqGuC>- zQ?SmBG$7|AXJU+AC}wte_(Two+Hc-|9h8Q0slS(t^tE#+fMSp#NQjhRHjR}i2x%Ry zGi>%S`Av!knrRMG2z4UAoO-3AEMuzAaJEDz>tj|bBzkRsXFe_20d?`$#fJ}Er7 z!s*apXQoLv!>~~!qy4bGFY=o>bL04u4ha@aWVlV42}NXHYodNKdKjf}ewSxe+%CQ_ zXIQ15@!Vn}7hpU`h*ZG#D}YeYj0j*!6A^{G6LJ^kPJT(roX*Di?vb?Uend7;i)U<2gd&-^_axRLJY1 zd8y^01Vz0sjr_fjIcDI7e0o`>;UQ0mP)tNeQQ(4SPH5W;g`ZGsuLE6&2Zp^ChirwQ8u`>cY9E(UNJb<-VLS^~$t0~wU zC@j`AryZG_Ytpxcto;r|6a3sl!?=El7}rR7R;LQ%h8LALKR(=g?kE7u*jdn{yyCK^aNK;2j80FG2&t<8TX9>?Wd0Z>FeQO!<%>d~T3=u9 z>EY?=%L%Bv9%2l_AjWs3$d~78p78_!(wn510K>?7eNWFt*I`DD(_ev!O}3A(p~`cT zUx$q%AA4Fqb$@Z3=+r%}a+5fNpJk)N2Be};eL1^zTd2i5Ft!zV+@?QLr_?>-koU|= zd4I6wZTl0;3sEZ(fCB~R+1ArXpcS-qQE{C+tAEjt6}>N(B2rk1zr|r*~Vt-6eGt>pF&O`l9VHT$!t$(c_CvNuyp?SC|4D2RU$uTqMyPbDNlLbUy zfQX*@DpFo@5EE3tT_3%*L-&jrF9RAM)6KXyij_E10YqY)*5HyjDLc z)4!l{MjlVn2tfZnn+WJ~Oa~2PBQN!d?K#qP@JqIDT-#3#t^MqGtdM`>IzMYX1s?F@ zVhBad++`i~sp7ffe5V|}&ueKh~kGNSzI8;x8Ru&n{ z3x%V!QX0y_MZ@;zECv6Ou`@(Ndn9jlYF)-&ORrE)BgwG}<>a|8vhq5DT2UY-u!5*v(Y&u6%GY)u_OFZjwyp~Qsa4X&-$6tu`BM!E)^cI z0~z_)BIDl3h`}W}K09W0zQDWdlmxgbp?|b2gx!+SM@C;X%2Fk!1<;YqHd4bcAwXe2 zO}g1b>eSCNV1<(7ZHLR>c;Ntz@z@pMBcMm>+`mGap4Zr1T}>p=|G$+GLX58nS8(9t zpwHx3pD9o%3Wg9lhn%M;IT zZ|wPv(3ZkIcTX|ncA{Ik3f7TTlIR6ChUJ^e#t$E4=+`F&bRrJrM_lh*`lvix%#Lw` zSB=6(@h;E$q*rREjePIw<{fSW&)N4u@cGbeOY%+;s{T0rzAhGj(SSXZG>2Dspu%5Z zhwhRHashDxTFbx4)RSzM4PlmZ=*bqeqi`?K%Lsme+G|w~%c<+P6yWPGzLcO5*`j`N z9eCS@({dRctKU>p;m@T6URHWN^k2dpHSqPi?xLshy)FGOV+{ByD0%XFg5GH>-Loyr zQaTWyEVUt+W~uMPo2y#krMKUV)K5k%OAGsPwb9^_XbdIo2n)VJa`IwL9)t4c^2A3Rs+XY_laB*-(I z;#rk*@0V-_LEskxvW?T*<+Zrf>RazPTeZ=+F_835W8ZjM1dPm40ubW~>#J29qyy62 zWt-#t@^T<6#LYC$PV`hXo!p31QMEy}>Tyq{&orJyIqJR4^7E%Zol{elznNJri~r7IZWUja&x3k9NKV1#(uQ1$ z8Yu>1#ncD@Z=pK9g)hnomY$++?lOP6b)#EJy;d~ao|i~SEiTszE-%+=Ng(-Zpk?4< zGhoptev(Xu)g1eE6SxwE(*Y_$dOeTYJJuDbTz=e3P?rfrH!X8WEEHmVZ$*xNOtS)z^H zi(lYEug=?vI}**dF=3i)e)>hMbZxCPR?Md>k<;c=)YP$ay47Yd%4oYIq`m?d{^b7R z=}LRt7dStYw#{`l@3G2>%AXp3JR$Y?cq%x78C%y%aF!HBc3V!4>1lrg8}($vKh`4% zHhl$z@b7L;mj%od{VVY}q>wX|Ikj*%LZI2R)V=dBHG8-hiPf!>gD&2ah_?Z3$yAU{!(@c?Pd1go^ zPusM*!jJe;37YHi=B`~4<(iBV#*P`G3DPa0 zs3EL=1Uw#xN-UgrQ9m3@ocSeB^;HHQf`AlHm#ahNw?j;uqE~E8G3?vU&S&77yG?<1 zZ>7dSVwx|WGkg0OZve0xVCM+b6V!>IR}ll5&oU$|Bi)W>Uj7z4`Pkw$9+k$PY1w~RT7xRvRu;1Ni%!n=Am2`T1 zwzo>uo8PpA{sGZ&fsf9jP#mS=<$A~E#LJc~u`NpP^_YQ}(f>u4N;()byhk!b3V6>6 zxRK-(h!;5X;#;yUw;N}>aY*P!8u)yi5Uo-OahpcON1oeih_03{@GunF&zlXSJ4DZ| zMRBqVQ5=FW_K4nnwq*u_?x}BQdfI->18XX)AzfFY)sNY19?X12RWJJRfN1kjvIy~X zz<@XeG`IP}FyMMa90#cRM~qgGje%EDM}g3^?o98oU4~q@_r`5yMpZ}`1BWgv2eyTx z&$LJ1;co1kD|r(N49ySY#zI*EzFCL+JdD0$ebB;Yfwl$HiH7}LV9)gzbwsHa;OsqD`kn%n9*y5y=-+mzbTda zpLLFJ!2Qcx=yW-H%9JW*#l(d$?yhK=@b{_bDzUGM$puJy&`Jaf+T%&EQ4uCw=kHk(^I)gB*XVwfntYYTt-oUC>Lh9XRh zB1d|9im%Y+^+DXf886efwN_kZG$;yrZNgHM45$x7h`YyzZZPB{x;;D zjx&|oV!`|aGvC?XL=D#GH6Qb;_ZnltDj_=s28c{1yt2@;SM)ne9mfNW`J%7G2kl3h zZQaaW5@(Q`31f9)-kMZu3nM#jaD89OW>!>u`tsrGFI#RChV&mgdAlPccAzIi$#^dBCj13L3yRPZQS6}B z?(g|1gg0^Ld;Ogx{pSXdnkayO-9DGONt1tt zQ9}h{dYiYN->f*8cbk9CEWnwkQ0>S(wHl{n?yIi`dv`86!o?s}|aYPyRP;?^`36LIBc!+g2`!( zcKYE_zWSHNxHCq$W^!+skK)tt&G$c93~L~yVP@bG5Z1XMjpI&oMpFUusbfs+-FIL_ zp-+*mXGZxNGA!S@_FRZsFpsWM`4L;Cqkk%FaIf7&9&I6NuK%kcGyw&jV(Hp8I zfg7BcG-@NR_e)RJ-88=zZ4WIO<*J7?pnV_>R9qM`_6QryL2jGkqLOQi-l+Yn-wY=1 z5Zrj}XuhXtHT$((-Z&P6$4BO=sHrJ8QmHal7Z+ovvl0aw+HGE@_3bvxF8|=-_|fd^ zybhVxdDm4tk=3#Vx#-y+=}o(-dy@ zH0nbv32B;K1Fs#rPPdo)UGT4hm~R(SL%2jX+k{d)Hq30iHWSE~f6HHLr(xy;f~hKy zMJ!8)AUJE4afe6RXrUuZkFZh~zZ!e4>R-!BEAxgq+VnC;KoH4#de;fQ-i9Y ziGnq*uwMSu^^~pVwp3P+2|6R}V;dXM$D~D-c$E|Q&b1&(%0`6QsTeEWD-9ptfjGXx zZKgL0kna1VpB5GRL=4Iub`nOnGU;6MpZz52Cs?5+TXu}Hux_7cPN?Z6O7HccQQ3ph z_xs*x?UXw%CKEb>6t|97^$Lpjiy%u#n8!ql_&N?x?PPd*oWrEVJqjirPADVe377z1 zo2gId!HCSv%oytiobj_~o9E(ZeyMFS{57V&iCm4rzEkgMlHeR(&EpyvmGQ0{qE%N> zNAP8@i>^_)`JbB?O~k60rQX{`K1}j?!U3yMH#Y85Qji^$9=*1fnVg&qEYVX!V}@fw#Lw_tV#stp~iHmQ#t(FKpS#D##zz z7PdZ?N0FFzPZSbM`IZe*1(W0PSo=zLY&ssRpA@P$Q@n4Od!k&kLse&xz)6nptxOEh?^SGQ|%Dvl7;tCR?_-eZ+wiDXc-+_KVV(mZnKHWMVWRO-1Qr!+;^(V$pr zv$XpS-lV&{H5y_2F_eHRPSbSMJc}}Fe4{vh_+uBV*CcBSR!@Rdv9&Q{j)+xSf`%&U zk&9Tzi_UN;JU?hfusg1r0ykg1sxRuTo>f@O1KYUI&CSiZ-QGbGIqvS=0Ng8q)#x;^ zUWTlH$W|#%nI+*@QJBpXGNErvHlhpSr-^BQ0BKHJ7oDLwcH}%qYn`F@hq9_89L|gs z-X;Qk(t(gNWj-NF0kQ@+)86{f=uU~V zNKm1M41>cG=rxZ;-qP1O59^{eCKx7K1!lvh)G5s%jD=%l(k@wo#HULAZE1TmCR;DlNl|IK zyD}ozLyL|1O-J{SDtvf}b1Gw`o;)wdAj7Usj>%A^F!?14%+wLuxoqET3r2_yO%SXx zZ8j3(c(-Kzi)HVp`^Dy+Z)J)1Is(pi{4!yLBkWo3RX8m-w}@0M9jWp?!jSK7zBM3% zlssTT7@$ZU5Xk08Z>NK0T`VfkXjqoGj|m@Tq_Sqb9R3CJ9CJnsYqI3N)u}=*^%5Po z{|#GkjC2S}T$o(UO0;jDUhK zSWG~f9}eX^`2)~*%%c?#vxaQ_P%(RMF)o}}xzQZG*XrHdB8nnhKQj4yfT{K@Wx$Hz zh4*3d7~j-YcEFo>vAH=7)c8#>QP9hCKIc$q#46`r&wdQX7+S9&q7l)?;lbH(&h~&V zkNZ+V(Bsy436OSvjOyJl%`zNeDvZl!r|dw_$Gymy_EzM1mx=E_Yh78*Ku6W7WJAXFoS}vpv&B0I($a7 zeC}<;T%ffJvb~3y1Ig|t4Jo09$o4}9p|TX&+1Bv@|E$Hr6j#oMd9X8?exf(uQ@UOr zHZ@$>u87xv1Trgtwg7XYhf7)wZY@!=>Dxx-JVh+U+*=nP*Ct$7(HTyB{5Io~GlPuhK&!iRxVQvRbbIl)1yk0+-S z#vn!#+Y%=&?PUGnfpB0W7t;h4V9#}qw;lqkCn~;SC)GVu(13_gy5<+?<_KGn-)I!% zY*W}B-i&Pez449Rm^*?8&xlrIClj2P2YYfP#&waFYdM`NH&PTJE?I(g#iV&=bNlTs zHG7CHo5gsOt69zu=`RY5c1uV4_pMhXvl};VkO-UYD4OfPGzSnTe8spY`wo+#ebaH? z9#6fF+G}KrJ*}q}-kyk$BD2D!rIGFGthjU}) zK=ZDC&bd3p04g@~yac;XI2A5vI19xV!JJtp zRB3X&vGmF=jZ2|h##p=(l4N)K7x^EjQIm(^M3J}_Bf?%Eili*efg!R-72hD1O)$|b zP6AZg_wov>UWTS>6t>d8T~9cwZ{$DDvXF8?l*VTbWY013vbVoAQ8ogLZvuZfh!R zH{Q`P*giM%YTLE-0ES7qtyfW|f?z>-N$mr)0Sm0M32$?J@t(yAu&pY3JBE}X+f$7p z4ri3jXy*&XGYT#tl$3CTJvv67hO$ZZPBFhMbJDONpBezk5i)*%{d2(Iy_wR>eiB&m zovD(RlpG|x*TGTrjscVB$qP0;n{QSi<5aQd7bbZ52#O}KiQfV z3_9XSj2&Dc7dhdS(g(tOy}#W5u1o4&tL>=eufcQJ*;0k^bPoo3U5%E5P+KEq>bbvQ zHUf~xNE2emw8-OrOo|SG#LByDGzszMj2)CF)tpk8`PDcAJ~%iiIcDD?Y*fA7t4GeN zU*|FS#NW1to~!Mz?NGjoNDSoVx@B8M}O~h1Pk`NsMmVBWnR@z9vfo7Y6TwZFX* z@69%m{)R2gfJjYvIn7 zm>eW|7fEK@;}2=MGB zkaW07Dl6iCw1Dr@BWCY)dyrV6j_NamIH{v^+)vqtL6I9~pUH3ZF_1v5g#Fr5y}v?R zKQ6R;d~E)Ou-d|~k&%%h(zX$Kn;IaU6mq1qvp`4mP$2KBio+&4wc)7eobm9RAYm_i z^%q^rwMNnZYlAxK>@X|wVCan^-#z@O!UR92Zy{&E!ux`9N8>OIAWe#NhgK-PO z*9SjdQfXi`(=~Hd1>s4z>0!O^zaOi(&O&qU?b9TPEDU&(3nFSY2X^2cEZ&Sr^DUZg z9&2UT>*k+UH;NF!+iwerH*9vBBNz9p~O~u}K3XI|;{;e=%NS%Y}Td zZvMgCOAWsW=`e*a*>4?eqd1WQEVULt9!BY#GSk@ks&UiHJ+J3=V|N1Q9475$(~a#s zKAs$!`?fuspW8{%ktX;3hYw$sF+cYbLV)>R@sl2kCs^dik10GH?Cb~()v8z#)?zNi zP8K4**Sm&>dOuL%y3E6Y*Aki98DoK)*IhltbLxfn_XBo>FEtO!Sc1+`cdlJvaGNt< zVlfkiU?h`pT8|R~4T+5%!BWGvweO_HJT?!P$3i3z+5beC)Jf)!b)s;2^E_!^t#Bp+ z8c}mX@m@W3Z3Oo%Wk04`1{0=man7txAr&5YCEHOxzmsek-$WfW()osr~+-+HSf=Rkh^mr(XLgZuhIbZ!m%^z_zjKQNxxPY z9q3)MvO5O28`Fqg12+?aFsp>TRk}8k{mPgVepuPXhk?@NMI#% zRW-gdLu@rn0Mas?cMSEzv`2VLCqZrJF8T3hmEs~9nZDdscJ}lnzICozG{{=ayu>y? zb98oJPO{Nf;G+7)jZYkgj&wX7s@fgJmst-MZUAnyeL=Pj^#JQHwzth;><_j}W79x( zX`-tu*T#87kTiqb-+dj5A2#BJ`?uaw01U$gDTE3X;IM^KY zwW0Eu!>XXMKJRKuhplqS)kG7#SeN+LHBqO;6IU$8dueOF3}Y!?(F#Bo#J%8`xN_(P z89pZla^j5pzow4Fejr%Jn_oLNv{_w~}dGr47xWq|YMO3!CRhnKH? zql^7;+xF>=8+5&slNa}?o6nm7grVL#cYmB25O+Cwfw?|u51JgdM_FAgTDkUZB{x^( z)74AqFa~OPrO=x7H@QG6#ZWXBU8d*PZW2e`Feu%1Klv)t`JE2Idk0JtX4cO$=Lcqo zE+xN%!|d)|Qc=K6iS_ewSkJLUTp(TZOO}@pJTKj1=IU~7+(&TBvc~^gk;s|EzK#wt z6_kebDiH3BvPoZGs;jGqXv(kGy}r;UZSqomG~eB_ zU?}Fe<$8R9rSBQ#FC%Yx{>Nr>5VQ6xUJj0L z=f-a)Kb8E*x=h`Dbr)lXaPD60>&4aN8dU5#s8kuMuXb(mFc>^pllYQVQCwVnyJ2Cd zC}8a4^p>E(qOXiH`{}w0c#f<5ZI@9NY;~vkmY4TUs!r(!ySY!v=Vg-37U5b{vv!iX z3oIr~3c%s#uouQbas*>4U`&oP<(V94M({D}d{mYfsd;~!*K9l|oas|ffSq>F!ab)( z5Ok#&>G8a2UQDarFU%XWbOXNqf?hrp#jz3}=WU`Tx<;^-oeX03fT>gSqkc^lm4Nmp z@A5m|HHny|feT%X)WI~imtCc6;GFet=Ssd(*R=k0{0pYAOTl%B!pcHat6uzf@P_-e(4Tl2o8 z!oz09!TWfI*7P-XRhS@>JyOF!KT+29;6^mo*q1FtP!#>G?3LA*j_9R=ZW(9zX>KSU zSweoW(6sERMICNZb2Ku-&i2Mx6uXLH#sGvnRGh}GK4;=8N2pxmLQ8O=T8pb!3|svN z3L*Xo^f5kWlFx~WLx$k>=Rp@7Uke(Zy;s{VpFaO-ohibH9%iOElcqQ&U%yc6l1QI) zTu%dQJ0$KN+Q99TAt*M8R8VW!zSLkQpeB0aHg7|k2?8fJ`J=(*L%2ara|<^6$fyFt~J5sRd2N^G3(N=lpKCLd3-o!B0+{3s+ zsb5}Tk_nUD^ml9g!5Uldz-5Cz<>wbkB_Mh&U`#qmeHRPo8y9V-h1i8&IaJHFCl*#- zJ0U(b%@uOPxVo&YXX0x{p>aeSkL$%qE4K`BC6Ahy)Rzq-34JW@t>IX*kmwFsMb=lH z$x*Cc%}jnuo{H;{>4Ggijl3GuwEe~!drZ@_NImY!V+k5bo2r+*k@2dhM?-{t5a*V1 zlI>bpN}*Z#_A++v^pj$9eD-x#GBNA6mzW;P^7cQp=il{VgP7_uI<|59yzz&maO)R_ zDbH+v6;B8kZv^QFvf5@C9Ahj9Z(YSqJSrBx@j}Yh zU)!};;U}+8y))dt5y@Sk_`!#eI!tKHL})OyJD8%L#!{gsWb@sQnmoa0+^ zZA&KE%^vpmM%_Cz_c-R}tIm~Jb(KV>^C2bk9rp+7Yl}egIsO3Cn@S)ZEavK&J~X$_ z^^2)-FVB{GeGiX72g#lpl5Vpyq7XTyHOzoAV2I}Mi3`2{qk20bx4!OywO zGq`oDq2J@v<3vV_?_25I4Gust78G-WU%in1uB*04>#9{MM($g$h)ABgN@b$_#5obo z3$XO6#;h-HUVG>GYN$&S-8o{-DjQ<6pA6%!Pw$EYMMYXZT{fOy1T)h#|(r)JdsUgtx zi~a+ewfejFiYsNK{UNJTJdf&y7PMInMlbiYwAjJ3S$u*e>nG$Mylu&=caOwcZp1oG z+D!NxK*)3+Yo|2(X)F1_P~s%vlgX9~nK`$-Cg-oz7;T_KkO$ihmy}p{&!2iN72LP% z=mgKC^C^(mvvbY*IO=8iQ_=cqSNdu0+droLU+MpoOK?p9Mpim1hNyA%&t8XsKh-N5 zmvb)}`&yWYNkAY}To-StT$+MViCOrChKEP^Mp8wDhll!Gia&=y>2o5<&?43V2$Zrv ziVU4N;17XB#*iV&eh?__-YYVM*%ty4e@%uU!1XG)-UQd{;HnL-YX5&;Z~Xqf>hJ5H zcK?(wfqHe&4==c$_JcssU|{25fXd*i5deWajUq#wf*^3|jG?ui=ezKo^^p%sFCZ}Z zQJ&|#FrK4Sb&x3trI@9Ecx1SL1SR+ku$BaqKAa0CUCa;&fq*$fCP7Q#;baKOmkdb) zt?!1Bp?IR-uc@B}g}pt0GDIGX<5DOYhQ|^?Nez^)gzT600)Ca0gUN8x9u7zNQw}6U z@ZKbfy*(W1Zxt1mNFoyV@Zjct6UqT(YSJEoOeEq7f2#b*lterpM<9C>p?m-R)SFC0 zB7o-cyZE0s@W0xGE0f8DJs%t`ewzqdArSURzeYy^ZV-J)2Z*HIHSi7G_%rOwL1gNc zc_NuW!2PMZ^qfq!KD$T8@8N&X?P4&QYI}BvjK`6{LhKLq(hD->-s}b$NBCVK8$yN? z=a-55<*VRX>?oKy!Th%tjgq_`t;~GX{qnx zT%0WQZ_3`csr$9E;MVT={L13o%+y4{gU9zZPMS;%|GEVMz@z$pS655@oW$=QE&*_o z0v=qEy-1buds-I(IFm9OB>Cv{e%Am1Qx8p%J0&4UmVUP+8%m~_zXW*$ioc;pL6SMV z2bT0F_yEAH`~N^Mf(*g^zYIKV-#@@Jr~#w+1H9`hV9-Bz8vq{B6!PWw9IgQ1;qJ5C z!2K@o18<2;Ub`=F{P~~N236r=4Sv+xXWIW(Q8hpy)U+oZ{y-{#4Ez3q!UqBg_*3Ic zrX=J)J_UjKK%jJA{`}ILOf~sRlmC=DFTmj6YkNSMJm)8Mi2uSlS$=@ZVZRoWPMN%1 z)joi3ZLF*2@rA%dt1Ex6GJqE(5nv_bUuZ#hfx{0Z=JzZBtYGrjzIa0*3cqXiVO3dA zt~&^UEdFj~A66J)NE9gkfz{qQs()c+-uM3$Ru(4b#30ZB_h2mz6@~*G2LRh(P`!5f z76bwZU*QlMDsVw^p8tga3@4ZhPrpg|Tte*gs~4)7lc zhN(~p1-L@NKS(O<&s{hqmE!OB{Rhz_3*3KlO1VInMrbRK-SM1TM|$H)1@}Cd#V>DoT;)%dKm72mz{O5DJ9`ofGduG@ zDgTcev9lNGFX+!W?aGm>cabus)_0s8o$ol`>C010NiOXD@T~fdXIA_C%7Xp}?ekA* z_`D&oe?K}#VYnS0o^)jh6wZwJ_k+b4>b>}H#r}OCdYXJlq)+q@W|sfsVK_5*+VX!- z|DP-Hzcu+Ep8VZb|JytNqY(e2ntzzg|8~Rwlie`q4>*giU}Vd*?la?X-H#BV?7Qa{ z1OYS8IefBsXN^nY6XHYNhXa;Z6yR?UHm=u&yohpQet)*cf2=R4saTZm%}=I(l-YP^ zQKsp~4SBv}EYB}`Q+l&&SsaA2GsLIF6{}K&a4>#6LLg`?wRqv&BCE@oVjrFdN zW7H3t7pf|;;!hYzaZ&xGYCduB!N+Od-@W50Yfe)%}O9t?v$ozEAMkGOt<*c$&xYEk;D&?67kuDuJ@&KWuoJ$pvbZU+R!#XNAK`&K__$EZOQ+Gr6T4Px`kga7)ldCc+`%+97 zf8<<~nZLhX*afR)$;-_T5y~D*!}YMUkfQY_Q}b=wW44pL+jXBicQ{7I+#kNRZXZ&d zuZK%3h2aXMU^xe$TYm1#UN1u1VWg$PN(SagE4bj#!lfhSn6p&f>J8ymC&6SnleGi2 zD-hpK5O1oNEm&kFd%`P6i3E+iF;=)@O~ZW1&R5A8z77#sa6)1+-P2cgm*)*_^tP9D z+7-PH-7LoRIjOsX=IX9YOCB_}PNyXPfz=7l6- z(8|fMA~b!#nu`fQO3SBCjiXqZ!T)CHyI#pBA9!^Pls@Z*PnRN(xt@hz{&r396ljt! zKqyQ^>O==sG%268MQr<9H_O`lMOV#-{X13oo_OnCyC=(R+dm1Iu4u=nV2i2-+6tqX z?YB?Q%+UuaTqVuh_tOCU%R4{V>mo*Z=cOwtKd`I z?YN6}Nyl5t`Lj~yCz)Sjge?nnYy{t}K*(aAe=B+|`K>$WuF#78#0Mw(AY1*SQDVKs zEgRneZ@1}wQFQ>9jQOXXedTan>GeD_fy0ket~)NA`e??h!1ih<=UsU3D>1bMYoge? z^dS8+{e>b!?`LCs&m!x2iX09`UCozVc&0yF-Ro4_ou@6NYHIJQy`cH7C2N#;y7+!^ zXn=S2W$kMP0BcSux;j*SMueOoZL3LUFSBYV7kS9=U-Y!syc;LWx_|^>7Aqs*{L{^O z#IaAc3cT+Nou!!)Uz%`t3FPISUs+j+E+RFIpwSn445>{T3VYn;WM$nPd1ChLTiSib`PpQ=ry160l;hVst9{ zAmYuAeq+VTZL9Rk+owPOR?)go84D$EoC?u-^tGnms3?T0eE>`6)M*@TAnrl}u4`jO zz`td7|A0Ge)oZsRWm6_}?1zNfe#gQ=8#AtGFUO(~FUQvPxp#p#X$boXhVheieJ z?$aW=br}Z?OgIjUS5Nk%y7eK~=zg5MP15!G>!w|^cGDZ-#1t|vg{dt`&bd!D`UEjK zX;^e&X(`c0Xq)aT@3Un^24tu#O^C;DjnVv?aia)hBkXITQ`-1Ze7~{Mo%~U+D-);i zhXWe+Bbbz)5x4u?QMV?N5ET|uBHWhZ%Y9e1lBZf`6lSjFl2OIo+cx}2zy4x3AC#~YMxGK)y}B@qV<>Q*A+@z zX-rjf-3~(i9DQ2Z0m1Hz0jf8+2Znc4>{ekfB(0-Hz@Bx%ugv%GYNKN z1f%3w^15?U-9`!5ElPiguEYv?o}Nvy{YIMh?^P&E`L~-p`1oMD!8D{}np8rX_zT&oSw zd9$`e%u>>BLHLM5PYX#PLue` zs)(A?_(h7+Vc%`%f(E^P z4RE02pc5mdYltx?eqIJ2hev3qmq_`oY60S*eCk2q{hW5B~m<$ja;(U)9*QD@g zb0GM7U^{0hm{6p>MJdJI;b&6G4qd9w@_TdX0iDqKx*^W%cK!0DE9QkJ_$PyT;d+^N z3YnRL41k!#MAvfwt4}Ia-YHCjZ<-aE^n>ns{l~yQ1Lu*a_;r%=Am?t3}aiPq$XVPmrUTESTL2eA!_G90v zYqdC^fxQhh5}1JrHRu)8P*G)`2i9jPSd!uO$S86JXS~Un1tT4z*{Pq zSKo%m$iy*C;yCb!%>8gXt9q;&jZ7TLyY2M&uW2p6(6NHuc$L#Oy~=gGct6^ggbC!d z?zb>_1j~(H%TKd?GIHJSRCH^OT+{{9*pq3DWnbJw{?w~t*(w5nZXXL3zx5Fj8jVZ} z)mext)p%F*y651G(~wnZB{66CRiRlsDV3-}RxP z+f9llb*Q>&1yxR8w2(3a^DX!c0%&GK7?lWX=%o=nSx+&=h`pO-|5k0-l9zV#PDI$o3z_ zM*u95lkplEm0t_e1g^HFJHyY~<(@{%vh25@!f?I9bhIqP6z!>Ui`Ov zAMy5j?LK_fu2J;BZ^^IkCapz;OF0A4rj3xUw3m*iqM{;oRSzkl;wh&8+EBx2>6w_w zGw)&z_mq%3X2_jd;2dAjRRwd1T48uc@oHn3@ri;|dzj7{=f%MALT2Xp7cU&a%4$(_ zRDhMW*vMnuObvHw@#~7`JrN^2{ZpJAb;94Xv00^F!eZyEQwtG_{}Ib*M8Un`GOM8y zz$~U3hmkt0>9(?hn zn6^%QJyv7x(MX=Mm#KAfeXYNBl09L)fmg|?^X(P0(9tHN7UJGTo8)I*rY?XFqjT0K+ryrOX7P50ZFXxzWxFF#j!BbQ2-v1DPt-u)3wb^3lXPiRD1dQL=f3h~)@pO675~)CY?gofW4_SeE<<5g+*7=H z0czD64IqI`#;p*pfpxTB3AEPFwk*Fjtark~`Pq=|Cg+Pn<_>0FId`BPu6aj3RZFD= znYL)S=-#)oJ)wL#`FJ7;F0D&T>x5k==2E1y=l+g zkzMPd+izkjnC2@rx+TUEge(S%lBHH+U(1gS6UFn=A^{P?_74Elc+FQnpxw}e-cs?7 zKlElYiIed{4~+Fk*U8Huc7AlA&@9DDh~$ptj+6f_hyd&P6kUIScZvdb+>Z_Ts}mH5 z^pch=Pg1PaOSFqRY#tNQD-QN5-gtTU5~)RCe=FSCSM>y#0v^C0#$j6?I7Y4XQQEu# zG{pCG_X}rgVBWw`@PP7R9AU9;IFD}hyj0Hm^|Y8T)6-iZ0h8_8 zO2w*ITGf}ab6(WP_Z7=uM*w`=Fq@}i)x-r(>#~W-+Zr;{u5uhd`}%Z92jYB*_fTIs zNBQ>t@&$n9J74uo5uI+f#z1@Q(Z*_0cT1eOrt+6I36Zpn&C*e~MQf)kSPp!&7rAL_ z>_z@Bp&m%~%V#=9#>U8OAUOekbp%9Q&bBF$2~AG#P4eheFe{5!P-S!1s;x)M5_)A1 zKG6fHxXx}EB-PF9q!9s0fn00W0!73J~%?5O>VW)XW!4Y z5M(RmEya!4GylgOAwEkqheE!GB}iJyB2zqfa9=?rrgo8FpY#0j?jUa$44{~!Wk$Li zkIt9jSDbnCrLcGp z#gvqx_Z0YjE6y)+lA&ij+m>Xx)OS(Iy#`ACsZg-9sam7Uuj{;d4yJxYUdm{4v{kQ9 zk4Lsu0AYUmv@Wz7R%6Pni#S12k0(^HI?tzQOpcVzSQtnpuDv7!4S^dATu{jkAcSv& z;RHENQ|9m=`s`D3B;SZaVVHEiCL1L7S^l{1+5ULw>uc2MC(66UrtiwI*S&<&>Pv-B`ef_WBsRRAaT}Fc-!5ig14RBuSgAF^AtL%>YSNr9e%8E%D zZ4U2Q8@}_fsmiucq}6)${J>prN{EPGHVjO1@t7eVlPR$RmOW#e-)bt^b7w#)QOv>_32Iu~$xPJyRX zeo2mC7uZsQDTL<_EdafET8*=rA$?jROL4d_*(>kLyHg+16Qou$i^Kgd;;fUj)}I@p zf@Dv;>JqFGf^n%85^)5&;4q)PEoB9PTLPY2vOk+6g*rJTn1EL$%Xj9dcCAZX;o<*yHW6zyuQwC(2XEXY3Q%0(^e*gr9bFj=UEe(@X z{TTP!_r>?yetv#QCBi68Sfk~gU5RY2E>EkE7Om(a|50_LUAIk34Hc|g^^8fOvOOh0 z4EuKV7Pli4ymY$}iE=zP)tSUgQks*jJo~Izm5xn>K#jK}%dA{{{ulB2m|uAhbB@m{ zk#Q>f^8a>8>swEkFF0cdmtkx+Qx|-gMd}MOx+;r!KsD^zH?N&pDtVk{r*A zHsr~6^5&%Dr}inrsU0Cb(u4KM?_*{gN=^rY{~mbO@$v0axy%9)@#8EA^YklmB_8v} zw~_l7we@oC=7aIFed;&#_i>^MXQM?*khoMQ;Ni(TX|AnWzE45+jy`!v7TCjR%`?5y z%iJf7IK>qdnWVf6yx@@wb94R0!I!xX{6`ld&*27rx z(iAzQgfW^ts43z8cL^^aGe-HAKf-NHE4fbuuqi%C*s4xuxZct^a$fz$$%Gi3)kU0_ zBgLkG+X!#JB4raBP>OJ~CwqCWZmICiF-0Ya+NoEhN#$-gM|)Lhx}F;caFAI8aYL0k zSy{6N1->29|49K5*aW2;h+1`A59gN4B_*J6oVcS;JQ+UbSsXu$N-j>DQC&P3+sgSQ zc_#Ku7zwkoI@5P3Vs0C$-jD$TSFi^V_H9?t?gu-g$5tbvL%+B7?Q>1lVSMAzot}t( zrB55V$O!Qtfq#fEpEsflejwl*X5X9_v`-C3ZSa}An@k7Z;dL|ZXic9ft^5PA&`n40 z7xGqmCqLeNdi2n>j;S%ZiC72M=`AcKVzs~-hx(yGBDc+)!?lk)Hb?&1Ts}oK{Ry{4 z6}CE*k)-{3_w5Yeb5UcKhBnEJcQzcKVSp5&RjrrxQ2s3r@!do#P98{7QO+6~>;3pV zdCCjK4r{mgEsz*(RU=6}xFJ3yI0g6NdJM4o%V;6WO-P z>P~g3(K0`E-|DWra;e(nN~YsTW&GqYYwC&I?z@kne8pM0CE-#);*R#1Pt;iPo76Q- z#@-;Z8F{QD2UDC4L2%feNxbLHN`NAeKBf!>)LGXJ(|#UI%|>s%m3O_;A` zQu3(e?&!BP=5#jVwbZX)3bRc1|E&6D>`2V2PM?(MTUS4up+_f_5h92Z$s^C_RF`%e z>RQod{(H=K!YrjHm`14;*L)Q5#P=Vmsi+hO>$7~){*#z!9^I>{KEbsEwQ?76BO@uxlTQxDsw>-6>PzoM=ryzog(L0*tG#43v#uD9O`Vu7_~4xiX_d6H z`q&GYV@WrGHnLi}ZeeWx4+x$kb_uvmlr?H+&w?}7HLmjRjvh_^0LDI%0mYwDwvc!2r=P5b% z%RhY(!d=jeb|kYdL7PWzYUe0>1I2Imp^A*C%btS3&V|n= z-I^5GD%VWcOA}#dBBt;^Ntw{p74fXN4w0idhsRkVIolD_b1d@riKKgFu0S0HXu8La zPu~eKB0LbGQ~<0|=OxEl7rtLIUx(kF%ETi;ZYHoVRet z5ZBvm4puY?L84sla?IV15+VaT@sOg^29hG0Or;@KA@HAUSQLgZG8)6*1XjqkXD(R%dz{WQb9CX<|R`i)xSgj;9bSPQ;`d-LY5i|+udGra95)I4#!~qwqr48 z^EHVaKn|llP{Jq2@>cvSX=aYH4jxOFfO$}+O02x(mGBjMH^xgTrHQeg11dhx3U5wj z5<#>S<+*1v)Ntzm)|oklPg+`9!p}HW%_W`3K})t%CZwL~gM8`MgMHAlQ>nID$mn1W zy=KZNd0cD+k=MSFU&(kQWg{eX<*x`)ce(?Oe&$O&R&(c!PHs#dh0B;WT551uYcJgb zAW6b+fHq8D5u0W2;|cDiS)=vtEmLvprb-F*Lc)jT!vJRzv2YD_pCy}t%w{V)O#P^# z2x5DqTq5B>KPLrg&YOY}8xq9pbsccT9q;oaC!vgW64S*Y1E0~ zV%y4C38_UIdlFnyIC7Jw*M|G5$E@769C>q*m)rd>c=;j~e3pkwk;u_XS7b4u*1p`H zaaSNo-R{a?(ei9vqV2+Y>}D*f0-A5>a0d`?H8rQ(zRTlwd4>%Rb*Q2OF(=4<`p;T@ zqcvnzy%r*xP&zNg{~=^|;Na~uN^47n?OvwMF{ijovMXntjBFMyZEa5GTu*+=;f9&M zr1@ngfRQsX$X}81aQZ&$c0*?tv7@8gR+$1w4_?|?3^R-&QpUzcEXe@dP4d-@xmwET}}x>ISvKRL!0N zk^yLpi!-l5N0E4_|HJEQ$H7^}v(w)kGlHX$^N|``#BT*nsP00klV2P*rkapPtPgcx z`j;bffcN}?(*cbEU`){&@O0S7OH&&iDHA{AD*FKl8p+nWDrkv-v#{>Ep04Ke!6r9? z5x0cM`=N_jafGZXfwu{N$7*qCZWJ6p=2imRZR}thzDj0xrU@&)EOqzPrnQ&rsBFd% zVxOc-2eZ&$Oj)x&xt<*%l@bf1O5+!(7jr!xQk&p4^ApFxjGe;l~ zz0LXss9BEazRjqe8B1=45&KrU!;;vmrteL(PH_O`lR3;}DMuWevEhEc!u4QZk<<#n zlk@7cHYnl_5r_eeoK|Cd52?o?e@9KjXAE-ZTMvOpMtA4ZBUXyIHab0tSX5xttm0*L zG)JtKWYg}?@mE_^9~f_mdanlP`Fr%l*qak-r0tq=8a@jH8r#}}CNdDMC1;-thGUUx zq*vk0|1bLPyId*B+>mfUy#l7-!P<2$Er&8)FfX&TSSy>ZIBLtFSmBMfn)zm~VirwPS%S!ml0A(dk%6;rmGMh7vO0Qu|O za5XhGDgSpYbnuZ{sm8DD@;G!{M159yOHf;e{vM>4DO){9l*MJ>Q~sXsGqao@Oqob!#(@~w_C z(0&+aeb*%l&G;vp`lb4l*1Gj?T`}KohZvksp zg?$`2jI(dZR8JtiD=pnEJA$@#`G;gNud%o+6*MST0{v;sIAn_lGOC5zT@CDt^6DGo zELZ6~FO~Ns(H*LN{D~W-BDBL{;~vxdXg8Ff`5R#R7b0GK02CQuK_wrHMk?I`Z3VmAJOQ$(j2;}~^i&p|lc-Ku?Q=c#3&B~t7^(|o(iF~f0BW0RS9?v*d|Y*M zH)CtYLigMChyo>!9e1)#63DJG@RBjA{-2f+e7B%-5pjE?yVbjT_~lZgSS#td;_BTv zUCoW-xe0*KeUk)-Gkh0?3IN`Xog5a***9ZW76hZ}_Vw^4&@j27UXH+s_-pC~U_GW% zGs-kxqX*6cFO;Zklp7iiS)R<>tzufPY-1Ad_K^CdJ=4p{7U2?pA=m0)F`X@w_h9S8 zp>!Xipt0zio5LNPu|@J*5x$%=MxNU}dF#>0f+TB>tN*PCh_3aSkg)7c^r&M|8Mffu z9i>K~H9;(J?p&F=$?LYX_dJzr|dM>8vv*G~9#XdSg zzW#rx9#7!1OfplEdB{0sUXFZ)UMZ}vA-*NGNR9d=K$x^oTAj`Rj-jMEukiaL;5;N$z}2KBAG0a^#f5#FofmcKm$@uoU%M$$J0Y+7UNVI4-9bH)p`A z*hvcG$#Ljtz;Ps%H&95Tx*^K@4zy=vFSWyJ;Zd1ZO*7%VNieC8p1wKW<64XJ-)kQ3 z)}A3f;EG1ZzW#6Vyg&)OQKs4z49RH9@_9s(>U3l?%-{P>CEn4|V8fP#!E3r;)+{fm z22dM+JZ$oZ5~DNt&zx1rCGH zwA4bZUuZZlq;h-MP6v#;u4!@jKZ_?w*GqK=V+F8X*YTO$6Pcd!!J57savaewrW?!C z6*3GIK3QRZWIOx-^r^T(qQsclMIu_GkxXyYwzn<;Xifulbsa$d|J!7QU}k(hro><` zd8aaKB1~!Gz-T}_&Ok@=XgDYr< zao((>eYXAje_b*4BMi)qsW1W&)oM7%XAb5#Ji@^n?H7#i@aE^^?MpScaKQN9pR)2~ zjsR&J-1FymvU;y~mVQ0@U1C49es8}jRa^h&H`D(>a0E*L>Q|yuHD(!?vZZ`Ke5fJP z+8BVCm-az6 z)&4$AYH}l7Bbww>b6Aggi}57%0fjMtGlCr@_iEIiM7)9a* zvKvFmjb_FeG`>&^5M#3wlBmNT;AgFE12bErH-e4T`bA0r?-y8uH6F@tT zc`m+OLh8*+4T9qj4wji;RhsNhdWn$-Dx{JVzt;i9Y^EK63Ds|!E!5yP zWx2AX{!7q{QtE1^U;ebC3?wBS9~wBGV7HyH#rAuf3(U$BoeP5h#a$v-O(x>dfb)#T z_7@AAeicaIc>aew+HWYG$2$A&Y=vf$)9bzBTb34}mbe()ku!_&RHP)8s(ei>r4eW0Aq=*;y ziz+qwob(h~G1cKXIHt94j?B9MUtSS{vL`|VhI39cK|~oztu;$3B)6Fa!rRL$TaSxX zEUNc!iWsjuB({nJMDNve*(Og#lO7N+eHUGmTS)f{kSVIehy~LB^SH*fN0$dtp5xwG zm6DtrgsU^gQt2D#08E%wHV`|nc;_JT0eI2`XWPqqZQUGi#N8EHEF8-+TizWG)x43B zk$GMwP4++T9rV=DL}>6)f;n{AT=M$Xq>CFq2d{)(@UA+)oXRpIflJJ4peGSAC|tj zE1o8A$%-AH z4a)L6JSw{1-cZQ+Ep@pdGLj{eNCD87&8nIDK2>=tLwdnoY6OnXNbT`7c!(5Jf{OJe&Yoe*$q?&H6vX$1!VrRIH(tRFQwIO zTC_7a*WWi(=J8H7*pQ&MsUPH;d^6_PFIGd6BPI;o=a{7A)^2!hWM@?EM>|I0)=yY| zYxQU;y0D%kyAmQGBC_eWzn|NLl(-AFC;kLHs7!=&wJ`Nn@@Jv2}D_bl2; zYI}c`UEC}@@7iSo7BZecfbK=s9f?ftIGjIRsbTmjjd>$W$Z~$E;*cKH)#IB=j$DePGxAoi#90fB43m!Kkg*5r9{uYX;dALf)gxND>KslG} z)+?82q~r~o9w}kJ7P`z`H2-^P7T!yp4X|y6K%_;D!Zoq1T=_?H^g^!6IL1n^M6ax$ z`}w2FcT$eX3rB#--K`LLt>5@VuP6H3!do=WE)ErFcrIS}t9$|#yGClM=@&YqLrF7_ zYU*pnQ@LEDn7*Hn9`9trQEDK|lkykHT{`lRp0D**K*UQej4H^tfgl2M1)&6?tYIg| zD+ZO({RqP<;9EEqr40DWV%Q&>M4nTOoyrS;x#T4FRFr0jl#Nt}xue}7b9dCRZ|U|K zD7+OkEskPizIi4K{$#b-vKL*}X=KRW+T_yS2imsr9;VGFJaZ{tQ^9-b>Z=3`lBdCh zj77_Don50mZb6-s_N5P^ppA0KCRtXxwl3xDtf$h*r5KU4UhzY@+11-7{9 zcVY2C#=0!mLAPV_chN6vF28^jM#gQi_al;Wt<#$1)N_@dAlC9y;_3{ySr0Q3R=6x( zqh~qNuD(dLU+rd<5@`%Kk%yq1VSqOeDDgLQiTU!yjl_xbe3`eS z-c-3Vljla}SU%yJ)VN7f=UF-@AmaFwd8CTz2Xm{Dwx`Q*pc?%IL5+tV%^a!D+r1?10ls+g^yhoG=+wel ziefF07O1CmBntOuTvDvdU(G7(P5=Ibo0KXIbj!2WxBj(OSq@=Wv>)tfX6{bzEM8Oz zXnt9~W1$GozbXL2pj=)!iS&_+8wm%mh#tGk7+c5Kr;M@k?dfZtJB zq#twE@|>NW|I~OhTn;_;yL6pejic4-QA%b^N%`}LM3I3R%T@iIBlHWzeLN{?X_}!# z=x}&PNTMg_^Y-hNHq8TVp>{@Xrc5b?Uoo`0Lnyq!7wztFnhaS3}GNBE%bbWsNQ=W)p%t)4%BMJHfq!aulA%MBfZ$b{oWL!`sd@I=p$ z%pc#{Vhbzo`F7vq_8hr_S@L3~z~+Z` zlUvHEiaV^qU-;&e-Z5ICEC1L@tKwO|S=z z)O+&>sM~SMM3u?{Eo3Ig6XaeNQp&qKUAZy*?zHh~z+rg`lh<$k^Ql06A>;YwCBFbv zmAI=8(tNp#45mvhF&PNv#x=^B@=eVUhR3KHh&R77fAuFCJS#_NC=gRl>e|)a`k;Av zmBNY#3-lAn*kwh{AbC^I)9a^-!g6ZNIk4MF*jVP!&E3%h{yQ4JBs1aTTH)~}j9eS98VJF@9?V;#Ib2cvaQi7iCK{^fQc z+_7o2JdXB-zdtJNCod)1xVn*q6spt9v$Vjr1I!AR{Tst_&q{HSlhl;98|JsZ8O$qy zM1*K-FDR#3?9I^A0OF^tV1IxAcW~1`;yPU=wa_7mYxICid$?F|Jzy^8t#uarp3v3x zSsOBx8WEs|Ws%nSvW~J-=|66!xa%oyh!}V0d-t%GT{?28VO$mX3QDsC+#!mf|CE$&3$+?OxU_FRteqPG@o?7zE=PNLTdXV4V>%)n*d;+ zqht7u`HW>QCWd=W3-g2=VDV0fb!fKc_$$L6dKFE!ucXVmTIFw@ zkWte+MVBv~2LFh&sBUh}!PNs~|7(v*T2)Us;h6Z**FW+K)!!4C>$0SD05<9+cUZw$ zDaAG7r%LNX7jU|FnC8o#EB-f>`=9Ir{}ay6$yqhYlD&QUT3NbauCdr(`f_Hio&AG* z@y7W=#l<$XsL#Y`FxbusTugi|ao#RjUvZi*rQdDi#t%C`RN~@pM;(HebK6%%893WL6Aq@#7_0*g$q}hh zfrs?9BbKdkm)s&;+$cDBD^ztmsqa$1X6_}yJR%VA{(MH=w_w8$w2yV@D@dIMSpFg6 zOP=!TtsEP`dM1kDnyrG{+64Zh7hf%&)~5(IalBG-FK2V z`tdR~Q&tRte9^N#ZGq)#(g@H>u2*f@9^Tx3a#)b?4TdYkPpB{egt{`pmSgL)_lKMs|{~adPoYin03R?8K0@U$6{xXQL6 zHYagPen7N_zpS#EKSq01m3_8Su@ApR03_B4VlMk?vXsOBcj&sf7L=tARxn z2dbh>lc;&15P({sLNd%Bo?TG_PkX|@Sbs!(w60mjifa39Hu5egIK~ErEF_IbnYn4f z^LcVX)0@$vaaG)@OETmS{KuG3Nf;2I6#viGn$$LRZHZ*q2Jvc_Ktl(H57Q6+XX~5% zEYV2cEM(asC z2F_iGPhfYVSx+UB3H(}&Vo$-|=K5Nbfobe#^-veW;61l{3AzdioSh>hzLTKX+CyJz zoaL5%PI|S+FU7Fwr7AE&skxn#P735gIjM~ekBtA`ro5d~g3KxT1nM6mdCT2cnuMum zMdacJ`fdQ|4NqW~J~?pMvIZj9VB1SwNnp}=@;JVUefvWO&uLd4<(Ant=4K|0&QhuO zcUC~HusrOHX!GWGRJZ%krlhyw3Ql<~&o3=WBZ&V=!cZ{;=T-&kv-t%w=2mQ*e~ksr z;_H+uPZ6+mnxnu#&WqQ4n)19~0q*eS=&p62%XKYpt)tQ;AGLudsB3S&x#Et`(bO^g=-!EdJtJ?ZTmp$ABVYwZdFpn9-}i~X3kQ_jkZ=XSfg;^ z@iugy&_WmTr`Vq7h!Xuz>L-XFAHgcGr=$4=v4^kQMg>TsRH zCF|tb~KI;~sokssBL~WztTpqONz@~_1=pPqsx;X@`mT+P(_zGf zNF4d|b+Lne!>=36tN`S>8(sw!R3&UX`lrwP^*oH~Q&!s~qI;ajJ8|A3h;QB&b7#e0 zY4xW!?#S8BtLp5+f4m!<_;v9$i)T)f^|*v=@R90DQWbm6WYc}dc(coaf#J33%F)|J zLsAni@->*y!qi8VF3JTza7j6&^iqNczn{~io#uzs{6?*?K%Ez-t?TdXT0WTD!j+2! z4V6c(_KhD(ejU`k4_!cKdwOnz%IO6j;2>j}JO)jxiglAF<_#Kr*?40Q1Rhm_N*`Cy zoQ2wrj`@CDTJc${c=y`oaJ2WMwk|}A_jGf-xR<&)B@gr#F@o~?W-=O8p>wgHKX~fk zE=~(~Ei-5Y1!7f}!?2U=bnM&!ank*ZwY!8Zy6I@@Rd2_0?|fD|nHw8&T}^N#{$+mCJqOcvI4 z?+#atd?zQ2p!brA6P%M6vNz*izy8*;P;Kf;R`Pd?o`XnAYy&$mcVVH=yXOvlUw{(N zuJWzy@7LPyqP+GMz5kRkwih^$25hx=w_-!NNCpax3%KX-F}uiuHpz=HQ#d*lvXi&v zev!3eezc*YVy1!u$u&?|!ng1O4=C=wr&1+s$U;TFyj%ISkmn2;da3iDj|P=l^6k-A+Lc%d-%nz}ciR(4u4CP>pX4X|s4+%BZk$Wu?TX>{-C0 zCcD!Fc8|~8zqGDenpIUKDC{mBq36&|U@yn+~Y6;JV^09?Qe z(z4;F%P~t7^=;9~Z#I@2ZGbG+Z!S3I1V}ZdBi6pH#@CfQWm=*!c#5<=q7ey4-M8WS zoC3(B1B>_5+erh1LTx%1#g`k3-U>W~I>Km~tnbo%E@m}dsUzlp8{09*p*WzfcS;$3 zCZ=4e>84~Z=eu_fa|M(m_c%h@E$^5BsmHh`L!phNO#*v?j#~0YecT(>@if_LhaSPRz!{<9E zapRpg{rv>ADiha$*0$9v+>!4WEb=1nX)2zKx3%?nl^s3CBlg(1&;GBn@8!|Dno#G& zC;WrM>67=s{nZF#zsE^Lf7<%)r{IT$BScXvD~_HkQ|)#K9&grFh@k=d5d*0Zq%s5C z-o(@YMyWa|d;Zv?DS(B6FS@Y<}=CneD+V?}wyvy7b1q!xL9&K+p9rw0M?T zsd;wn-o{q5DViUW3rUqam6&KHB21gki48FFEp(IXgEv{}9}Vs{(~T&gDq8fb4Ov$hMn%=By4|)vHYaovy*ak@`Igur{)y6 z1E-fgp2~ZtF#hIf8ZC39xj*>)@@e&E@)lP(Yd?5Y%vH5#JiV?RKcDNCo0?|1F6%+xXb|0=q#c0B;KVaU}=`G&3Tk{Dnez6K zuok0-_?O`BUf`@M?xJ**DUe~udZc20G!7%Zaz1rSW}O3Nk-NKl>nIT8lsim}mW8#u ziD>pn!B4#RGDyppAAf!qpGvH^afPQ5)a7%1oqYHHdK$}nScU_G+OL?7xbEUm2i6GV z{CtOoIs{o$9Ac%gM)Gk)$bZSPIe$gY zsz$CJ7Dxmr(Bo1eFelJ&0J%G>na~|Z)5RJrAR!h?9EsXaJab0(%sW@GTb(^kB3W1}6k9I&Bqg$(Bfqsu@ z7#OX2Yyo9zPR9p!M0R{anG$bj9Q(&g4kk|sPco%vfrng(RRe{&Yro6FdQ_D+v;#?$ zMsHI?(y020rPZDI89h^+>pgutyJ_#=TjwK)Ts$a)0wZ;hsbySzR{w>a% zN)c-dSb?X~{6+lXTU##ss2Q4z4r~ zSp6Y{Fw^FrAeW{z#M&CzjVmo90rR7WHOrcUXIftb8bX}sgv^{=hkwORpf?4)I1a}P zv!t38;Jb9S3Y!P~ld05O4+pfCYydYAV9e}UbDQNa!pi3X6>GVg+L2rIZ2ahF|9rns zbkZ;fRu*w#IdpEl&vM|XWLSgf>$UQ=Vmf3LejN$%OB+D86FS2x$}Z=X#$=Tds~K-%5zmaNAv}0)cvZjKa;{BWJvoW8WS|8AH!gR@K85w&q zA<{!T?Y^(m^a8ZXRy1kv1o}drJo!|R;G3sP5kT{G*5-jMB{AgD%Ywgr@<*E7Xym>> zc4``%ychX|3E{XMz%Fj%IJgL~6^fFeHCe{De0jE1QiG^`Y}?Qr%A%X~AerSiM{t!( zL$CRx(DA?ihCstI(yDr}Iw7NLa;o~tp4bBSaymN&I9k2U0$MxfE{KrljV>I;7=u1c z$jK0&Y>|&Nl}{W;$9M<2y1u~zxxshWae)!#L4#wVnP?KHgiDI{l^Vl4j?l&dU4qja zN&tv1;)?q$$)HZ}aLWY)r8=L0?VRz$&E5F(z$wN*dh+{-f0dz)ZG;8p|8=hjC~8VW z`@zO7?a^GZGeJyp-wz(Y4_QDnq$q=vFL(GsHOuW}{gbgVX|B|zMo^`Uj{y8zKGSyz zU{5A%XvO@G&!&hX!Xd{)*8?CLd()R6Mkv~R%93qUaGs0*)khQ8o%v{4yqJvjC+Sy$ z+pn$?utbRA-~s3wcKdsdM;HGpR7dJUl*T`{f`gQ!`{v3<{0roNQkWiqTc&mDqtj4XadqaGH3IZQpQmyfSYygie@UJWHPu?=O3yclm#*uP>^e<9Djx zfgG3B;{X=2s=%tOp+L=SGq;Q2z&)XN$pk)k7!NgMQKyf%xS!fw&ePcGnz%`c9z(|I z!QgcH)IzfYu2G*%E{Bo0Fp|dJmeCLyHOKX|IK3=gIGJ@30vzuw(HEk5xW0NXSTHF( zZ<$AYIjMKR+!QGkgcq3b{lkf_4#xGpJ(w4mU<4v;0(*pz___J_@3sde=|P@MbJ?`};rlK;aVC6aGS&*M zY3ZfYaxlzs%B0-6%rddXY_z3oh7QFJqARc)6SivNtDerhES>GJZ3@V>W(u#zKp*X@ z@pJGo$`CTy9QAhNhUQ6dvsOyo?3TA23_zzeV-rJuS72-6*#JTAaMc-nS;}`}uvZ)* z+8YUoMBrBsaDeuDw#b}OCpcZ_+4ktsqb<9~r#jGXZY`f*vH%s8HK0dh#;@NT+eo%y zm)n{Apr0WFVtHyU5N|H=LDb@Q*m7GOCazS&IuEpYXsUOnmfSfwiI`kXiTP5FCx_K)15fD9PlJdp{3SzwLS4eE5H6Ce%#OB2PEV{;j7a14 z)Gb&~rg}79po<$*ihD+wP;*YYwjvz}WvLkSRMm&7dyjwmZ^$26X713YpMn%9?8laP zVqKCkkPEo+xoUfgmf5KKt2EsJ5r#5O(k*kJDlk{xyqo#{r!XHLNH6NXDa{0-|INU4DKCbNAB(-Sikzj%uCE+8Ah)psQ7F^zk5# z-K9`$fFUUIVTuh$jZz_s2x>vPoFj~AP+CupO66zgNFRJ=Nl99jiGTO|4YfiG@P>TU${oG9l@(s z+|qH;(%2mhCkq-0F|bK>Q?s%Zog8IN+k0ldI+xxC+cd$G>q+&zTNxwR?c?6RlunS6 z2%FaKav!cKN^i?bEDeZ+raA#SRv7qD+4dR8I#pn*x0Y6Q53K70j_lQQf9Pw!mXl>PoaxDF_M^U5#7d3pgr7jjfay8}N+qt11*_t-6zbX*bE z6zh1XBRYvG;L zyCP4e`2>G#l@#XFe3bGCX#RP3E4Cf5M)tHw7nh*>X z1QfBv;-M!9wKEmrGDz8f#INnQ9eZBvb<&vI8DcfZ+2kQQ0oGd(aI_PQ&$3N{&}K{1 zM`Fm0@&0_e8D|M)xzXB{IjUU6K>8^CcT4OBMc}*i4=1ujL^O^J^=gY%vzg9G^qX{N z=96oxz%IxJZC*s};a%GS5JtiAS}QcYn&+G~ttIo~E`SG$ z(LB4)Mi=YozcUX#F+1H!uXFjDw$H-55cyu&gVDE#>R*u_%hLJyFoMEp$VMVONgb46 z(sV0NR~oin1bADnR_%P<@)a7sc*>dFr+O(^u?=l?WQcsTqZ)Pv+mxVvv4^MwT zGDE{OvS{QC1`#Q}2s|XJoq6K^)G-9dg72wb`qY=xAO7UxNluBlfSTG%R0o9%dS9W^ zh4MF7ONZQO9N!Li&Fx|heE`vJL&txI|M^}3A-iNrsXpWjzQL9jn122wuEF3hHAk(9 zJdvTz$UsfjAAi>@z5QRb&5H{3L;!LoREv31@!4Wu4Jih!cSbTkofgaW(>dV z-gF@;Ti0QS`otKHI4Tc!2LhuD9JLG|cqOiYSz?f?x=U_V9@$zNr=j%;6(`kl+Yz6* zYmZ#97oOLSoRP5}uJlQ}U;<^isyuxCL`jdD0Sb+YqgG>=L*C{E?TYR10d?XvySpAt zOw%AG&k{9d!8Uhvw>73fdp%?Sxf3TTyd!Otxwr zuPrY|nSlrN!E?WpGESaeIS0-Gqv5Wkflrdi%7bvpJAw~Y7eRN_N29h-R?*$JO1UE@ zUMlpXDr*U7;j#h`sUQJU*EA-9)DW6VQYhgGh9J&fgt))}hyk}o>=WVINC4-6$Z9ts z$nIc1rmcpdfG97~9A1Z@ZW8?Ah6GETpO*RttCa}r=TNy)J=MKefFM17&38C*H$-ue z3r9qKT=GeferxRaR?yo>BNM~e?Fm|GwT;-s7fkM)M-TCvzbEF<)I3|e7}|e=VXUoC z?|1>xAI4R+ep5PJDAKHj^sAD2%{(P;X@NB$>>cs(wk(4gF}6eBBn3`>(;i zvQp7c(a`PanHU2y19owL-97v|0?>=0gH^5#o%>DJ2;L9;j&L^M=Va!D4eVSrtlt z+@L8*wo#Ebf~Ql#%HB5fOXg82&c=aC!wA+Io!}=6N;Dyf=ck&T2DplT@>S&A1Zb3) zozL?egOwSQh-7*yjO`Zy3<9ighhwG(s%ELaw70jfcvaj4FAc}=r0b*t{iNmY_C^TZ zaKiZY!s{Iys`rb(ani!T-$lrP$f$>GZ{)o&m%Qk_2w5#r#*D`W*arL%tfF@e>|6avPKrNW0fM;=fexpSZ9O0fuH=kzJvqsYCPo$;Pn04LUZh{H~ZCd6a-OVWT2$^hR- zk9}_H++~p~y>ooh5%C(<8kE-ixtp38axc*D<#Z*&jfshA6yAxSbh2r;X--4mKB-73 zD|%iK^Heb_Z*G(B_=d;RkCblo253HWi+VzFo%z^16F9Z5A}5TicRFI!PzQCaph>4{ zIX6#ry!EW1?1}F_CTMr@LEJ^=l>XMhC^*6EmzjSOTh!K?6EAeqm6NeW7}qsogY27d zF|V5qg!MwJ>|Z(fgE^2*#gQv|C!3w+9qfmxcIn0)95sJKTB+nF%Yb;#%q$N+(31k6 zJdfMxt88MGv}DEu*2jy6fFtBU)7Ew?v((h#m2};&Y{J*bJ^sd)1Y3>QxZau#t~G0F z)f|AA%57?xCVjH)ZgOkU3LOWmk_L7zGNH(9QpS}CZ3{N%SsMf>x3@ce(UUhd=Clu zv*Ng4xabm-HD#S7Hci$9R7GjiQ`Yff$6-$oXTw*MK_qso&{|2tx=YMB3$eU`WiTbG zoAwQ5ZZ0A-^0B(h?g2-?8r(_EAMJ+VK(Mtccw=8Azfg>0oYci7{vwDqqSr_0hB%>Y(~y%A0x=MhboE@ zzZ`eegv-kCt!M+^;Y`2G1=e_NuFwDZL};U%h~9}ZnZ*>gZixML@0fM2^HK1uBbbSO zYl4KOvZ~!%JPBM%EGcQ#nHkwd8oPF1QmFCwj;BXQ+(rQvfgnZ`Q`W&RDfpW;b^rKn z2EhDawVF>)$8mj7O)bPgg)8^mKnZU&aD?vlL5&tp2!p~_e}dcx7a3W|%7E!3qq|vf zyBGo+qU3ZaAJ8~Dj$LBVVe?+h74Bhkwv)G5iyNS&lPcsPy>SX=wDiZ64Fm0#Qf8{)x(C8u6Kh;w7o9%k^^yHoLCKdkP@ z*D=L{T!HfMecsw8(-b$pa9do}_jpN!z#CaEanyO3p|v5+3m0TgqDE@|DIF}DdH0h+ zWcOWy8GN10v=sLX$1Z|{yNhmi<~b@9hbk7KjM4rlS@MMeu7{fGyz@J+6H2bp%u}N@sQ>FpWDvsufm1dC*C-~6~ck_3US7B z2zX5Q_jJK+;$!L->8ak^)@}3(uXG>zN)z%N=jsVK@{J-D2e)>D)ot;{`1i-#=ldnCtHaWV$RABi*dZ`G+{!hGd)UP!QMg?B9p5|!?JcLObGsGV_1+W~NnZl{?)``Q#G7Cx`G7%lGU|10> zXInBh;Pi_60)GU+A;EHr?l?y4#U1e5oT4_wxV-^Ei4dQ25CnCKPzJAN zhBxJ=Ogh4`n~z=Gw;(j#Lnuvu^s;vJ)VlRSmLqnvp7_AMR}`` zXa;CZE81J43zOycaP?F#4yeo6qK~m8SumJnDB>-At-C*4ldfPZIC6K1pWbX0;pEEH zpf>b~EywDa;F(t~Yd5L~+}-~e4-%+NV`GXP1fGtxi)IWY+f@qcDTP8jv6^ik({RVL z5azH-pO;|9@v*(?h+eB?xb{UELIi#+vsO4%_QfeyOJA7qD-o177R{_5e`~+M#p+!^ zB4GJv?DwwooPG3a(W^7bys^_`YNX12<_mpRYPbklSkG6UYoWj*ZpRGJLu~w-kk;|@ zl7r1xdg1t9WKAD%{Wh;YtI$00BeRwm1dzPipO5Q0COck(xHx&^#LMp?CYC)()4cVI zE6pwK_XZ-B-v{chui;nEU15xVL9cz;u1+a^4mD6Nwf9Q zniyI@{;3gQ(p)b_AKgw!O%*UFs@c01jb%v@>*(N@sEhlm>>#W1>^aUCCpkqBm^#|gXta+^ z#RPiAt0o@PV23Q&SZ?>(PTUe*+Opa&u(vT+PFGTmF;|Y6>GL0a{V4P%gbn%_j(~jc z+PVEEZ`ERUiR7-;{ks+x_bu)n2BE{6cBZ`6TKL=>UlGF_f)TsB9GKdgtj3Qm^V#x{ z7AzC3(qjlgU~L?EEm5GL@2`12fR_Xno~vG$}v5anwjc7>y3LX2yDnd@Ya%BItG+;z9O;`qPlmgJy9R_L zuwC~O$I0EU!~Mcg25lk(!S{FVA%w1u2#2dG$>J^MyPXBW!BWf8&YV$rMT7wtCyY_w zey>J!y`do|pJPa=(9)N4ZX=CV_Qzw{sROg_Dy=qrLRsl=mVNFO#P)=SVk)sI9Px@SRwL%tmGW%|$S zA3PvDzMmEm)P9{CkNYYflnerXP_`FxCyw5SohQD}rnj8_RU4@j{+eGrN*sjg86!QfEu%SJxcyt@s_ zx;}5@HVo5DqWG)FzBQixK8I&O;*^0|7XMiSXr+~(F@wf(v%ZX5U_JftiL2;Am~9rz`lm>T?elyKuduEXF7pQxceXe zvDiY{>@zF`yY5HUCe3uznly^a_}DwszgM05eEF&+C;wDeEc`jY#tZG8`2v0SE&^5@ zu34*D*L42ieSl!x@0qvoWo!IA-3m2PS%%cIS4r#*?piS2PYNuh3s-Jx>&s2tDgj}h+)rYed1f~xk<%L`hEjd$aw^gzplWe=L3klu528q&j zA%PlGc}<^}do5BGYgTVbPJsZ;Pji4{})1hXhy@Zh}ASpfOEl-NNt*<-Au8-_3YK2R)X>M=NKr3R}$ z8(x3GDMsJummOTPwQcPZsuJJG5^Gm<=`GZF!2u5eN7ckPsG#A4yc!TA8I+a{>|35M zw*zy?nd2v#XNF2Z_8RGVk8kzhLg%;Y@8vT!L-q>X5Vq}c0iEqy;|Z10>)X4Bdp9@V zASp6-#t$gWx4(;1#W7=I!AxwEq|7F?6y?I$7l@-zb{bIzkt;+g{9I1j2SeW{H;f2P z?6j#C+0;rtd$iHvyEkP|*K*Nc_|JYk!k`1~O{kizN&2B~wHL$pVsQP>) zHt>QvIm9kyPQqq&KB+PkwQKi~nT~Ws-Yh{!gFknDb@d^mVzdelM}oF1 zQVJeKEgd=XJ&n&Nn=}=~?{DTQi=1Qu0XRGt&xF9}g4&7a(z3&X#RIMCF`Kn*8zh^f zL8vWrvv?&&8h@gqr`nXCV=AXoHT~%tEFZt$A$dQPOLx5EQq6Jp6Ee9=db|P1C}?*f zrCYal?-PD7ng%l+k9Oq~%g_Ty@~@M}J4*0IH>WrqRxtZFeVyhcUFCm`Mz&R!3n8Y} zZ$$?G-niA@f7|feRD2WRg?7e8PB|ee`C9ZfwONFp>McRhH0qP=ar;sr73BRodl%{P z|Dj~oiY8mG(hfG|CJS6dFY<*trvup}SOEsGMIgdvvB8xU@YUf?A8$)b_)GgfVgSu#A_VRVwr<9!^7non(6fUT+#=c8@@9yw0%C=~i=SiK; znN15UvNzOW0;cOXb=(k;d!Vm(9On{dw&4 zA1>5V2j2ECn5X&c1Eui$d}W$vl<~7WA{a>qbx1o9K2oI$L1t^q6hQ?LUff?n2=2y1 z?nCZkmTSe1Q!f-I<;$Cw81q$BUX^Ap@iu>otlh#&;nAX+Pd1u>Khy)u%&{^g=!w1lWMP4lSJ&+a!xsv}TGsPnRr zoz91bL#LJUP#T!Y#X5@~w{o#t-+1|#%INPNXAKsCa$Fo4^L&+z3%ZEkgnxEZzVdCD z#MQ^Q(2)fG+_@Z%8eOvrbE5KF%m(+0jEx-fRD3NK%KRI;e(uW%SG9_>4v!g!%1Z9K z+Dh6j8j+=e4`NtO(K*LC*#@hNlw%DN{WRx~I4m3Tmga?z4TX3PpY&NJqs+(M68zL^ zQG943f>>CKQGf7QX5&X$e;{xPhvy#DC=$t&+){f#68ycRpWEjm>V z-Fb!X2|UD)6LmITsQsqT)|lq;CiU6q9q^K_olp=RoMxVmvpUEk?W~LRGTxc_!k@X< zwzdonl_}|&nYsH~htBphy8(^Pa;Xhd{?S)#W5kbF&d7+bsxkV^4fH8UUy%>bn+g6%4$BaU|8~6&$9IucY5nLSWg}n{x%vc`qB5yg2r12&`TSfFM&p zyA!W}_BQa`9gEz>v#j`a3jxlOY))=O<8AjMH@7ll?e0d$Ht{#^?=1KAn6rB-EGO0c zROq$hB(N>Sn)oe`-1Lvi%*-kop~yEg<@LC1uR~(=Fu_j5Woti@qIUhd2f-KxL0DD! z{tZs(@x28+a9g25CyeAcrC{Kry4LEd=*%D%*=GvV^rS}3--GmrAIz-PXgsB{&T*Pd zR$S#~o!wtgU$|H7`gDHR_&eD}%&WFfj#UfKgW0W`)mGUzrm;NT#!1)Iwi1)6GTszj ziz8x!(9*?j^NzmIfwhh)Q{xY1kpFxgf7roZur#YCL-{w1q{5vEQlk*({#xa|O6o&= zh~+~P1~goPJn4KyJpM}u_~Z9$bmSwHWGDD75J3!3tTptp;z{&!B`Ev~={#JN(v}ge z*BKLa3SlsoXj`~&AM(1VXt`(+edwXiv$jz1Q_{7-ImSLzN4+Tu^L&EIhI&CjMwTK6 zBH`Xh+8tJQ80ojOcWd00oaXC+m`gPk!Vy1$8|ILNWG5S@n5?G=VwD?`B`y5B@CdTN zGY~nVlmGd%rUv=jXmu~bBj%cIjE$L7L$oSFiMC9v)3P)DyGU-Lq z>I@135-cs!E9#5zf-cJ`>{o{k!g7OQgnz>}?QIx0&9fXcKQeQWtAy_*a@Ct0Ja-^28W&4&WNzEeN)x{vUVBcK~@Rm1G-$yqM_nZzqI-+_4>jUC%Ys^ zjHzy$Hz|5XE#$MrErXMFQ$K#BUmkB8IV&Mz3tfI2HV1XTf@;bx z5~{u9@XLj0h>lF7afI%>!jmVpn?^$7)dUhJFbt7u2BNup2oc>0%0QUZ!iUcv{V1G0 z8;-`P-k2gF!v`~$#mSegqar8vib|uhU3;b?o|r^-JR#$#ZT)sBuT;+RY{?O&uf6S| z&ABfpI|GnG5)g$c(KL$V@Zk^pD17*Js4v0CgO}mR-A%^mki`rua1oR9mEjI^Et)c? zJ;G>RI_~qlm(T;LdVlLXrL2-14|gY2I%EK#NhVJ_wi2y0F7u3WD?Z09Hnj#mimJ&R zyGIU#38G^4ByzDmr)FZ(g&h6H-{PTmxRH4w<>Yi&~EPT9Yr?G7Z8KuuejhJ$2 znZJ5jKUUnUJdb!hRKQAqz%PDYz18v1CRP8;r>R837>u)$3#@gVamOm8CQ+s&ddPo- zmI5(wVxo1jKL>qpvQ%FGty%z*M!6Eexiz(OcW+9*A-(-2?vObx7Ek+lkvHJQqX$$% zM45jLa}k@_QInouLIyjZ#+5T~f8jqAvywArWSvNr z$dPrDT-Lph;rV}Ty$4X!+ZQdIgwPQXu+TxJC?H6cVhGZui-3R>mEL=Y1W`eyBOo0? z1Zklo(xM{0caSE%O7HDE0q_64H}lOfcLr}rPR?(awbx$zoC?g7Os}>9GLgXco#6*J zl1Rx$1!zw#jbDh>hV9j(+1$vK*F>Qj4$JhP1hBaVvzuf?#C#kr6AdlIlp|Zu(!ShV zKg7EKbBFmCpwM%HlIotX2AE#9G&a{L10YAwnIIdKgmAxSQ94QA-xjj5E+cI3p0{qEx;B*+(< z>ZfBJn(<(+uZSidi+H-%ij)>%e5-^1(#Ip+?xI86(rz}S_>NlXepD6J1i2v*mXJQw z>%)lb_dm>x+lFbV^FYFO5sjC6qaf?@xw9%0mC&nG(8Cs#oK#o}nX!!`T+{(bycrHt@i^&-$KLXlWQ-`EWejfRE*YVBGA$-KOXLbhlXbrs?tSE@$J@^iQ$v zejgEx`*L?Q@k`4qm_}#%{+4J=%9W=i`{uU?V-g*Q&Yke zJjz$D2ric39*+FNmr zQq|88!?U?QOx`(i%9I2{c?}&S7 z|5yqmR~9CcF@1Mx_C@&gs*pP)n|LW^Z&4}#&exflcJuVje#Zty42IiU?5;_rA85zUR+H`aX!AtezTt)c+ph>loy; zu|gGDQw3xjjUi5aP)6GOI5v1k#HSr#O1P3*5p}BKpU?!7th|w1tz9Xz1W$AnDpo$a zox6V*JA@ExQERkCj(fk?uh9_!r_+mfiDgxG>q{@}?jp#7G@<*$+Y6dpwikt?9!!s* zr`NDbO0Qvv8|r@Wowj=MOB{O*&mNGIbMwJl<^Y|v%!A*r=cDxvLu z6e3hxpSRH&sT&am6XkZc(Mg}q6FABw#*p(J$!;@7*d*IiX05(WlFp}3)sfUFaPt2> zvjPzha}c*{(gOFN4;l3!FFI<%;{j9#HRUpx>X1J|&S zClot>kUxkTjg1J8==57!uu%~ScOjPtJn12UeZSD;>^10og1?siW@LgQOWO-Qi!{30 zqHU`^)-|^pY7j2j?wb`0B{ju(#?E(6^aPq6dt{Izs%-j@A2-dIPxre^gob!113!&b zg+hw`Laa79zKFULibDx%k^EoxGZOS!y7{CC{sDDQBC->aCrmjS1pmwv7!?V-@mXaD z7r*+fLHc{2yOx22vg#@5f1a=W88HaUg%TR{=LMB2>@SIbqLxitvw0i8c~j|kLEm`g zP3z^BsL#Nye5rP`-ItuYYpjxTXE=Q8vy$zJ`MjQE>Bg^yD;p&iy4IUmIEkfJi`3=F z(^csi4}{(gxJ@1&>hg^rD;R^zFFLT1rWLZ;jvE5SDXkZHIa4I{&Q}5eUBG^uu-k{O zr{@ccU`q|?jaV_p7h@0J??-bAmYL0kH4FJmG>Zt0F&RHQE`^N+TILo|Ph7P6Tk|dn z^6g3nilH?RGktQyF!V&|UCeoOs7FKmDucf($z3@|93<@OSe9brcaw{6OL7{&Jy_t@ zxh32jdzUc2iXUCu-!C0+RM<5@fT5eXjvsV|(uGmkImAkb`A;;VwL$DkDJ14}_W|Y1 z`Fj=Na@u9u#((e3ni_aip>$-ROIcTA@kVIW`e#Onf$ycczB!)E)S_ndCf^ycKIH2s+zhTN>nd}J%kGYG4@^dJ@ zFIT>69m(^xAXfQ@9t)FguzXKRy{_q#&Cx2$4Z-Th?rF;z0QGmG z-8Ze`2~XwR3Aiyb-AT*vuinBZQ4NhB{d(3zpzkCmk|!APG#rK>xDu@Op#j?S5y!49 z!#^mIT%yMpseW0``(D$%FedGc6N30ZWkd5oejdyki~JXukSOA{x9u|o{MZ+}(SvSUAYk$`?>T&++Ou(H`8-OEGK4X`wk9g&qQe>R6g$u#Yp%lp>-AWDW>&dxi%Lj)?A!l^n19X zkCsQBtgCLZO#kF`=g^0zDL0kpX+dLjU=ng|1`Um>E6&ARG0E}i6ZKbiwFw{mGYNDc z=u$8t)z5#Wkwy~e_Sau8>n|x`DQaUG+OpOhl)Yy6`5g@3l<`p|ew>k>P{3r`%7ffF z*xH~`612Rd;05Y$TFSi^0Bc(}wO+(T>cg)o9+VINxVgh6cry|4A^D?{rNa`}eiiIU zx1UYegzzk^%tzutJ~7$Qxntlq21x{eXU_Q;oK1Z7?r|+;a2EV*zp&Dfd@~A`tn(MX zy`EZpWXG@;X-!OJ{cRziU`+^9T&26evA7wdDgHkXLU8N|Etv2~E(ow=5b~nMy@ShO z2$m_sd0BUgPG&cO7wFh`ZTspL(*Rs?eoAWaSPesDqE7{+pQe!m>@4Q?GX zchx7`|F^_cYmg&dLdfvXqXzh|+zWK@bf05*9kjv!4YNz?>XLPV4*~!@rgc-5zUMoV zmq=fp+cO)W9a7<0SybmHAOQPDg>+tWRv(uVEPR(m+tHluH~*Z`<{P78RKE^VxOn!5Ma11XBISl+sa1<`Ks}Zzf*lWF_8GVsd=YDExb~tQ+hl&EG05 z{s$55umM_78ku`Wkp7GCUN<0w$S{Zo!+#$w_BD1SK1LcU#8dd0V|U~SIfThXXwrK` z-1@0Ce|gUl;|#dP=^MVUS5ra^hf2RnweC#uw3WPg^{nH{)v^){ssYI4pU#TG^glYxbolNBxqz;u7tEyqbj=MdG2Z}u`&5EU)R=H7Q*Me znFR4KBA%ec77?fW{fjmb|3X&d{(PAMc(WB+^}fUMm}(I##XtX|!O_+v--8~U@BKHn zRDlz*B}~UdHNHE)xFBX8vx%8nz5?G6)sF@hnVLkhQg!Y?>};DUwSM8{R;KVy1i$;S(b1`B*9_PktElL;Tswu zNsvGNH&=8$t2dU-s${uhKPJ@dZ5(Wwx{eLxs~M#l7zmY?38mY|J~PK^43YC)5{D=^ z-a+LR`o=u2DMWrRjiUKm6OaU1K-uBT`$eMK_sxMs{Co=zWLQq}`ZDV~$^HvL01uNw z&neQlP;Ty1=GYYY))@@VmS!1cGhjS4CO&&DHk`VX?PSI5NVAf&r#MfuB(Eb6e{>gX50rZtqy0jF|kgwXo-1e`%;y6wG z(ST?tjNvgDr$zW+>Ipx@ks4L1+MRAzdaAd#e6aVVjeCw^726SzDHbt^%?t`WXb)Kb zW3fcK(6>*}hp6t22hKOE7p^m&pEy6fP;BG6@<8!0Tlwb0V+GmfWU;R8WK^mleC5tsQ{|jS;VR>_7KtkyI zz5nnaK90Cx3C}u%gRftqtDO>mOi?`an01!ud}GdmDNb7D#k8eNb)zmtHrb@iNy=IFE8bIEDG)(RpatpU;Wx%d;MVeRH|f&sLNJTscR9P z;P+mKbox+;T6yDgz}~@D$z@H`8pYqe_mhZPvc3k3W$@N`dH1>hAoc7f&TXlHytX*L zH8g%i%P)Ck)Flv@tVU?K(UY)$XS4P{!qq>LX!@`v_r`N|o-=nqeuu{|(Ig+-SY1Vh zQ|x+Y2Q>5GJ3ZDN!x9p8m;0rFuiMLn;GGx)SvHYg{avh>`$Jb-uPbwN$EQAz<9YY$ zOKLXayo`Qj4}2|66ZDL4<%!ivDNih0;lk`^GgvbV+La1{PEq%kC4U=lq1x)~8wQBu zpS9_mX$`2P_VHuVlG9(i^*@4F9Y{>j|4;(U6`WB$m1e~mRn}eqKCWJg{ih_%$DAE^ z+udz!N|q&U^^pxicWDRmsgk~eMK)DHch+%qPNA^x|M{e!z)3lbV z5VP@>DP@@Nzw~<@*UKlOS2=4d4Z)X7HM?w39tS-#KH)|KAG5xrtbaP$VdFYBDxfKB z2S>FN)SamC+`D+8Ys+)(i2=;x%Q+n5BLQvxAIhJO=!sk8hsb| zDEZ-V1U)7e+HFg`M^J7{DqRtR9-+ZL)xi!xHmn%E=9zoC^~Y6q@>2$5E}awUz%(O) zY07rX7~o8^Qw=8ZlX)Z9%cX$1uhkfK`W=QtK7)YaRLsU(kB+ie=ztu#qK9#-KRS%C}^6uiMdZ$9`Z;&z*u{MXrTkHe>FP@-){s@oih z(b`-})s;-+1qL0-iHn+FrRwzQDUrrDM1tB)h^=wT(cJ`@4&SLk7kb9?w#NS>4?*6B z?M#+?#+?RoN*rFgJsv0}nu2G{;d%4qp!CU(ne_qMAdZ>8%mOw8fj?luX08XCBbYB7twc|;33k>rI~+jz9=L(qZ;c2fzO@)VQ|Z{u zo;S0wc-q(fot{D8H-M|pdYL995)=(_`nPd-+xEAP;bv)_=)2P1hn?wk>5kT=|9{kx zP@C%QN}BQhLgV{Z?6z=L?;6C8q-H^l%&h#$o7u78!b`@~_*Cba%76+iQpvdStY?}* zHTXDftuRcp@$hhE&ax6K=*^ zIC+HED$PAW5MR9y;~%6@lc2e9@}=;hKhxE>?Xbt9l6?9_WrSH$HN?7Y16s>Dg1E0E zgvjxU8PUntte(xW8nHgjFtT+0)bxbFb31RwgE)97s2swOvuOoE(5T;c=4aX87qNM= zS24~~T&6IqRohHwaGl!pr^r93HXje1#^Ad28ItD=MOXVI#_o@+{fRP~@K-o$KslD~ zYDbL_An{xvLEE}YN%{>M)!Qx#N_h8IdF?vMGL9{#B)dYWm&p|Jt0qKIB%j>h`0nJK zQgqexcUhmfpQ!iB04eVIrd5FN8%|13au%p4;CmD&Ys;~o6Q>X(=*}q9ty|?;c`6Zk ztCO_Nubk-b<1m3CY=?f8U2iTLvU@Bn4qcl|xN?>Myd?evn#19bxG8aU8Il;j_ZG9( zo9Xf8G_dh@vygWm1uF)Yb!i$BbeWff>w`+sd)=73OAk-c)KdI-bQU!?LKS3-Gi*QX zZ`r=xQHgGyH!F+PS&ab|XZME$Rci?qUjAt7S?7Mot7&Mb5_kdjhXI; z^Rp^S9roe2^*QJmisjU}Z$3z)r z#|)|uf(O`q32Mg0D~O#g3j+JpdY7TENh8#}qOZ<;LNO zd!*-*chI5$8~w}0^WsG=1U#|y9l0)M&{AloEEr(QT#F#w6RWMAwXE99#x!3Y_`=FQ z@e{JEQQ%eBLuD}Yjza9Wq0CGd3}SGNGUWBcK$+iMYl=R7ds{UJA9-WYtG;_%zw|U! zZJh{>omf&^50ql3=f>I1;f)VzRfZcR)wXKN!#xiVgFf%olf(ZroN%xV#uxX`%INuE zNXoSDiG7wQupY_dkoLEaBw~{g$VZWQ$Zz>mhZdbF-21USu%dg$5B-!D{LE`Ok_HqS zN__BYxP44fhB)jr|_7#%G zoWIqh81QYQeTDeQ;7DUmqFjUYwXWLK*`~0y<16oxg($?0X{S$EJ$T zizJZtEYIrVh8kVt1qZ!k!8lTm{{@^Ljv>iAS-n?-oOj zh^YaG7tgp#z_CpZedX($tKg)@&_hY}=R`+8YnwGJrqpDqWbGd^n!mW!Z7BLn6`cY+ zlKF<1!vJ5k?cljIv(p?{`4;WncwqDZIq&=s@kB`){c`=gG!k)#?#l(hzfo?u7eNrt%x-EK+w@!JS}--GOJ z^AF2!LWc|9AJ$zsac?;p5^t>9r+D+%r;Tr$q3oQvdan$iN+dMh3#{)Ct8vP{VM(i` z&*D1?v0wA-D{Zed5BK=6#kq?~Y9(9awBs$sq1$XcfhlTh+??zCcp8mX{7Ou*+4b%z zApjcpSw&lOALN#R_;|~Cio2Q%oIWay(-M03Rl06}*olkOt-jp*RVck#sJ*+=32c17 zM83@z)}>?1SEr1_ag9?v5JxjnUUkHED#1{24=+%f`lA$PU2A1scJYSKi40;vZBCz~sH$3EQc7w%!@b$GS5#Ls^@zzKNyo7#c6QJp zGr>{IHYSU&0=bqTKw6s0smwl~=$V^|(6*1~wm<%vK+o2dQ$t0pId; z32MKi$p(-X(YF}=^w1?#D&qHkvbk4iW;)evUaP3^{AT?f3@usPM-O`ed6P#VYSJT_awRs0) z8!`vHvgt6t$kFud_uXFqO46NdWM@JvL~dy$!3I#;W$vwh2LnOcy#i%3`=BgUl}Ie|-ey2Fh2c1;F` zh#gij&OL}&sqsANfO9tm4KhL`GfO%Ep8ir73rsqEL*k2SPk)FIn${_lS!a?{x-LK* z%y+$$HPp-`fB#TviDGx=YRa+K!TF@YVWLartt6XcMYm_cylU|XmDwH6FwooNn(I+I zTxqV{+5S+bqBN^l)jg|c`(k!>67P=m*k#HmyZ(!5A2G*<%kaISabsqr6V~j?uZT-$ zEQ;}0u-kkis}%i!|NL~(B45+v05chId^uUU1*#hcx3P`1@x8LjWjJ5>Ir8nUC0aXj zJ6(roOuojwd1P6R%sznd*oy)E$ZY@nv@7gr)cfn$%-(Cr2{#VFfuCRsT!5W3NY7;9 zJAn7+Kir%Syy>&W>w#H1n%{ND-XqJTP|q_VLT2(Xw6IcK0-;87DU$+avTDpY0VEf}ihbx*~ATE+5SNB_c4`EPe{_*pb8*pQPMe zHvU!!`%ql$=0w5EI%{;jtV-b0q!da~8Z{pDV4JSo>0w2EntM;)zIRuwmVJDPR`gB0 z5dD=$74^DaI?2&Go712lF))0)+B1ZZL}@~1L=~Fd ztN14BI2vnClT5~T4ATyjAJYA6Wpe^JZv1}y_5lIxx+)fNd|_<-6f(4l5}3S~XR+(? z{-Ww?y7A0?*$Xdq&j4FyEpn&Y{>ElI1*OXR1?GRW|8*7c{UZFT=NX8CS)hpTk`kK( zGzcfjA?r-Jf`FfWpjDibB}0gmh>FXF%zNlLf4%CJx8f>1^cx-Z-L^$VT(=&vFg4lZ zP8v=DdtV?j5pe1vj&40@X-LZ|Yey*Ws2QovUO~u|1W5M$_mN7tkMu2_ze*H*)qfj* z?DuJxMVMrsAyZ-d1$+19II3)T6%OPibr1tALCZ1C8a4E4HR2dt|KK@*CsRpYuJ^|LJVsn(1wG-QDg_rjxLh>a zKtk!y8^W6)Ldk%!f#s|n*T;vZxH^)%0m_%F3|bUqZ2m1_Mbt=b*hq&GxgCA;ZLG!l zJM949w&)<#11<@@SP)x7&%C_b8$0x(%`*?G8({YPB2nhf!-B0Fwd~0s8Dts{)*B<= zg`_RXN(TAOS{55HXVgd>NSHqP-P8PzTP1(S3#Ts$`^{I7!y5N$58DYXM?m0J8p;|XZm>` z+so+$%S8xqUk(dQ660@O%u`FzBHwT#+8dJ(u!kFSpkIb4D)j(yR?NQsy(`EaJenE& z$9Ls-B-g*A?NQ8KD!iPTwORlCodp-mh};B0sB&QR4>2{IJdLgDJ!LIwxvOy^CM>;S z48qWNDBlfxQnMET2*&UhQ%~@$U-FmtD+z!#{)>oYxOaJ74yTtgmLYC5mXuhZlh`}G zt7gd)X2IK#u3v^wDg&9VLeDPHHRjP&fB&QW!ue4b>l4E*)4l|==hrrchCW+}-V#!n z>eqgh?-(-{Z9dZ{;koVE;yRo^%XPC%sp<%I-4N=KXPC*TxgLiuZPP`yn8WKS{ACnT zl?bxVQk1R#^5K}=Y#!>q%WtkH7rM_wf;5g?VD)w6qldqa!?Agob#HX+Au9P)fw8k@ z{VBm?jo;}%A+gEXS+0DfaGZX1J_>bv#tB{Xs{Yo{Ztc6)gcJ09e#(k|u?5jtkW6I& znB)D=OQir4lu%9hX8)#f9W%lZ zWx*;RM=*ty(FS-K$(C_>A164z()3|WRopqbQodf>7KX$n@YBfFB~;-2-|~_sqD$v= zTpun4Zi~PVk;XtM)aU!>i`x2kKZ;0$y5+Tk+V-*?LTZytwA9irm{T)n zUKLRO>B&uUSIk;wjvLQ-2{iBLie(NFcTTIdW^1x5bZfl#`LHFBp)wunSsHV^#v7q) zbi?b9WTU|al5>PahJ*M4GhzKw#xBIUh974YL8P0P-w*45)wROm<;LhAPJx#T65H2& zm;}fOkK)nCEk;i{#wEJKj(4NWsO!(gET2HYWJx0Z1fHTO@t}2Pn)MN=I$933ro?lc zwO>7xR=}#ZU&N0(`a3{cY^Xydb4jc?>6MVWi!6eEbAFWHPR~{?>Wk_mcXhLn9ZwYd zfCTVT%r*^8xj=?3b+ql4O}4L8WZ&y%R-s12g#^w| zbkxRN2P%m}ieBYGl_E{8N~ zLyFrEUkdz~g|n&Y$D8bg&+#kH_$MA-QFD6ek|`>geLI`qc2+nZ)@Gsp%W~!s2ac!B zv(h_Eb<9b+1=>fe&BYs5$v8wMW~;NQC8|vTRCL)+A-eXMjmrsi%n$`=pZ$kn?vDd_ z4|1J1=#)M$A*2&Byp(;GIvVY`qbgPw1c|1=M7TzZhWMh#OteU8hyY*(8)TyHDLjsf~7fZ`AAyk%}a@H-$i8Q<0BU)>W( zTexRh`oilR%6sAVg21?XKLztYB0 zDQpfqPm54s7S?EwvWxqa9(_(ksow826d2N9JW52Z?|Qo&^fssZ-w1DUHON&P-J$!`C_@VzU# zI+bn*AGvaP?W*nc4&URt{-g7iO-p56mU@e^Tu{;64MGzqc^|6UAYT>vSIq}*>xU+% z)1@XSW6}T-#P*Rap4WvyUP6v$=v0Tp<=&vHk9QM@z4^KN|zf*;4 zLChR0@sPQZg;it^g_9shsg@PANIU#+D2=~vXo{*&bS#0!{;AAK6^ogtW({W1bGr-~U zTK>Aj?F;MHFBe$C!>~Ve4T;yp_*bh^=3mcE=ip_4=LCL8*uazhcvpj#=uskscZEXD z_btWFA!P?$66R|mpZyJ@tB5pZP!P8v)b5+_vBgNYvB_AzNym5)X!gS&3A>2BONdsR zp;MAC?k4%(m(v>3vvtjR2BLpnH%iv7-s`*l zOQ*;%F8))+@pcw_(`Vh$V*YLR3&*XN#ToTVSDI>eFPMy-Aku#Fa+ltGbjJ9CS#$^? zI_07h8rw--z}2DdvGJ1zaiEbF^6TR&g%}u9UEcB=OHEvXC@iTglZC55d}2IbH5^B* zh;=_$Qs^qW_WM>*e%hfZ_x7cxP92?i!!k(juN>=sWslKRqhf1`&akfL=sh<`#kIBh zme(^YKU8skdsPuwZt%3VY$lS0-57&tE=#`2EN>EIpRGUHC9IEfN?XVHuOUVhyJJabaK74fYZo(kS=4nn)Qz; zscQ-O#n`&Q#ETtncI4W=0iO)Fzi8_y4_Y(hOt19NbIY^Y!kg}JvC~H@#COL%JJzR( z70o-WJH;coZiW68UOskX>DZMN?LjDQPae-nj&sp%@91Z^h|*dKx+!qYo(1IO%L z_w0FV{CbJbzHKKi-`lPuiDA-6;}tp~HNTg;yQr5zpngzSgqgiq?qvc)UElaSk}`5- z1>%di(b5<{xDin5m!%c2;#x%SW@c{Xob@a#Wqe#KJOgj?M4dKyLg=gXJ~P#&Tw1Z) zX!;@-=8^H@xKVNjMX{$G&wL`^S3sWgH%b*Dbve6qtm4YzCC^$@mv{?n+X(++7H$c&l9Ni4`Ext_O*G!#$;|ld z64{l;s@ZYJsp#QcKFC#zGxbh0F6>nJXowSS$)RKAUV|>(k0@sL$_-_E*N=ikkI-lv zJfcCUy4N7X_WQAi?iU{Q<^T24SQ#1R+nHI>8drOGLD;Q=w)CrTL%{K;6%`KpupBMz zCf1#wC}lU_HvkU5^My3oG9OO|mf-@Ou`;gX!_G@L%5WRzw!nbvQvc9QxiM)S1^RI& zL~z%ls7lXqUh-UqIQO@qXrucyNOk#QbT%}%jV?8I|{U>p-T0#>Tas~0A(s&5P zj`yO{lfd@A>3nj0snkgLkA>q$Eq@>%CiEf7;ZN)gU%9p%TR2Z8m<&T~jFQsa)J5xy9}~*#dBeFu%PwZ&&E?B?0o;GrwE| zAlBGpoRORPAx;3oytq5(^L4yopQ0p#bp^kbz<-SB@fZQpKn!BGSQR8X1f^`VKadlw zUi4miwx8j>VuYKb+2O?T`Ib6BZIk1Ri+OWk_)OnI9f%%(Bs`-)`?<p+NuP5yY?P zZqD!pKxNhUdYro-+F~wbrtB3sh4KF}7YV5MjE7IbcwEOibJ4nDTR=IuX*6j&HP@slIOkYsgOE3Z$G#V$|WQ0h6P1PvMnNRs3I+mwy+XmkA^&PFr- zlB=t=dn-P!sWe2voKR6RKF%M|aACaR=GNFuE#8j2BEuyco|N@vYvJ_AqR&$9;E3P1 zKogN0U<8lkXJYK#2MOMWSn$H&aqD%T$E&S=2k^=Nd`NDJ3~ z$C|%o!I<`c`|)qq(FESvB9T7>F=#&TKEdEA`>DF6Ls5nC z?wl2_b}2x4&!Mu~JmONx59ZkN5*KgmER0quij_9%MJ;>zw2p^@CeUU0%O)BWmOp_3 z&myV^5;&=jT-Y3zU?$u9y!RISoL7w%c23$Mar1H|>3EDpC2Uv}^4{?UtLBrFP1J8; zj`twZFTj`U$kX1?^84_x!vHNV1y3^&Dzr{b_PFGs2`Lr#({`c=p*DUVw@f%DI~!7~ z<}znZ^5V7CSqPKBg)pX7+G_4dT%@H&s-oJV9cvGd`s>RL)?8L?A5F2HjC6ok_y z#)$#Z?RoGaQ~9DKYmJ-l!8IGs%24R`_x!p;vwn{al-NT0hsk)&eJ+T&hsX}*L@3VH z4OX>`T4WJ9>w{wVa7*?Xzvq=K2g0+&rYGPzSc`N*GiT7CyO|1ymDRl4L2bO z>nH9M%T~;3V%+|;kaK&f&d-Rc&zjrUt;dpVV?IMU*~#v(X2WhQ`?IgFdUbu?vHCwc zT7P@95YIU7bn~UXcN4vYnsQ6zdbGQxa=fArn!`G$Nuc8KfDl zYx3>Hv5r7!veKdwIsAQG^NoN6k>+VtozJ=v@+q0h*1v1S^fou0L$BQ|rMa;|8+BIB za{b@sEH1Ef07=iVieN%;;67EzlHaTeDcXm!^wzPmc4>=YC6k|sE`pln8!NiwDmXU} z7la0{0nYa_>8JXj|66TQ>k%m)S)X+}e~ai*BoZqUqt?ET7~8k#WWMlVP@OSYA-5fZ zITnjtH{-thGj*8fEBz}S5zgBIR^<-pdyl?eJ`Mfd#>|;SY0rN}_kdUG+HtV#3yuAq zQNqb+i2cD&5AUw5Ez)D$3jCRHG4MK)hWQ%os6owRr$u6IPLkxduX_+#;1?D?1b`2C zkDddj=9M4${llUDf|^f${EO!LNmUf3@>8nKWX{RdDJ=g-oA7gldho0)dWDl9^1aW> zDuUDH02v+)@Ae#M!MJ)ln&!QF%EH$VU%tUia8)_{&tbJ`X;HAIOTW=1OI&thHlay? zhb6|cJ}}Yr#pVUKB5)?j*HVAL=C$BT)HaM`OciH!zd+X4+!M=cK)Le*5gzVEk2kFo z*;dc7E)z$)#>*dl;jKOEtO>E7IV^Vbfg3kBL-K#Gp$_();^|JNzjQ?Tj_Ws89s2@! z@pGJc>#Y3zPgh+9Zd+>>0EOJelY@8jk0uuNNLoOoDFg5VFs&W-Z^Ch-oc@MH68o+o zUsK1qSEX1GG7E!yd_Y)zj%%^r@!L-ycJ*Fy#MSMX%|q+4X-;`YR$!E5)KGDdn7jAe zhECfqK~y=?;+mh1d`&c8>|byb`vGtHdWPn zx?oS1>MICd5FU%>z87O0%q=^+RR>_hZGL)E36>$TRAmA-F}^Qq3bfUeEyegO+0}LS zHU6=JD=q0>A(c0y`h?1Fw_Pt1tXO3GtF_wS_k7s=!QVySOF4#9{jdKIA1>Qh`Ms6{ z^GkKz6G4j_PaafQCzVM-o_tn$qbzA~5T~@%-Pv>-aewFDBzzCjHTGQE96<({LWuu0 zoYTW)d+*$ZwYidjA_%lDScdj{0*di)2YJvuV42o}K*b?AeGD>H9j2oS1Q2sgRht1a zgnw_9SpCx>Bf<7R^-wBs6!$OPw?Lsbr{#nC^X&$t0oTv>9-bDbQ0U`C0UB#fZ)Rt6 zYv)}`(I!J=Vzw1G6%<_}IWiub${-Fmal;3EmNVzl6EH(=m!ze1c<=$|`)igCe@yVP zA>JI8^8CMeCoN`b>lBaqmr`y_^+C0!e&^gHodaV}%s|+{A?D(aDg7vc13P4wKyZJ( z==%L}r2~6BAU94gg^~6{!AOMhOCp(o&^C=g27<4#t&16LQm7JH;~wcw*@n{g+ixEU zTSxfbEXu#;uho}-?eIfpzF~!6#S6JAgV}m?&l@~r=}`ReZ%G~6Ezg;(bBxUPod6+R zhBtDQw)mTr6qi2187>YG8aP$odyrT5*g?I4Uar76OK)TngM^LEqAu{EN8kOou{1Di zpY}%YafMmiRW`Amjfe5bj5AsQckauhl@M$)56tHUYHxZjjrw?{PriIw0hiObq4ykG z9e(ti?;*iCMszJ2DA~;2_iDX~gt4zXBtL*jvI^G+!=Pmis=0t$ns488Y@9QLJA!9A zHr1_%{W^wAU#ymk$I~h1=uMJCb-MEY=Jnh_C7VEzAC{q63xtK)$GqM7psgY4O&BL~ z%G#BLxmje^d&UVwm;T?v3|i-_^9Z6~5oiTfxHgDpZdC2@Gb;}ifD!Q% zJsu)vkw13s^gZp8-r$K0>1p5^VL8M~-q`#$e(l>K&ux-VXYgYhXPSjNR(S?fahNY} zymCP=8s?5OmRlaLH5pX^H?>b%hI$*o26(flLFo^xnWWB4bP+?7_k!OebX90mpAkH zwO0$jpDFaN%HsBZIj;!M*mr~hva_)ZgqX)Pi0xmtsA-+$Z7c)u9|ToU8MIN+)ag3* zAld?*h8M9Q*0O(lvz6sKosmMzRI^}SVej1Mp2dzczAqPyQssG$%=MRGe5_CWB;B8- z@P;i4#UMUq^qA-#yKY)BMSOYk9CSO`cpqT4?-pVdIdUW`dT($Ao;p4r6;a$K9&`G6 zp|L&w?qmM0K1fqp!Y9Y$Bg_1VceHPh_ax^~_Mq8wy;jg^R5}pnvPiIr=#+r(7cFwt zH~)-(UfVJ!FvrsazMm!G4@Rte2chV*2ztz7EO~70^K0!|T*_XwpJ1Tyna6{3*&y>= zc7kP!=-6SQnzh=<>b*Rbi)T{Ia5=2%@(p_BjlL9XORL6jtP=@xf3?O#c#^9Sni9WS zGWkgQ0(66K9dRyO}&w ztpDQHCzp~>jyWp-f8tVai0$hbw;IC}nE!aQ=7-jBaA*FHWE~z@5b%aE~y9 zD7C$_`A&aT;+Ik0qDzApB*lIO_yEr}z38zwDr0mSP-G=vjq_xn=>QrnMp3$w0j9aQ zKx@d^aWqNPM2jXIb7J5mW7B5-xUS`VV_B!1V_n}y(B9S^edJrdVkK%+ZRy36&}XI> zm)+#!yS9)a8Q-v?AJ47AyWjmH#=ehZV~yX)-`z4PMl{9%s&5q2llQ8d?y7Ix@#N_* zr5pY7wdwP$VCj!>z>M3_`Ip#Do#iva02vFvUqJ=Vh?R@Rrq&OGw&D!N%!y|rYjWj_ zQA_Nbc2s5NE%meZP&RHnB)jU3V^KOnT(w%(2>2+;HDeC75#*&pp=nij1HW@zQvXECL&r*Im~9D^A2$8bsS3cs9v?&iZNe)F?Tx9 zSAdV>4M8@cXC%1$i2dhd@G1=!hxxx6^Y{m6{^PU`u3OnkK{~XweA#(^`nGlX@f%TLu5_I0Ke3S6Ww)fY^n%=rl)XM7{zPt;4p>HVXwk|PF;_zzV zif|BJjtQGx{)V%F*Q}BUwWy^0#$KFF+T4*_f)Cp*`-+;o%#xei;2>{s_L3UQFhPMB zxC7!iR(q=diKUay?B`M&+%UKKfe~~4BUullc=3cXPja0o=dVOA*39gDBi>_F3 zGkugyycB(p4kaBD##m`exA0iz2I$fcsDS}>c z`iqB5FFVWTTa?hXBq_QOTipLNQQ z277yADPtFX!eg!z`is#G-szmYTi_&{mRRsfhfU7$h{2#?Swfys*C_Z}<;8}C8R3~H zDeydAzaQ>6#idVZP|`CF$a>$CWAY&-3#!%70`qY_dqntquY~LKJ1B9zBfT z(2B?58mH!4DQvsZ)Yb2|qX)bmK5OAP8ET=AFsoteY*j^AL`gT+`b_tS6p{uSDa>-5 zTuJ+lvReLjc6e2=Fu*o)hsSB|TG!RbFX{^3C6t-udwitx3K3qC#Wg&;)!preg2~>Ta7svHM(YhVm_i&e z&rkj)UL)$nn1r`7;MicW+t+b?$X_N%$YP9T}1sFV6iI!+WuLJ(vbczxEWZ>D`!X!1%@QqW}xv7Tg5Q z6JSmIK}nCGFX|{Gz?C*j-izs_Qas^|9Kj|}fNOS(aT4KQF|0jfF2y}g7hrBc`z;L? za&|}~pC8`VkAljJjzsgGe2r1s>a z)C2n?hmBQRDvsaUi`RVaI&Kk1mB1b67yW-tc_5I=(D5_O#tF(>zW105a-en~V}$CC z-7-2t#iX+;87dfEZ;+Z4qzrtK|7_5ObIt0tLc3@0K8s_57I_if54--T+|Y@mhlrYZ zfr@O+GRtW)cDg5Z0p2wNFRkD7&^yV~@-pY&TTP;oSm(p{qGWgV7&U*QQl^FQbyKux zW|{D2M)=YShv+4#oJdG+y7cBSTEBawb|Uo_;ac^I>x4U0FB7NQ2aP;Qod548O{u*< z*^sjaM*0A`GcI@NNH~oS&k^CF;JZfXZxb8t%rLn^wajBI|MM2}c!89hT{DpellT*M3biep zu-nqI3Dq^hMRd0id#eG%lk2# zYP*w~BV{MA7u7|PgFt|BraB9}+6{*>*~5C0XFUIsK(93ynj5P|mS~#tTR@AeLP6{} zPey!y^&%TSfK@$#0-lU1_2MBC;y`FrXijUSL3!v;WJo)nMe>}j8o+ujiVQVL^7eDk z2%e=qYZfVd6>-EWigzY_N0hKN%d4=rz5fhVV7>VUnh0bM)a@Y;pyMVI+Q;`YZ++5v zw#O3TdXj(rhq$*Gz4?V>Vqc=KoB6YuGB>gRMw*Uu3>74pPe6A{`wKp{;lnIF6k4Y{od@T7@g$aptHlz zmycaAp?)WHv<;{Rpa09}Zf+$6Z6~$G6@-C|mDhSEjn0yVH1p1Pe>SBhd<#%!tyekB zAhEkoqNSlY;-Q2Cbv&26b62Ay*;mZU{HlpNr+-i3`tdM0)sf*3>P$|+54wo0J#to< zA^VL~4#Lq@H8=tN?e(!G1Cq9z5)1NOiV2(t>Ue>U64a#{ao5-z+Xnq2bOlKc&Oxkk zn#;_pDIq<&q7Kx0SA!a9M`54wy%0anzJlllDP8Iw)3Ewo3C?{jRpl(VqzcuWIL@~f zulB4=*ZFlbY(cv#E6!&dI4X?Un!z`skdYv_IEu*DHU3+>K6>eS{KlN@ICEm`Q;)>) zqrY*I_hY^{9tT-?*|{H0ME9p+U9oShzFJ}(5<@nz0003Du_b_hsV7D(lc%_;an~9U zAXoA(rfEagr`N!vThY?VP7*k5O7*t$*OE|tUCu6^n;HzdKp|*h%gDpCgf5Jfe1Vtj z&FJV=J^1AXOntAR<}7$q8TTd=;A+5_CX-R9yt-p$vg4!7w>4)$E>io*-&PZ$Mml2| z2=V-cU~s*J+NU6|H7KWR3Y=cpW$hpTgNLhSbRR@LxCzK>Ro z$i`SFX1FhFdGdz?$UAtD-dWa{$1}4wQ>UiPhHTR9`Tu#K;!ujHvP*2E&~$P0n03i+ z&w+n;9|`Exnap&_9$r0S{s-k)BlOVqh>dz;O$?-)0lH38K?`thGNO{N3uU25^JtPM z2By!WT5f@#@dUwo2b}d0Wql%Dd5yJbQbT{cpyt<)A%-XTC5e#V@tFE#O_t}oTD4j9 zWLgrymkKZwj>&v3Dtco3zPzX_q@cq*Pc>yMxy)mQ6}EExS6n<^Snt5K}{r3QCa z%X8!nQ3GV9lz^Gad(kM6;nK#iiZ)4h-L*Kztw$Ai05AgupdshIfbYG&b+CO57xmZX zXBn7!ZerZr#lo9H!op;o%VAFSS<};3hb9fD21f7d&{CUuujU#asRrz<@KpAV(ASsy z%xHbj!;1KTHuWiw>>Y5dY?Kxd(^mG^86mX?+Wj<(DqDxk3PV6nVLgpYDp+`MKfa4! zJ!v$a$-Z|{qB7HWS?7?sUpT~cc;)^D`P-{?xsIp08KJ+lN;rLO-~I9tI4*sHrfi*; zq8E;NdmIQ43Jku*1BoP{MnbIty`fA#kbewSJDW{O4<7pnVAgG2cX^n7E)bJg)g>1BLK9Ji)StkodP5iTWtI&68>redpHU+S+H!ub=mjrmV?$bbi2!Vd$(eJSp zhXf>*05eBzarw@hdO}@GEag)XQww zKXLtXFgu4?Ij>gvvF@*ba#eh*3`~H|(mU?_-thR&_o*QhhQ{m!k851{&j-GmMQ2i2m$|I3XU9&4CB2)gY=n_Vk|Oa`DwPgU zSF$@oUh#V1ZYE^j2S^jNNr)Jj2+!kyeYHaZo*|*p0Ra$bnszA%dA@)!HYrT}f^}xd zQxy55QDHD#Ka7w+cMPw7Z!fH>+TnxEL4R?v7^p-?F=Zq<+1NcIMqLZJ*;dm3-@_}n zV=079Z^lxTul0Iens;t#C$02Rg_p&hOutx2u79m9;S5yYs*X!@)#y+hp0~K(POEY)@c<^m^Ju-BBmKwz~+GGW-mjWPo z2ZRq}1HJI?r(n5+`=>{!@)CN+Lf-2VJ`(DNOHa@@Ep%EtQifOuK4l-JpNQ0wZeKB~ z?hBOt^3A?MVeA{-@@En5wm4?w(0A`hIZo5b8v>=V>>`R~YeiJQw3HEL^H1^<|hQi{r<>hp*jUA&ln zo`7MxZ1cfDSu!R~#CxsTT%UHfj>Jp85f?&Gq5t9sL>f&W2w%0g{rP#j=B7oLK3Fi? zjOyf3qhro7mhWy$7H6&CKZ9Bq0V`AA{z&C^n8=r5FZ+cuhrF+Jgz|J)qDtaZ#o{Of=zMY});?S=iW7vm>y z`}FyZ^XxBJg%}ne_lFymc7i(HKn>A35cUWGCVg)HcxZEZNQ z_awykMzv>%K>G5}b01k#^V^lbUM9bh0LGN9fkTtXCPm-`S-vU2+pIMTSN3DZd^jBY zj5x|49F6yV59Pljd9jfF!+ex!y=|pA09)+A_^VJK36sXT@e)-WBb>w52aN(DMT87 zH%c&{MM$0htEt4i3~9jcl*0VrMGaK#*vEY$nD)mCLLX|^yD`G8Z1!T}>+XQUpe3nk zH%%{3Vu7(r54wrVQMcopJQ4}V2g;@rsiv7l^kUiJ7SNLGM}KWO8NJ~l!}Is+V^{If z>M*6OBY#MQJ8Bw4Nu!zSKsQu5{(QI+9|BWOQqB=c<+7QK{i_|Urp;f23rW|-vxLuT z$g-X;@2?BuZ*jcV=56?LQvy*!9-(Y-O4{IukQMu^sK@94Cs!$S9OsuZOnR8EWb$-Kmk9I{Oa$E z*VH#;R%#t%(CopCmOs!9fETF-7NM~8pEvJ7982(YYj|KnRod-(_cjfoC6rRfB}`Hp zpuNWy!9hTK^s+5Mhk$WpnX}YxxBpsk^2Y!-eUUTqPlC~ah&cnUB6OF z^NfI*4#a zdWmOPd7+ynV8XTN05#svf*v;hZrpxVwu0BJNlJc6c17k*fjTN6e%ZzJItjZF?-Bdl zd+(ER-W~g%ZEgG-qI{sQO>?ni{JJeBqm=`j!aw$=`~^^HWx#E7uKWxrQTx}7(Ialp zRwau(XNZcSfV}n$n6Z?zpDdua;$xxa6!nfD@54=21~k_hv}W~ zvK+OOUzl+wGQtP5ekN)_j&7dg6s0>-zuMWQ?e%N6c7(&VQkw%eeROgXTpHi{$e2su z5&G{Lz z^{WCDLmrADq6*~&iS*Z5eTJi#zZwaUC87Zn(F6qIrbegkww>0x!bd+=s-Zs({OTM+ z3+pY-)l_&pybR)PZK6D{Lui%Lua7`ug99*P(ZRkC4YNv5sl1Eh8ky%W zPMV2pPW`|owK01L+w53KU}7~aQmfz7a76t?YY@koIoKt4T18if*L1k0HM8m4vEi6; zDi?jJ$W$wVz$L62tfYv>AcdAh+r$V;TIhKLTnBQo@}N*(w!uugizHCyrcUXzmt%E` zz~K3j$jc@jG=s%Ux(YG_NEvUcE1E&Hl=(2BX!~#Q)D|@iUBXXf8Z zooySxtHm>T|DvfjI#Zf+JJ9MBul+mX{I5cAb16>3J(U+!EIjW$jtDWr1uh+USz-vG z(}dz3qkig6klJY@e7d>0*cu7KjX=Gm5<%vmKcDv!k;{`e(7G>A;o7rZCu1_DHs}tY z=%Oj&n5(?Eb4}WZRYYq|D;P#gX+ZoeiES^*c_C%0 zTOG4RjWEvaX~M$@zTX=!LnKPJLgDar^_;{%0t%~#zuNV~3n6VpQ6G4L`qK|m-O%nz zpGM%DU;BT()JZ&{)O{Y;nG*$EUQ-Ee69LrJnaz_HwE_i~g>#^|ET^gItn4d}4`RJg#*zDK3CW3`U`}QYA=(K_Z%%5m_^0-oKo~<(SP`HBL zy$r`SjO5OESfp7l^|qJlVSQ6$DDz0pphK}%yxBzlJVOdY5~NdhJ2X>zLTi0tEJH}h z^M!ZM@71Z;sjA(WG4Mc!Rk0?@%pah|qzJOO<)C~)-e7{LL+?U=rrh6QLZ6!R>&>R# zSdI@`B6xl%RS9`p7>e?6&q~3GVs&auIn>|g<2h?KcPjG{{NG$LN;%0r`SCL^u&;g$ z+M;RR@wIi6n$^cmZI-Y#gZ84~@EdB|5P7(;a<*r-h}q3lwPgSUIpqyt=vEzCztchd zMu+>$R+dpV1B}a&=^q+fdnd2zywuwG>B7c{z5ZCbK~h$9!d2f;Db$!99u1jyGzXZ! z2%~n>XPns^Gy`cCO@K&9d{-0Qen`CGrn_;sH4wND7z<%S^6ci?2Xrt<_+Hw$ zJ>&5o@4FU)?7=0EJ0%Dq)WJtjN4qNtz&g)f4Tqw=bQ?_}B(xDT2=4jymNs``{Fhfz zVuaM_RY!??$l_8JM%wCcX^JZZ{Mt_K^D^>|gK*P{4X~v|D6~=jrj8aMUifgLs5X;L zZ@@8?C9l3f4>P9k{Y&G~c|L59waU8Iu?$QXvx4uWX%t)D6bY6Z( z`FSbH8V@k}VmPjR%Q#PH1X%_u*9p_nDtk8^#! z;^BH2GY_u0>ZinB>23EMlyl{lX2_W(KJi`lnpXq!y=y*8$E z6~9?fy`VmD%xroGxs`(;6o}|2Yw~J;M44_;37vSGaQ- zhSX4+o(bpOqF>jBIIN1G0f_|mU@=K@FG!=Uypyz{{qt%rv%-4=@6kHfVQ4kv4&0V8 z7Nd6OOn{#pZVqJE|8;pH$|inUR~5jZzd;gG{*I}extU7rD*MFdxO1sMLF>@h-ZiG8 z5FoMTnxT0p zyi0QXRiHgqQD1-*@hW%woauc8Sy4U49(MDbD(Il2tQSs5p&~kF9rRJ{cjon~YZ4Um zi0Y&Hr4k*Nzi3q6U01D!-bvEfimm?lyzMjmBo#^de0%vn!rLT_s6Vcc1}gZoKSVay)O{;s zShXBr9AYC;DIL0q79F%QQLsH;@bu64W5b5!A9aa%Wq%6|4>$a@#Irpo9t0c`t5nX@ zvzrB2H7g{{j9u^$F|Qkx3iT3*8%ZjcyA)+)ZP6C62pniMpc`py|E-AM@DA%XSF`JlX|c{4NtJwrHV= z+C8XVn@rB9Vw1fww;T5ly$3wSNj955g(+XM{yZ@r9pyucI7=sUEY0GL2?-je0?<=V zFCi7`r}#}cjTA)THB+|z4P7hHSv)Z3-E}s(Qk(-goR4G149!3Q`V?#6`uQ&Xkgza! zT7y-c*9@yhf0Nt&L;^wFkB|+_vft1z^kJ*Sct23 z+FgCG4D>YSPcQ}qs$1`l9R#gB(i1Dw!UsAeEnY$l%lzVu%?qS6-24I? zry(Z>sF<~Y4X~!hL!RLDnSwo0b zY$fR=j=LRlFc8Vh8U=%4{_s$6cg>;X0qcY{I1L~3t_XTlSMdQgB`&co)#GpVq@PMj z-gD3R`U+?hKwlWfXd{IEl{xxE*cOq@v1OStLv^s3+A&r&mh$|_>MMMc4dfiXSP(0i z;`I!k;?dDrIyTMvAy>Wn7eW)wU>dpzdXr0}&Jp(pEL-KmBY| zqvSr}UtLg_|Jp9p8N-EW{EpwF71z;VLQ!;h-Uk}1`5IG1H#ve_tjd+uRRc=uXs_^jx8A!2g*B>gMv{1 zb`aMhTF)F@Mz1+kH)#mN)TWq~z2&Ry zqSJG0#fo$Pz4O*B>NRtB&Y}R8b17X7ODg3!UQyVR3*(KaSa1WB(t`VynH-7^_ux$L zfg|lN!@?}Aa%;k%mKUQ>rKftxw*vUv^l-{ga3R)5oVsYKs~gZ|kW3Qgt1q)e2DO(u zlMb)=dkzzK=$ySodfcyNtTXJTj=i)cGIvcYQ{$Jv%({Lo_`$JWs^$GAxjxyh3UFR)Qq{7~7zqqZZ)Uh6N8$Nv9fP4@?6d=J0q$VHi>1%1FYLiD(P<$CZHu3Zx~ zeWBeQsqdkoCpr%3rGJ^A6(1#uG9+Ib^MZi9m1_;hk0HJb=; z+BHRBkZw*><~=1j@7_rzQ0WD&+XgH#(G>D6RaQnFh?mxRvN|&*1wSHxPeo>p(6h~X zZLRjdjPU=fr)OxVVxIT$^VN78Q4R+~Zix!IWEEFL?A;8Bo;HMP+_emIa`?Gh9zW3agmiNIhJyItIn zk1dO4mH4AC>>5qV->x3zgTRUGjx5>)^BIaZm*;K|=GztAhMt9ws~S52{G)d=QdMwK zyO6e*(Cd#Ihb2$JP^I*0JCK*`cFV)kKlJ{?@OD`F*s&(O$}h^hn2FG#pR+%@;3+Yd z1IcqCaW-I-sA)HRbfs$=Wu@{4!uQvP5C;^qjfn-pW6%G?-6Awx2dt($b?bE|sJjNo z9iIZd$3|o$KI-2QBnG9W|5XAhtqWEr6706vwETLs&~9O&zk1f+KUw+u-D-y8_mGJq z!&J*6m-+c~hx9qK>y-FMF8np}f@ZZ|LJ43l?kuw2xUI*75+&2*<$?(W$4W0#(mzQ4 zV^3ihJ=p(;73J|uhuusq^R;*Ay3+{>^m)~mN&C1ZnWp%Y3R5fgj%4?R|-kz3da#AllLyXCj$T@(yx2co3wlNs4A z57Hk%+v@FA2G89f6)R(j72R77#5k8!=yQ(Mogq_6+qJ({Vn-TsE%f?Yf1Zd<-0u~$ z)a&c{{2y6P1izwxQgbUoKy|NFBE9`&Ow95uA6d-nq)~3aAeGBM)8)&b!+Od68}f!C z^Vs;Qlm#JiOc{3yA-2v;UVsx{mlX_KyXfkg3uf@5*YtD^y8o9`p}WqdXJrD=^%ZIerV~&?o^{!9LACP9MKh$XmU*E@Z8zWOaUce=?Q=?tRRkZJz{(6_NUd&o7g4z$7fx^O}+MRkKV^l(a z6XzAb003|_zReofy`Um2uFk0*bhBg{27_+U`(2+*4k4RFD)h{S@Aa(jf`O3~vb*_v zbp*?`g79DB)b*47O!!M_A4!atBE6g#|0xVC%$rwxSt9+7Z3OcKBzX<7m3pQM;-4@u09cL8lOIUlb_r{NYT5B#NS^zIH&ly@C;eK>6-%fU-2@ampEGssoeY8`|=fDlJm;P`H}lM zn7kMzTQM)VX<3qXqksgfmezcv@U`e5Z5TucfH(y=$ZEH|v10<21pnlR{lf%0X4qI> zTtg)9Q&-Dvk~{x z)hh5rixs`qjZ5-}y@d|#94$?&hv0#q*A>W;lfJqBjf4&LF>ZH0|1h@$2InIZClJR^OMR(+>+XWxX8?mAbBv1fMSd+SI2fZQSWq85N|hRt9e~ zq>O1X=S0McTuA#4}CFLXx8%p7`C&J>HA$0u(wff0g zuAd(3`Tpt%++N`3D$BEXZXu03R;1~kb!Zk(enoNBye914qpYHS0+QFhNJ-z^&ow?q z-n-N+T$fc1MOAvk$Wr^E+jOFGq=I zB|R2{XK?Ylk4jU!IgUKP2_H{U;lrxDr4W7pr(!W9$aqz+QvR($XanQ@a)GJ4O_sQU+Gi-cu=3SGomf< zK#L+vzHR6^>s`3Kb4zgpaiM+(yt7*(Z%ev8HJd7GX~Y-;TO<<~B9R|XT{A>tCO{(7 zcP2vX)Zq+2@4w5}gH#Qr=&-&TjlAaixL9U3=zE>iWrlwww}}fc@Cvd6dAv5&t`Ht) zvYoWt_EF87Vq@;=l4{A{y|9gQcQ{~V@xM4!iGwBGX9?uRPNYK^wg#yM>-;`s_jbzZ zv&tQrvl`5vQC;n>s$rnC8R?P{`LoZb;C1#rpG@?i*oL5Td;@?WT#J_THbRAg3dx6VMIc3zbjCiI@tuoVRJ9>4GU1`0{&gRjh41D}c zn_#JOEO%+L6M4GL$2D9VtZ!L2yqWk7t{O!bZZw4mDMj2O^wbQYc(R)dX!^qFFhck_ zZYT!|L8Wj?6naRH&?1h)5ZDqKGPOcGVGEshV;!8`Xl>g3* z0)2VFaD9mW1CfUq2Q?~)8tSoA*mYxmNB)8s*SMYS-g%qP_oVW>+*bB!7l#xG88=|a zdnL{TS8*wSEm6#!GxtG3z9m`Ht4J-_&wPrp8i3ezoebqZb+1v@sDG}1p5rcDeVK91 z&@8>cw>y1Qb)xic9izjlj%h+UF5Nvtjv86Hu1Cjd8qn8{Hia&K1Q+0c9J_-TG(n20~p)h^|qpFA%c3=FzRWPAdUs30D+II@+ z`F!YT737HDDEaxnm^K3B3R12TWhk6M=13KK98R6RbnVpn;>s{FTPDy6dXo}JkdX!` z&m<`yRvJ(s;wQtz5^Y(VI3(Gsee~fM7XYOw+D~cyet-UiF!PhkWsWhF<2;nqiZl2~bX@1mcVT)6#qH;J`k8ew{-x%U-?Uu3Zr& zy8qq|?k4+Qc;?bpEDas>(1nFqB5F&a#$%8@g~2xt-gPSyqd)IkTTR^m6;{^P+LR zwB`lV2~%%ht_l!rz0GLoP4!t+m4`@pm8UQr$r_%rFw*h^V4l&LFY7xB5hjPv}vU$5?Tx?B*uzgmEm-~?FXFN-}z?~!eX7V$OU_)j%(V(x78c1}4Ku6J^qQ3SA zdT!Uly(0a#HHExim|O`s>m_)DKk~1dv*CVC9GT#ienX|J7QYj|+V_P!{_V96ZlWiU zsN}r>3R^`)yCQ`sy)LyL!)=ze{oUySgpgVXmsNJ4Dm{2!q#ZsFzCaWq8NN5g zLS-eoW>E%66K(zhe4!uoge1hS6FNcVi7<_eTh{Q}Zcp-_>z<35>KETK@m#XgqjC`W zM*5EZ-SMzF$8q;T0A;bBK~!S8;)jKc-|a2~^nv(}2@Ps)OVLEw;Xd8Hpzk{3?9~v2 z+Nx%(k!d9y(ee9{gaEw znis@H7ZM8Ieq4&i-iC+P!&KzFcE?(vv-GVuWmZzH-Ecnm=op&u6NA&YQov1%eyn`C zq@>;};70=y*FZ1hMTY8~p|=ZHj|T9;Y4J>K7g+l@dz{LTti+Iq<#%O}A}%X7w7(M~ zFEh^r&5pN;aR6-44Q5}`zj_VRp-djHX4d!?X%Ol)wfnOSfT+6-W}~ zWu#GJHwc$cVZLN+Q{}Wap(kCslXJFkcg|1fxl24LkgseL@RCWRHCn*t;s zuijtyRjw8ay0>%IiZF#{8cj9`8!*hBmj2cJdUnArYuQ_w{vvY$*REZPqpzdIcJ|Z-Duo0AH97u1uIR(QFuBoHU27XXMZV z>tPs_WN0oW3@q8fPZbCK=;_}f?(oVh-BQpnpcD(zcZrQ}E{`!s?^k|9w1J9aR`fvS ztK88lNQ2&=XzDfL3hHtORM0lvzvv>aw%LEI*Ev^SM-gm0E2UaS^ZlFjbIkU6gLsGUgc)Lx}8N!;o!cB1ZiaFY5_1Bm)h zL$Ar&eZZ19`+Om5mqML(H4H%E(QB*09=4pPsK6nSJTMD#+>J}R=y1`hXt;NY!2r4 z@K&<%IhOZ^5rOuExPleN0MFWCDKqZ#&F1mEZ{bx@OozIEB57krgVZ3f1 zIH-T6Pln6xjkav+|4DHRZ30~M$L>+?P2Ueg5eDv&<>E0sKio_*95YP^}uk#fSBQ#OGD=K@r=(eOboDv@WX-#lxMbWf()=@*(!SF@Ud)NA^ zKAMPXvMe2S>ix)lv!?|yp8RjawFfs!@AveI^pCV^vB)`1cxPI521=luAp{vrxTEbX zV+T`K?6{4pkslYCAQK~&XN9gH-BYT_1xi=$V~XvDuYFJiVlV4cQX1IaZ+wrC5__-m zcW)pg$gKUy?wyU2H%PWGi2k==-6H*wD zd(^s<1(1tr1XpovJU?~ph>B?F<1;SX5kjssKCtQCGBUsh!2lX- zVhKjZp#Zsv4`<1xw0^!ry8gA6H*d4d1$lwuq-f;<9G zhjoC&BWm~Z2DR8Pcg7Ft zCUNKA=aUwWg70~8Z1-E?o7I+>0Z+Ct->Spt7u&JoD_^ymC~~fho&XOh3VwD47BO2U9ZWJD&6VvOd+=Qe-Vsf;5D*J_j-Eb)5ANTOshg2 zPh5v?vQPCpNC!9epBU-xo!O6!jipZcZ6AL@UuM?c1A1WN)r8iGDRP)uYK{HHt3^&LbzUV0%hdAJ0WPNYVm! z1=oDMqr?Or?qH@~VGcI>mF8M{&X8k{=U_o&#!w$vq?Y0Lf8Hl8Z(%NZX2}t|C*K>1xhHXW5{M3^IiGh zOBH?U&O$g8Aaddu$l&cBnrc!2-Wn(v z6L%|MTwpi}&ayPWg{QR3QKc5H_) z3v7)ioy{49dy0~ z7gCKW{0RD~pJ?&QOaM*lcrmOMR9#)|pt#sa(mjYWO%W9-!Is+n50q@>BZY`f%~q{@ zH_p=(#h6N2zQ9DKcycEe(khH@a6a=^|32z>Z)hDBv0v<5=p_Z}TiJ(ldM9<9Y);id9XjPU9D=Mmv5#E8}##;qhtZq3l*{W~7VXxxzYO15NXv zszcV<^X{nKU3b{?f5Q7I=xaS>{edasrZ?f?7r_&ERuBB z(pt}{5N@G!Sjg<$$i33t(ISFA;BlCRFqQ- zOc&@CRL$2y;-;6fZMh;Q^kuGUNSOJ9Yt`eQJ`|HM%lFi%634C@tC}<0TYfqc)r!pS zrBsRMiJ(-q;y@dqvEWBke}Dk8p76?BaonxEV|i|Fmd8u%)I(0%6e^M>`C)571v`*Y z3K&O*`QI!6DN!fZ<~X*OcK{Pp{02Q;*8izd^f9NG3?%MWT80jVflkK74PB8pGBqEg zz$awqO{22Ofs)P_+%ZH@TBa>a>SrbH_u-M#WqCbeWFQh_642n3@K#N{9nc9f5h*AF zR_TjfK69y>=|d1+H{j*#)ANXOEMM=rY4~vc;6+oR*4B;5OUcqYX%#+6X4)htFE-EM zzM~}(DK6xu`G)|1s=a@6GE6vrlRDxbJXFQ}^wH@=3N9$g`QHsa&vQWAI?!Jr1aaQL zqI_yM#?i5l(}x|*fiSK*y`@QNYq`GL$}kkeiZ)`TRYQ^L$dVSR)zbEmm;Q@Om3?*7 z@D>pBoTlWKl6!AmdY5E z9y=QB#p*&?a;D~T@_Y2$z^Q5D>)p-8P%(DgB35nefVpu&$YV1> zimm<>F`Ws%g0nCPU#Sw6w?cuKLt(UYxc}St#Mp^-^Ypo3m{}0j{(Gfk24%uVv+a&7 zOh)wVB5KyNK!D zzCMx~2;(SNT9${?0CT%>F6_Kq>d#Z7N71iKx^y9xxAz1H#HkTe6)oS1_&z0Qo5=8Vq1_j00p z(mb`Fr6r7o>^}8cZDOi+Irtd;!QSUt`u733lw;?IZhssT72pg>DNg~d$B|kzeDhK) zdT`h}{GxJS%;Sjm>fsb8v9~@;?(ETr0*2bks_@`m&_v^|Z60~)O?^I@3253rnWegT zI|b9>tURrWzomoq7;ufxx~KY)a)`RwZy{Hwmgc_$XF`q@rJ_gV4=Fq?)^y1E4z`FQ zgOra2>nX1$HD5prTm9Oh6WFfeo}HsH);Obh@^(AAPv)*$TPZoTHqM=QrzDdxItpCA&o7TA5d(vHdF<-)rKNk6tzjv==Kh983l!u}h zcTxjYa~SR`c9I!2k~^Qe@Ibm1=SF7D>-llr>w{G0lh+}QZ0OGvc6(`A{MUH_oqI^a z+xLT%4!WNReHdvh(9?y?RQ>;GNhq8!P#%<4Y1PJQ?ET~2vDuw8B>RpN*V~h)PjBkW z3&j*;_P|mKT5UDK`XBrb7`rF?CwgrK7TpxG2Mp1wDUM^H$}XTK{o_c2u`0nYhu413 zWo`IB+BhcI_*n=gu=~OjnsxbrDNSD6ot%nAld;&Ts?^1YD{{=ZFOr0=GJY=YPquvw zXu~`$jXpNk0yZs7DuxlnFwBT-wPxI7kG+9=CHwDAP_$3kwyqCyVexn| zDcSiiUo{>z*iboof45pN7wdh#`TKIQf+WRUjj_Bc?_>F-Z=*Z`6ElOyL2bd>{Xdf+Elp?exxO1pzecHv#lBg?|0otmu(f|GmA$d1PWD<&C@6 z*n-$vIp;L?4l&(P!*RfsdMGr*MJeQ9kVCOtqI84C0aWx3L#iQpwN(`_XD)f^as@|L z6gh8!dhH%q53T8{SL9F4sF4tQs`?ws1E5<=_q`~ND-J=(O*3N53j>GzrP)JLA|L%z z^zULYzhzPT$mvbVNIM9agkq$%qaYM+yfoM7GH&~kx)iL`h6hS7cJ4vrlKgr}&sj=e zNKDM@WXC$~>9^bO^Cr+nbNP4hgX`|=^=W7GFa?Jr8HS|rp|+;MBl(Ho`bfSfgpTS| zdz-RiK!2rTe{EDDl`xAnQ+twbhy6FH-NG5R>8Yye&<)h`)&!7z`hwt3*H|U!Y{~Sh1`oLgEd~3PrY!7mD=IIHeM{mPwcnVdTEh8)%vVr zJnrwfoJ~Un#|cGv5$#o8!D-6VajY@Ab45;KvSIN@E^vRl8QHA6z)`7{h>?!Ik}=&^ zNntarm7`WxL0@}5qJQ0VIhSd89G2EIQ4*m^<;Ll_>m$6<_7-q)5~2Yz5O498*A*m2 z(=~36MHF!OWQn5z=|rX>j)YZyuQOeTY2mE{y&FX~C|gRVjTkzewr{92&l$>nSS%|{zA~yAjyH8w?o3WUEVUihxBh=*ePvjb+xPYm5+Wr^hmtDY9g2WR z8Au4yDKT^o1Bifvw9=)NN_WqIv~)K^cjv&s%=@6{c>KNp>zWVqX`b18uf5iNuXV5W z)MNy+_Elo*#H0IoJI?kg-F+Rvj=o(aDIHb8?1F$jl*Rf%N24u3W)V~{eJ{0fBqP2kqe=!nwle?T*R~t&~;TzXENNc7Kl_>YefCH_fJH4 zg-yLw9%a~$9yV%2RuKaQ2a^v8px6=HB0Y%%|FrS$(HRn>xhh!qoTjcQm1Y_pbXhxv zN9^p&NBAil$I2!*mW1Rjp|?+mduxKJzAwkVwymOOeMrxH8-TK`wS@;uchnpV3~R;6 z(Qj+4OjLuiIkJ)m%^7iUdRU;o4u$h4^e>Dq!d!Vhn5u zB%%^4t)_g!a5#6(kL1V5m)Gm{10;SHGjZeNoF>-)8gDa!(IQo`p^vZGSQ;_Nu+((O zFmCfjHZrNl*3Agduls6I)0No!r8B5u zb@gkx&BQ71W61*pk&{L^nHvZxB*9`SlX-^Yp9FGSHYmFBZ{(rH8l@gqyeki&0!vlz zNd~*`qNQy9<`3m0L42j+Gk76sycxOMTPnu*ax2>r(u=|upGKcz12#70W32qoTA$F+ z96vQG8*@PeMN>x8A;f0n1r2s~r8ChZQ-OW%)y`s`vEaaz!pOM?V;Ck?s6w+@(iJ{o znu(25)id3c%v=r)M5Xq@{)WeTCT>l!iDQ!m&AV+Z3#)j#ZKCbKw2uNnnB5>qmUQny z;N03WBpu8df2mEgyhs2@9%@M+%m)-OfL8Br*l+1b{7Ps51uimdW#aqr{s?Q#h{M~$ z@%|!F2HJQl{fR?gL^vC$NMltGJC%l%?qall3n$tT-q_ER0;z0Aezms}Wo!IQ^+Pfe z8G75zIT}coK}!_3h6fVz6Q_UnmY`g1Fu+Ts$j(3(=^n(&cZTxNjma4Sn zMc`d+ovgsV@MCL8?KOL-whZ!6%(DAUS7QyMH?4z@=tVnMdwh(){daeNWz4vl9S}Yz zEjj!xllS)yC_i=C4qPS%X%n_rr>TtG++rC(({sJg{*+D2$c8?1aWiJ{(S3 zm4bt3B8+7PMR;Nc=WrXkchFbXc-QFsmDE+%W_aH!q)IV6o$1se&w5Is7QdvFuhTxt z0F)q9aIx{B9b`v&FV1zAr?{A2xNTkt)nL z6oqO^(=JL#L+~4caf|%URb?c_xtI1F(rqVgX4u7TzNU(?R^wxi~|xiX4mXcIzD|WN|E{C;=4TvlGG2 z5;o2^v4djfEj1PKKON8Zr%aXFEkR)!*X)h@^sS9-*WI_TIkx7A+o@ME+f0s`Jc>GF z$$IIp`<}L(g<;-9`N>xL}VFzAygC)+8o9-B~X;zD0cmUjq;@ zubQnVUYb3-s-5f0L(7fx(}PWr6{nMh`ac!MF!EixvsfHj)I0ui`f7P_F)s@+5?bn2 z-w}qEtMGiiTs>B}X`V!KFdRRKme7hL)QZC|@Y!LaLd?QRhs$MT$!8;T1?lKnKK0Hi zXXCH*x_lhtONM=Ex6QFYlAA3ie?ofVEk8v`lg_Ipvg_ayVF_-dAq4pCOIle5$Y;)L zdC@VsA~lC}6@PK_hsOE5}!twy|H(8Yp0&=^2x{mw&?~u&tv6+5}Qo|4lQq_VHs|z0>oD z;>Z|a!O7P&_9_qKox+7gmY6(sKd^z8ZBDt`ZF)JEmZr69GPSqrA8W-~uvIx2yg^{Z zN^)gdE#T@UP^jhjipsj$-EZianCp3mD1^!`zzycdMQtKhM!TwcVhGgJoW%8Aj5YU51=UGxm4kZ9F8iUZ zn6P}xtKqnyE9MtOShB5l%m5G-@mK2@VMLa}MTlV6Y7TfMLCrdj=3s}NQv z8v)iAupY=~jYKDVSW(6tm>+Uc*BUHZ9q#{`SbWVJqm=UP{D}AQX~K?#xb{#b;p)W6 zP|+-vQiyi6Ms$zHOx|>F?u(Lo-MKF1xXG*Y!3DNqEykXr7mV(-EfMUG5UOo}}#p{3RFa8PM{>Rs; znV6W=?ixRxRJw?Ex!dv0J_yK*3CR~$lpXU;ewCe1e72TNV{I6pI57CT?cg#KTaSBA zZqhFD=0g-@@IIJdF^+t)1cXeaN8t7`U5HLH*BZ@mDy=CL8-?%P0ff~|YGIIHl6 z@lwltX;Z{{8Q3imR{bWS<{rSTG+PF>SQtH;iLNH4q)6AwHB$VGOZ-zgWT_w3td#Hos1T_T_|?gA(j`XTJxE6!zDbGeOS@Vujg)db%%UN zai^gqs?m6Z$LGp%etG(L{c-R~k`DxIPei9ULrjDL_x@EeM^Xgkgj-{+$Wm+Jmeb1h zyTW+6HTKvektcKqj^mYW=A2#Ny4a&p`Fem z)}|$pC={t}=CDn+s_icY-Jf3iNJiB5cG-< z;t^BbVckdgZsqpoCUIrQ83UCh&D0jIRO9rhxaFlRZRnvK#wYP&KMpRHI{N|4F^^02 zeL@+?+*btgFd8-Q>D%=4?p8a@J*aErO69op+kbq(<(Kpof>o$RcbPe5S*X|ce5^+x z5N<^6XTJoWcO?h{X+_a(Vw>NJJvnS*@&>CCwqvCY{+i8*-AQ)8UD5i}BqkB`0cRfq zVVJ<}*Kd<44Bz`^owCKGeu9~KQCRWAJU^UMA3;@rZ2yphCcJH?r+hW;o#DJdl-(KT z)FE&w+vzD@MyJ3CC7IG|MZnpsk-d`uZFUZC!g;#0!SnZGEuR5Q9t|5gR1kw89R%ww zQsDPue@R>~AxqIa5WqF#m2fB+Ko$YhCPK?|mi%VGumcw@0^3IcW48FcsfC#_?$CBk z0k`v_c2k>_WYl&gn;d?F6Vf`&MsBlU0ObcY(Jz!tj;eE4m&7?_P_szfmjE@;6)(N< zUR-(<1vJhDG)zq;%f?$93PUKk&GnCa1)U6x?1iS^sA^3R#(`Xp!%?Jn&6>ZyPr;9n z+JA@1@(=r6BL*_%|9%dI{6C5&vXy&#ok_%+E&&@|x&3-cWsk~tk7`BcAfdO*x=_&K z>yeh4F5RE<{=L#*C7PaSZRb{IIWgdv6Iuy%$`_eN)aW)VQ*YCoO++Ne_j1ol|0Z zU|&6d&d-65Id^9sj8Qk>W2bukePizV=@GU9S5HaXl%(TJC|b88|0TD1Qi9_~u6~pZ zIHs|b;>ehWwP=c9HE5Y*qmKPt#lNa&(WUUyWpfSN3pf*_L5k7xn-uwQO(OKr4jI;C2VYmb9; zk8Ud&3S1ou)*bw#psn5oZS^xsb4xvVAT%dqOsjO{nC=wx|*)e)w@fuUB9jl-3!GsQO zsTTI}lUg|E(`$D;#>nM&=3_Wq-D!W7050RFzqtyC*b)9TJT$PoN3FHGWqC(b%kDjh z7DbsM2$FHz&I!IiF01G}Hcg(ihwJ^A-tBb1@O^f6Zka42Dt^0wq9MhT3AyxUOi-Ns z*F2dW)R_Rlt%`J$El!T2=%r4|R1%n8vgLm1AiEN_@}-9)jhFf*HlNG;Q()sGA2o;w zoLoE3KY$1Fv8@@IPAOtf;TDBC&~?!oM$Z2x@9wIXe7tqQz^_*pXwO6SwqsW<$N6jn*Rah(UW;?UKxF3fx zaI)0+7Eur_d3zW`pXvl0k#ZOcz?|UCh&_JdMWr1tG&detx z17&5q&yDE%n5kJA0(gU$3IgYX&+_NMq>xyj`*tMsV(E0Jl(qJmTAPWv7-e zu)FEO5+MDpM5LTxb5$Lr!Cc5^k4M*g&0JkXQ6`7|vB|URI*z!Cii+Xu3X_%Bf_p&- z8K6fEHXY}~^iz#&w%v(hmsT}|_YFo4=(Kf(p51FGV-!MO0-1jx*Y7X>ska;+$>%X! zVUVv^qbKgefESHg)s&rUeMl7q)p+MFkZynBeFM9?+kSSm(e%o*Mo&BTUpB)E)S9S| zPLwk3%4B6E>{fQmD?vthpzk&-9+GlTl@5w=L7uu^UCd(q!kjrd7WxC)kV8?k7Y1#i z+3cA}6r9q+eZ2~|S2i$@stqYzIyT@ub~nWSOJ`;q}QUKdAfFH1uK4){EtlipHnH#9=9H00i&Ztq7K#+3meI z?qeLzDDCBdfcfac%6?Pr%LkKTk33Prxf$jb>O*q}!k}1gv!@_29ooL6m&)1x?P#vm zFMx{O?BFcSnEW}=+vsp0_fc2d7VcITaBCiAaM6v z_nY27!R8(5qk3{i$g&T1rc+Kr-+Tqx|(Hg*m-5E+401LJaLc-+%1iec0C+?3i>Z>`uZO zjg)5eYL3M<3~9*jTh&Yquo=m#t_iAJ{jZC>i*T%6Q1MHQ;%A^3<7RullEY6oFm44; zne^}8zQ#1rWWjGi{ZYg|N~vIK=gtn-iWzFvngbt!4B3ib0j7JQc~e>2xV)bw3Z))1AYlrJY~Cyqp8U z-8kmL?y<@pq~9@=efiRxHvzwg@ca^gTQ%UkMKqk43mNo#oLs0?D8f&5Hr+uDy|(Q* zj`kZ0&!*_N@yRwP*nCPUdg@)$wzHWu*FZXlL>%|7cs1Xl2ek8v(;5qx{i>==9}FXB z6Lz=oV&rqpn`(}F=tj3VvVcr)r0Q(H5|htU?qYD8q2~268KNd&1=9#P5n?A$(pkw~yg+LG&H`p2C!x}47LZsC(y zP@Kx4zu{vT50B+(L-^Q$yo|HrPg2O>l30alT;62)WJeV=EwGm~FGW!Hk`7m>@MnH}>*ldqc{Kandg;8A!h(W`jQr%mq+;QTZ-$8hS2sgFQR3 z88rSZ{}Bi`k9=Kp-p5D(SQ3Anp&qiUVf!tGZz z5}cG-nJ${Ug!e+^H0wsh_Ovzg-wzk2r`%*&(SP$}(>9Q!VA=!->ww`<@#uRf<{vBU zk+L>W5%3>=kW>Yjv;@A?hVjW3yLPxNGC)=g&~o>>7kuaX!-tL7$mKE^iM^BQaN42Q zM0P6=-nd=6;pFqIkHmj!!q~mNFVYJ9z~k0a;LRBRhJ7SN(q}HbICS~%BgPJ`hIP5G zuM%SCXrw_UJ~LYl#&>{skOkIWh+wDC%Y0|3T(+4hsq+Ma1VS@U3OS!Lm*(f+>uL?7 zGmLpg@=rGga8)^zL9`3+eCVlLL>K^AG`>l_Rk?N{u{#?*`3#iAFq>29%tg*8s~Uxw zISbWK46EFV%$?a4;fRwxvAho1Qc)*Srw5vkluH9rs!>cF8jnt!3AH0O5a_0fJ#sDU z$KxL}Xvhj;xneGS{ z?u38oT=0!8Zv?jb4p1qOFi0F8&eVGgmZbk~&G|(omjQmF4)Bw$B62%G3R)7j-NaOi zJqyl?=iQ7ad@^*dc(sPqFKFr}%FI;goi=PGjWxbc8*hRU>+EN}0TJ@H#nFH^pYrx9 zxpvFIwsiEM`8Dg&X`9i;vq(8nf>k`fVEA!);ke}em>X`MCJ|wt81}-#LT@Wi%|Q73L$o%r zh^+F|_T-()NWjCCky)hZzVL3R^0^CLafhyaJ+6xw(Z!qoKb$-tS3O1ID3j7p-^VrRF!mijtI*4J}8;|}tcNPWk4d{PqUMy@cd*7IOl zG|~SrzxA4JHew8A{W=B9$l8|D?@AJu9}RXauOiyGt@<>zhL49TJ4fxKo$SF=8m{#& zzk`*`!xP^n7pL=gRS8&gXViXzfph2j(gPF1$=1OJMVT59YeT zgO#+$ykk=R1>~xZ)5}CD9oJZkq6wtVRx=`63Pv%C351A(csdP9waYNgVNWVai-Os* zErj~>zGadx7}{Ozh=~9k(0>sjQjP()gf_=&2&D_i*@PXog;?B>UNT+u~2-)pA9CiYY4(k>-^RLk6HQ`)yn9dHib)?igummI| zkLBPvrSOYMxE&p+byCEwqi=3MrpNfev@DPeC2|QMulupjdMa;t^38=(kI&KbQ@63j4-MSD*0C9?equEEusBxhfV#L36O9cepiG`A1VXkLFBi# zS(L7FgHr`$VPTQnvw!!-4>b@sF(lwl*!Y~};XtX=0Z~M)i_^)g>&a4#Kb5=RvZi>- zM~sbTb)A0>*?Y(JlReLsYFb)y(9I=o$Qp7bmXz9WS5T;QUnV84! zY?>kTbO~NKYJ=gMy~6q4bado&|Iu3mPBDdfmeen^L)Z20TEyWO5j6L9sqm54BaELO zM6W z>aw0O>Dwp(%5p7s|Jl;Ci#$8fyJI4gKDi`3$5=+UKZ)q}5#Loi^@NmQ=T1rq6qFqm zyvpSl%v-xzl4cP9*783X_e2&8?jJE^mAN3rsJFmK3@J6fDn;8oQl$i=M8TGEWL5NL z%9YghOC}%cI*;EhfvSsM8>+N(?tzE;fa24Yp}+(z}$ zgPVkT)YyZAgS^mf=QO&0qHy1sz94=|N4*Tl%TF2^OT3{jfPgJwGXA(|K6I{4izPY3 zO^g(}a{}FwJPRHi8TqdT{@;i&N{}q$b2e!(_emslUA1Di4K`gVuC&vnvGDC~#Xk@y zK3MvzGRv7Vo94k0lSho>_WtSFC|u?<3M7@)39^6mGhX69+GX_?q_}1GmQlc@la%EY zNXzr5AWV|wS8@cCeB-r3 zOvB9un;>ehP+-PPic`{M!*E0DVn4Gew)8J0L8Psie z{v{Ob-hPA6T;SRa=sg4Ib9sRVCRoejM;z&6KCwHciB|cetN1LkX0FI+2@?b{XER>2~(tVp=!ezBjv^>X0$L=p>N1q!ub$KNsJQC2^ z1yWs=P%sQw3u*Zh!_A{Gc)YT_Jar9Jnq=E(Ta?7R&v0$?(`*f`k-gTj`YQ*g-BWn% z?E76i(?%>G6~E<$2RFE1o4nOJ3gBbnMV=-Z8Agt-mse=r4-rK$=c2cH;yUyV4IbBA zYxvRN2m8tQ@~2+{xtKf2Igs{wJUecgcF~JE-a^5T_HBIy=#RrfIolb3GQqnc)Rg6X%{H1VGu(x5FoIzjYrLi z1WYKy<#HJ{7X!uw0B}}^oDV&zzJ8fo`j_`H0Cg7H@LC*SSiJV z`^6DHo9|a&-?O_R-B#H%+QLgK14wYEf>(fg8V$$}o6g*Zw9NH7OL!cfG$W*W*|Ow{ zA=PWmlZ0N#a+3R$WAJ#i#OJxTe>)ceI`HxVXmHXlldeQ~Xn_R*n-;+Xa=$93B9dGw zS4xc!5E_YAyGy`p=l4=R7LBvr`RKI-eRjYH9hr+YjkMJGc#o@u)c*(aau7%z4LwKn zIrWJYQv*7plOvdPH{NCT@$#qMCPfOvaFt83cg^qHcEp&izG(_3^}R^6DX8Z8O#l5q zGL+7Z%jd<^3-n0y{RF$kkn`05!YN-Q#ZYf2WG+A#$1Pk+F(*5d%#H_HKZ&@NWpaNc znJG#SPrI7=&2tV{D>QvbE_Z67K?SDk11@j<>UnmBA=gHRjr>IyaL>!lE!9b{>qy`p zdW)kvG@$!voiI+jkB=h2afK(Y#f#fFj;pxUm`)Zvi7#j2;be-`j5Q?>(HJSr->;+= zI8=8ZedX?>1~f+3-@QyF{qsqGjvGx|2^8qojiFXUNjdPD+S=>$qGvH? zm@`VsAA;9)5^;OdWHITmSgDO8--7yRhd==QDHxO^xgI}MumhR`(?!&eJhG&VbiGPZ z!Jpm>Io6k6OcY*Br~n}hf9vgE!1ee4olu*tUP-Oh?%bW^h|FJQ9UuMd)u-FlcmFcA z4;?#x5-d5L8TV;%!S`;oStqxc(_*`HA!LcumtWfEcx^_?i+;_jn%Or~IC;qB`+J>rB;x%>Ha@a%p=%!02T#RE_rsIBhmD zz4Rcnkj~}Zg-aw&Wx{2CfX3nRG17@u`rMHY0+BX5om!DOS^6jdyiWR0?5UtA!sDT> zhF+64v1u^5ds4>!-zz@~lwXvQ2Zl2YjkA&O+(_DI(}^2vje8T+Rj#za5}I1{E{DOm&KwhzYXvJ z+{p9%&AE$p#cP>8At|t*TsX#RSg9Mc5EC_k*`SKsl7i}3epur=j)1t>JL-uJX|F@;a0?s z#1;WQh^T-P7$1j!_!uxFNmin^%R2E6;%DSzs|3u$K^(PsPnA0g$1r!e(i!xQzL&$Y z8aPUrPNYhg45z;fC+S;c?_{sghIf40ZE}kr8keSih!XZ`V{otAlSG{MWE$MRJJ*-W zpL1dg&|$EKl=@lg{hV!{=HAbR&1ksbO}0SIOY#3ocG|!FCJFn7Iz6a9s6SyKQ zdYHyGs+MThj=t049lG;9Cd}S@A}St;XohOyUk8_gd!7(OO&HOpGYV!|hS{#5`w8*o~D$9_w=D;0L`orGFD?H$`1Q&tvt5l1J_AgAdu&TJ`-^xOTtKFe>~l1lA1 zG{2|d*dDKTUa5_`{cD`q?;l)c$NDhSwgIYFn+&#R{{9LZg5#&(Cq)%8Tvfz(fpmVZP^99WH9m^jT_YMP&Qo zVrFjKFzHbxb&0Rf0nJlp|15>sLiBneEL~U;g;V?r*Q|Ni#lmz|0O*qYdVn{}bRZGK zRy`TlOe&^CUpc4pi58FsPGh+edG`ni2Lk%eoVHMqh2~*E2t^w z-f7oCHPMU0>`U#@KOcVsRwI@}N2#lTwd}<~ zn|C&vyYiCbOGM+}>mP8YMGxl&J#@jx%wrCp<`Ai;e4H&-N=ZJ7N=hJ4NO84C89?rz zy(zhIhM(!ORsJdS4wb72PC@ScLw{T^Kz(1xE_+-YF`Y4-H^Nh#%U62^!8_Eo;Xopb zNp=dpOiTvL<=hD14N2HD_ovsu_8vw)PdgiuU1RFp<$WfFf7vef50|?fNiG`iGtPsx zLdnsw*ICB&MB!BuSPAj{1+&daP;fnEU-&99&YsJ+l?q=!Mx2SgzCtAfNi6C|M%CnE zfWj`0$>;Ftq*dK(y5>?8L1gRbX~}rZgG6XlA)>LO{gDDQU?q>52VP`J@5ZzF@e-Tl zQp3plxZlB%Exh53ve5H1_pON|(^vIZDgPAFK7lzoyU*+b4kgrP5Kab-%o*tEo)jrv}U`f3iI zEq$T?E2Gm#0Tj@E26i|NS7_93DdzKD#w z1>HtHvlqPNbAq$9C4jHiUvQEV-+W;QR>O4w+6aPP5|jq&j#Dw)(fDD^AAbT8pEGc;9d86`opR*8?r)v_ zr5(sk5*WG6T=mEn35hCEKs@F$gK zgktDr_ISg5?Mt>KN*hiBn9gT$c0Af74GikNj?7=1{&f@CO#yd^={kaL9N>MiQ2GUcCiB5w;OzV0Md%`Wc4r=$^BejmyLZdH0$N+ylfDQH>0 zgqJcK6lQMR*ZQEGPDOZ**-9adH&^(yayKMv443@jQ@TvONCk!)eI@!5fOo!F!2QQML>&0)ytn!=g)m5X7bGamPm2lH+R&8|u}^;Dh}*v2ep zbl<{)VelfrsF$hwcr}tHEE@a zxCgmzbU`dajlz{fE-uA`>yJi=e0BNGtsDDPM{N`bt;wieutgD&18uiy*HPcA2W1+d z)uJzkHOk}c&x1v%MQiR~r6eOg_)9kD`ij1suI zL~TUoM>h(|T{%@U8^{ZpD;5zW{%5jK|;n%ja|`WXSoh_n5a?iCK{WW7Z{i>JId%3?X|>#&$8UL*Bm9jH9Luy;-iG z_mvclN4QJqhi80jeWzCW5U$!ErnL$`-|u9q->R788S`98K}_bH@^k&MkySb@L!|dB zj*q>WGs#i*74ye8v3#yHKp#Fa#CkGi+oCqABl^8=fa>2_02kEAvr*pFPOY866UYhWK);vpi zK1b?{9C>qvh>-yHW#R#pSNJW&B1xU@3AQch(8HK^#{cm&*Zx}e_j?>7IDmgmlk(cg zujE;E{N@t;=eKa~H^3KorqQbDqumwmo6mzUs13)-PfGWm1^3W&`h!|nZ#{|ft4Coj z^C6p&GEe1kr3)mT_|t4G!|YB~2P`5%zE{$*kjHNgGg>-kL|z3GThj@ZWF;N8H5Z~I zP~FEcexEd-W6z)Faj%XqcGIRQZ>tCVd3^pYBc{%Ax6fSTInoNwDE6FgzFiHX5=Y#NJa8V z-HP;%v+-jz75XR_;}+9Wb2{G?0zEjLH}rDQfCw}|U@a99Y6Gr@>P{v@%zd7exx;~r zjD*dYhUXO!_FP7^#le{lCbyvG^(h#7kW}iGEIEDquT2N}Q<4+V8ASN3$}^pf7O@U9 zIC7Iu{yZ3X7q3R=aCwfOi852BLz+(AFY-fed5?PFaTUg@Dbqe}PvtVzj>pA0lKG%DOETtBw8qf{Skxiq{n zqX6Pom(T?JZr=wDzSs@tLIl@n{hu&FT;pE3i3@gdLQfD^F<;!#pK`nXbzVC+#L{gn zKhG_*n;h_kN5RdS4c9Jlof-!#*{@|jLl0bT!m#$2ygUd?i%4Y~y{{Xc&u zLRR#nc0KBh#FqkwJa2sg6XCNU-eN2AI$F=#@$B{PA?8#arhvshYU#G@Zj(smVES~B ziEpP!ScJuwfh5vMt$Dh5FmU*#2~k9GMu$MQhBA5sko9J2!XFzTvl7SR>~ZdH%TifB zyQ{^a?Gs5BPlyeWvGdo+@4F=q_QN+QTmuetxsGjW)~P0!wGV0_Len`$b)1IiF?7pR=&lF-MQ9Ym`olK|NX^F{w%s5z{ zir1j-UY9b{T7>NW&P4@bq{K5iT&SrW9Vq$%+2lS));7Y7%+efNis*&nu!qSxDJ&$P zK4zNURMH*nHJHTX3&@iSY#<8P2>$$=%bR`eivJ}zPa|!CUl0VXU&ZjiM{jB<>*byf z*V)6yv>2U&2!LIcpH)$(L)@7Wsb8N1>le!IE%ExEmKsxaLxlc>y1tj#$2}0pnB-oy zyzIO-Yv@_)O4RhrDlS_qLV!Er$a;6`%{ZCs_zmBLsoxpM9bsyHSe>1l&|5inTzpqz z2d!~`pgf=u z*f57k`)4(10l#qr?J3_Ya()nFa1yT9MNY&;Qho#qrN3lN&x&jDMh;mi?KGgwQNL9- zsE(2sgWo(iXF`nvK6R8ys~JU%a}ynXTWXKcuWB~Ju9MrghKY!RK$G35<(3^1klyxp ze~Lk8AD&SF0+mDAz@2(&DM+Vf>z~+h8It8haqVljDz1D+VoX*zxz9F!8tDzr0%9QoRdu$Ns1EomIxAVRVI`PA#--(>O zzW4C)ELT#tNzQOAltke?@FVuaswTTK*cWC#H`IL-RhLgE5gW^bpoow@9-H8W?uDjZ zqoc|tTK1#+6a6o76SWgIsSI*fxX@?I#+N#FZo~h5%`Ig8wlgG*e1rdHC`!u$HFejE z3S6L0gVSb)4Y^_@5Yfstd67RpPf}7ZBrRi0(FUn5#M0@4U4L>|?&k`wS7tV=gD+OSrK>p3v-O@EwB7T}bLNe`rr?nbq67Jy<;-GmzIt4}dG`3EA_N+$ zEcy)y0`?RQRG8-?xD}K3wVs#g>CGjq^p+(2&kuLuVZ$0Cd34P$(87jM2IllmxB4`& zM-6>1s0_{q;!>%4=7>;014Pp#z)jFMuE5N_z0Rs zA12t9R?sggN0>u0epX1WWw--K?YncY^a;fR?ABjvce`Hn0JeVn!3_+vKfMrkXDoN^ z>5D?I;nAi#z#Nz=pUVsrIKDDg5lk!BR7DrRHDJ1f_GXLU?!}W!ROy`w!ZfZcmU?E{ zSBz0j*1Tuq=J9y|15h;TD8+r|bSssr7xdpgKO#UrKwydtUrk2{vZ`1nmiozkRUS!p zY^6yfkUgts=W?HS_3e8>nh9~_jw&(rie1o4*mCaAi2@m7t+Lp{DfAbFjvb*0GjD4z z$e2a=scLrkkT!@594!kGvMS{)tlOufv#**HeDL8vU;E3u-Sr3F?`=3~S2>NotBR1> z2Dd;Tx5{*?Fia5iW%~orVvjv*ZNzH=P{4K%^?dN4XEC~RD_;Yb79G3+W}dbc|CXdB zUh}kc9{^i=(8eoN5UE>xD;pHIg985xB>>JpyKi*5zf=j^b}dA`q?SaT$u_^>UCdN_ z>Nw~Vx)CHWd7_YJ0YD^G!QHDloVCXDRY5|&>wUyv{xw}s`AsI@~bNUxs=P33VJJt9L5Yb zX?yn)50;Cf=Od6*<1(Xg<2%xogz3Z}<){$5QzAAxP@okpp$`8eIw|bEuxA!FS7NnY z#=>%wDm7;Sq!$tVs_D7y$&-NpZy}BBMJ{Ut8^?fGI%wj`=egrEy|e$3Zj_>8cFeLO zadb(Z{s%&Jz5_=ehEK3g0>f*-S@11$z1-R^CZ9PxLP^I9TTHN>so@ zX_);pY-Y!GdNIohfQhXHkH0Rtoo2}(;|HW)0RfMgBZr{`LtW6VC`~DQV4m*aG+`^DEKX%q3;sXjAbx1Fy9v%M{lUM4)h<^^L0me?Zi)&61|@0QLv$ z1!x4V4X1}~Ajw0Qoo$nkub-MwtK?tp~y3gdcjkjNnT-M}Tit9xj)|@_f>Z;s zG+ZuYmiMXCo0_>BhnKjlO#n7$o}|h!f`F15ZQaLba9Izz$qCJ&`2XxP;kH8)vFLf{ zWq}|qxO7AKd~CzbvJ?EQxJu;fYn!N8!y%_)voszA>*a}DI{T#$wB5jBJhl~|b!ECF zmD-+~p^^+W2q;5cPg&c}Uin@eb!y0*E>dh|D7sz$-=qNF1?~?eH0IJPOK~QPLwyQI zcZxq8oNxGc4jYF?*+1*vSPr#Yx{ZH%^f(a5FW*{3b!<7O&s|A<4^~pCTlZmyS-cl( zbq76?Y_=A8Bg#?#Yh#CGfM0d*v@tkH)R-{bylOdQEbQl^e9GEwn5DH#^b~fg%KN%n zr$i$T9M0bMLpKa~&ajwp;_$4j%d}bXhZUQ>d%>x9So0%NS=mp+#pd7H6xOVN=WXTq z5%j-)PYD1Ui;bq?;>*o?_SH+p4zY_iN3)|F9`!-m2H)AAbg`#|B+1&xuISmKsLw#; zmv+XZ82D|`o{LGaesfm?Z(vwS1AAZPCFB7D48K5M^hoZUs|R|<{D(mKbDn>uI76J7z}kP(>^+igDlT|xKL zm9B)r?vCdviw6QD-4(=XI*GilT?{8GFT-6rTq~#DCW)!IU%H&d>e-)0ll_-f`DKI` zw|AS_;`I0TaDeoGu(5|>dm%$58@E;_3aZuDDI)EPd-4|HVlzRos`K3Lv@}{mC^QFr zpL5-+N#Pc3?tJs+VE2Y;b|;g{G?M-1fy}8XViidKNnS?_G`#PO<6Ys!X)Y`N+voR@ z`5RuWYa0@_U|NjDyz6C_Ts_|#7Vgy#*+7y$pQywkG80?8>~CPCSvI{uBA^<@QSUZ9 z%p8i2f5a7sN_iR?g5sb!@YJi`4{IreovoWIF}M!lYv;do_1)2=#`+%*w~Mr*S^W#5QfBx#mbmFu|Gr6{%3k^1;u(yIn44#D!FFiKRN zo!9!iG|)4E!d@6JsEy5eKMIvS`lgXmWYL|tl;BD6=6?+3HJMI{S;z2aq^$5+3+8cQ zf0On1A<)laUC&n)9h#+66Zwsz_ifUWNK$s7O~!bHhYmQ4_F^sbbUK`$5S{llm}6z1 z9!mPyCP(<5FH{E0l6#!5uC6XfkYE3w6|IIhutZ2X4RRXng}}=Tr-R5t3<}%On>NRM z;e}YwYSc!~FMaE0QgSRAEItrbZm^o4$1%F~gKKFhiL`a*{I@soKKCDl99(B3l`vu1 zypF%{;xBMdg{zgP-1dIU^B+91h9MBVtbz@&Vjc1OA!h$91xbs_OLh1UIZ8` z{&klFG>n#hesX7mBInxBv-q+)v=$qN-Wx|AkC*qkVkL0p`N26Zr>|8)Fca-(1OCK* zFr$1~D^k(7(|HPN{K`wGboyRgN14pxyU2wI zUML`>bng;{pLVm|epOh%C0u@(JY;iXpV`d=-C~^lMt{&B^cL_I@=l*$s}CZ+7N?eU zTWYYfKd<_Pfpsvr+a&@_0jaZVvUN9 zDPs-3kT~h_kF6)u?g%2^y->q*Q^Q7nvA?rbLCJE+Pnh79-ZYH=ZpMV~HI=*GDRzaU zKHJg>xOM5OHj*K{-Dpg8!KpLN@#ox$x}cVSUUG!*rUD&zR5$p!tg=k^R?Q&`_) zSmiJ$Ya{UJ58b`Y(99}he@6PQ4n5b9J{C+n?Mi9P9i82?u{mgijU9{A=BU1Aj?Gy< zO4cZTFfQ-&T#Vg+8@NP$(zV8`Yhe8~_N+dN<(mgOBAJX%# z$8P0+e38+}b!r+K&)JX9)x{-%@fwV`kfYlZ2-nbRfYHS)YAI`;S9mYd)8UmD7}JR=1tz(zUboaoai7zLKmb-m6A~O5fubPkf0zS zQly5CbS$BFlwL%H5PBy-NWMMj`{=vQA2{nSpFVP$+u`R}ykoZ($8A$j^f|_2ygDj5Ao6VBOQ@7-w z#>$`Ko!nijBi|RT`1wLBRO4uPFJ#RB1CC!5q8~`!k%b7zGHY$(WM&E;gzWu^ey0Eq zt;&@Re`izm_PJGW-T+_S;+(baEcOs-v-rCy_UD~C5~XVrB^T#i@D{JnaFt!Pg~K#p zGSfE-2a;yCYCsL)VnM@(64!tEUi%{kRBSH3485}u?Z z1ve!kSyooFmZQ=O4GOu`!m|YUs*2J&a-ZEbVahxE?#P9ZP&f9VHC6OwstiNv^)Ed! z$Vq@MkvkN~#Hf7ps?8NjY-h>eC)jl*UKLSv>bS^xwK1V!#C1S_#m0&?yGt)I9}Vgi=p^Qw(-vXJiKp zcMBLLymrwjvXNN7wK9IZ34Y|WA;k_&S+f-fNibNWJ!oB_Y!XB1Ysxjz-%n+Wvz_Rt z`1G`Khck${GQ9U$f%q9GIppx}&YBZVFSF_N|GPE{sL2D&C3`~wYu@s*$;%N7sKtBul1kaj$>+v#Vl!dB&= zMRHEmIzghUa1}l%;0TwPQ*x4q9GfkhFS`Q0Cw}NpT~&gSCY6S z8bC>h!$Ez(L_BCjr}hfJqb`xZ@Nh}Yk>HS8Ic&_FJCou86q0INw`W(qTnSs-ufN>N zUu7zd%hE#4?igD5O_7JZ`_0LX1iwi?8zm@!_#G8lHqhl-)a*=v2!3fP3JS14@#LmN z9wH4G>aFJ>5@7&nn*4mSiGMUrVy#hRD%_L7MUsM{`>=C;*rlQ4CuUacg{rz)wsb1H zFUiA+`L?-pPjiK~yOfUQjRDE+I2^>coVNUPXXdztXvX0`Cbvt6N)0VqGXe6`fGyt@ z#JYb!Ltqf|R6239a+tU>w=^L6X;nqav7P9yw*4dVT2-Te+C4L>J>GhLik;SS%)2du z07XJVjT)EKQp{pHeymJ`XIs6cPnNXWoXp8ZOe_wuWy;qC8D^fOK-S7Kj;NO#m zoXQOe#g&4|8%e{DxA%^VyigWBOWb`RAH%PATBC-fI&L zX(Un{4UD=&;}xl;EN7=d9&GVCNmfVe!AeXLnNBaavBKW8BR;741ur*L3_JxT;Ez8c z=zT4pz_@h()VYqIyhJroI^+FznVfKsD6B5OQK^qH-(WAlz>h2MA7brya>card)S+T z>{WI{+fSF<*F-B=i=yP`iDMu6DSzDGurXa)&9qGv3h00$T9Hp~)X1O4o&J3!k&0Mh z>c7N^V&5`V?#$+p{m6S;})lX8b0b&C^~L*PfpZa2W8j) z;z;$j(HxRTN(kr<{ia5jKpS+{@_PCT-P`DKxp^!~y`S$B50+yq77g23g~B)edTL4pT7Mlu`;OP>1ya=wspp)76epWndxq0!otZ3CuN=!+^{=K+ ziHDJN;aHUV&OgMtI?`NThum7*Y@f zYCXawNSKOwBQ(RZrlVYo9E*dWV-q$i7(e&;w8y7VfUJ7UKd}AFdV%pLY)Ex-Q?a`6 zHE8Y^3w#hiP0!_7kIlhvf?HK3Swm_CThNJj5s4dO(_b=oB0)@H^ zsJOYg)j%T1MfM~xleYi zANp6#N+J|5c=V5Ww2F+&tTu6XlD0d8YK3z<*%l102gvs6`poy99D^k{7kz$i8u>rQ zzRe59)d6VA`8ych%b_2ZOfRfjS|{>^}FS5~SS5Bu5$3+5V_neF4)4 zGHDlcB&csm4Prx3Gw8*n!N=#auhb4E$W{GMjvypjm^1-V2tLq23s^#mc&Q7 z8pQ1YTGzh%BW@KdZJh8!Av{y!sw9Ppr$CN~?Q1DYXC1-H8mOSzosS$8z@su6%OV(e zr`9}vm~HM-04~$P@nQhWE^_R=PX5cvfV=Tb+}tw&QRWdu5QGIsaJW^k6c+HX3@Kyl zu%6hOohgsYH)hRN{T$Qm)V6xOoZ^_uV__Z5L(F7jxjY5{JZHBWyNHRG08P{Vm`61{ zY+-m6&~(5t=&yhEm02<(Lp(IuI{p%1WOvfPIlTBw)B&I4ns(JrdEMT^eP|gxKf#C! z%+v3wOncZ?r_~0>43)Pgzf^W`sD0*7_JY}rI!ny;>%Jo_(T{g|+f!T4h#D_3xmr@! z^I1Le%*F-|S~OG+W+^GxVAC?wwpj2LVn}D_GZRjfFu>#*Tgi7R8=SVA^i<1Z;rdJb zf*DV8a+*UFYN92HxQz=PM^-ARcZS)rED4s_;nJd5@PW?B@78V!+L!!{iG}gjbb5{F z25Ck7sN+W}4Zb=O{I=Q|1io)IC=#Bqw7G|)ihzddA4Lq92DaqSs%>o5KHWyn+i(r9 zK)KuavmlB3hQG7l!)HTEo%-RfkAi&n%IaB220S?ggO4IrVe8TsTayhWf?N@Aghg&E z4p{j-`@Mj>03Vy+80v7QIJ}TPhx&mUqbZ;_IhO~FqW(S8d@mK24FOZJ7>n|e^U2nb zG-#dX+HSh(b7eZ-=4e2NXVO|reS1U3zmf>TQ;LvfPV$u0s8{cO_)d2eX&1nPMVHl8 zu%#+2I1u}s*Oe}W!5{ySL8!7zY^Nub*au2r04&tBGdFV`0va=cobFG)8 zbpFJod_N@r+BnW#Y78Ht(dhnGcIGZ|02LYG&Ho=YW#sv`<;!3n#+)bN00n z4zzI&=DtmJ$APJy&;CG}1j~>G8pb~f9Ij3Bpa4R!f7g0+{;3V{D?`FW&HAfV0G9vA z;Zo8q?(*ZWU_FGyWK`*ecMIIlme2OH30kQ*l4Qs~a2_C^Ur zRyt)wi`T9idoq17QOYEKan;LV5HgwdwYR-EWw{jVTEHA75Y3R6s?o)JnSjmDMXM(ai7eL50q!PWbM; zTeAObR{3Kql=i}gnN_|Krl%uQj98&t$@m=Muj-$ScP|$6-;qhPhX0WEf?u)tPuebeXA~DlR!(8sh3HB zDPMLvF+dS7fvz07mT3jn#`;mQiK?NMi*(ORoD1IFYS9H>SW*jsFJQM@B$Fe(%ZBde zY-lO$t)l_BLOKYaJk>cMbkV$%_1a%Wy$k%73bT;STD&=dCc=)^&5(z?KC^wbt7PzR zRl@@kj@&j6O1Q6GRK__vOl9j*CV*QSW-7FaTh9vgsR2%v-8wj8onggY&tP8~D>{DN zit|M}x>@j1wTHE%O(t>-;X`^#fQk&6Nyyda-MSfNnEyABWK|3k*h^e_{*v3XP#tp` zfX%yDeM9q&cQKkW_-v4lZsj~MRrX>rPIoZW6m}sd!r*lt?QSBGt>_rm;ta9>2#ufv zGnwUVdl9oFh5g_GO!0^#Q0Oe<31<<0eKRQB5&S;2=A(+4Rg2(9XhybgK%JM8jezwd z1c`+qgdfPhj`?HQ?S(>aCq}{nE2VB{1C;lAmupC^`PHi}H>nS?^oA|@r#+t5!+3z)-IA_S_0R941W%KGkGQ>Sd8Ka?NP{0zKnSJ)jeP03-- ztuHO~Gs2K_rqf$1R}i>J&z~Tn8n&r@7X{ye9R)7ea2|@6L)(LK2Rm98*1t3U2{E24 z`ep|GB<(ICJ~(uz=4i<-ln4c`zvGg>T&vE~HQH2(MZQF~f5x@k(Tx)oKxmq@z1~nM zJs%_}HTRCt`Qz0$;Pvc*wv-WQoqElpIT~$oX;`G0k7|Q*WqHnwWJagjVAfg&k~Z)Y z#3l`FJ%;>F9Z>iE0BnGt$Qy!gdn0>aN$tPLSPMIf`<7gWkd zCI>qMH_s%vR^om7p8i?N&_{|F6#L;I1TG%|{K`X6PxsuXW80%8$nDkA$u-07+z0)` z-Wwkrw#xcl%-jOZaq8R5F(tgWq#W~Z?HJ`IEF?56*XDynGryocThp1MExUDe*gDe@ zXrd#w&_optWlvSJ+6E)LANnN%TQZF_huBdg!!|n!W9u1tPTYp>=3*l_EW{>HliMk>A6K4c44b|HPqbz(o5D7|K^QHhowwYIyN{Ui!i z=wg$Bw8N=lU0hb#W}%{w=O;s2pF?$=1x^H}hp@xR#|hypfqjqv%-oLVS?1SH0H2H= zUIM*)%lahca0tsx5Urd^J^1;lew+WPIe}rMcjO17C>IW)O{~wGwNtuNYFa8w;oill z;uUr$W^%+^=RHN>+DIp)>gq#5r1ijnz$(E73`~03w$}imC)`$BEO|8($u7mF8>!+n zrnw!`^E1r2K-a&97_|}osliys!=A!q(ZKcV0^K>JvDZLGRqBI^C(*p>C4F!CI zg&9MunI5RzIL!&fA-3iaP{AOI&xF+<24)|rPZI!=6`Rp{5Df5n9zd3hDFo&^agHsa z1mriHEpY9Cme~h!`81(yf2|CZ3^~gOti$U@9NtBg71I21MHkK=4{I)k0<{{zU`nZ} z3JM^sA~>#4%hfRU!tLm2t^{M#iT5Q zpITFKKyB0*qo1Dz#Sbcm{8<`WTVRLpNZ;zur~n3)MtMaB?{5VHd#T9#)tV&>9qVJ}k#=rXAsyM`;rNsow#~W|R2lfKAjLH&B)B9I;PuN#d-%QQ$&w3Ar;g zO%e2>>t6S7t@?b^vi-G0t5S5(IA{%DJi;|zcW31Xb}KY$VSE>y_>VE*0EV|7A@GPv zgQ;*`ymwk>1gP;L!@Rkx1U9|Tm{#tW!(k}1H%2!*FlI1`xGnEIUE=+S$jD#P;qZ?l z7YNiW49>EZUYT~mOXF=a<_gwSmXzaMPQ#`wz+2K0r0>2NWIY-5Ro#P%iju1043}qN^D7pSFmhPREg>EtLFd@1yy*{vlvhMaIUg-8ANgt&qqL?L z!PQu8o*}fD-e1~qK6xv_wSDWAZ5=4!jr}+P^Zm#QFuFZft$?9k$x-B5yVR(2ar>u( z^pc~(&aBQdZe!INpY1;a>Y)*&%L48)#JXjwh?kXOYh;q+F1 z$4oJEA60)uZi4wwUG<)1wOT$qx!Uq{kaYk;@-*7XZpCa|K#YMbaO<9z3V^aiKX&KE z*9#BPU8KwURKtPjHYyw+7Ldmk$4juRzEFlQMR^zJZHvhymB3zcNYeI=f+jhsL954{ zlJp7GbD@}X0~z&|R!mkg$4!G`G$dcK!5s^%p5$>!o{&6>P>FZqU;yFW;>huFTj#Fj zV;z!gUaQZmwC}Y`$UZ9#A+tYpxpE-`*?c@oJd`&OU z-Qi(g<9_RlIMrZggAKSsb|4%;3C;HtSE7Qoe5HWy4G(LGt!u+g+ExD0w-syz z0h(=Va?3`ctJmj~Tj8jERb_)L`dyQR`6OO!P$%7~dO*pj|ETB^S%27>YT)Oj_19q# zmCq zX?!l%@Ax2yVh5zkOdTx9toSVz^!ns0tw5NKyj=neXIL$KbFF!5H!(J8O~AhAb+T6D zT3TnLr++r0gDol@=rC+4C-wd?re)yge%Ypep0~@z-7p=Yt@-PK(!I8M7G__I%JPOI z$K3o|L{|ms(7tyUSA1JkfKS_qb%Bq2i7w5lWG*k!bG;DojD}}spTVUAtGJ!_)Vxtu!Jt`XYu-0tA(IQ&;|Z&3#b`TqrvD!?I9O4V1wkG|P=nYYpn7Owo>irDZJEQKUB~w0%h%_+&<}*gN@Z{Yts-HKB$=|#m!giX(H6=X z9@VhEoPn&wSS`;|BhkgRG@xEkmCmd7cZJuuHuZ=~7uV+}~m`N;W zqkHH8OOX9z(^+r2b$6!v3~hrM>`G#u5tx9gZch|a-Dv}k5fVMs_*1L-QgT#+tH$L0 z+$8BR_4;nIh1tGaQyWAE)L0B%!&&DW(c6j{~nY)NK39p_x*cN^y_}$pmYt4(tnH@ zW(Xy{u!D19a-3Y0_n6V^eye`?4G_+G{9dUy#ec6<;appK!U~>x-%hk2pD~S=gxAPS zqNg%`=p)@D%XR%b44GpTcw3S1v2fR>ygDwWS|Buuu3}E?b)b_>I9zK%yIW}j!N}|w zaRPW>?Zm?dXvJhHs%&PLtkX;T6Rle@hVxds>jQ&FM8^RAnp(eNfGs=iWMbI(niwB0 zP^=p1k<*mXnB$@8vF~Y9>S%Vf>-9Os(T2?7d*05;2|ZIWmsfi{i(K1qYqUZFEH`eKI){->KHPGB4n+9KC)@Xn^oKv*2o~vJd;EK5(FtMc z$eOlu-}-m6XWf$q`!0`1e)9u?c_%j3rs!_c64RW!bua+v+I5(jV#m&{lAY?*AnocVtg84g)^kvnz5igj?xWhdo&6=YH+J2rD;~&4)P|ssU}n>u zK&L=g&d#rmg3`JH8k?8J8h$bs?yrGm7kwr9U}HmP>0O(}cb{fTFXCjQ~YQ`vr0y#@3sDux1d z;U3mO9h+kK7m{cwi0N$I_7GFJA>}{9Z`Z$KoG+n(i@Y;y^D;53MkdK(hc)6U*S_Hj zO;E%@|x8>V}{$S}6A#%rFlzCBU;YdtkW{sJVS z2j^WHpmrIX8EJPZnotn2$HfWC*d&+NoY~qcl=0Vg{kG!i$67qy8C}%);)I_aDcgNY zrC}|ai~d)Mb|y}-{E-dhLG^JN;TheQP7x}bUteq#}Z`);G`pRaXVZO|JT=hWVrKIykA#ujiX=iRsF zh+Wpfy_3Z=W`zARxTQbcdND<=xQ}T01%q$NEo*QLhqqgRJe!k@mZ8EKsicRi9)Zca z{IEsC;f!SrF#Y1{Aj&#bOOaSBMb!&NX3En&%{pbU(dg$rA2>B@jh(~|q z;x(GCBjs@#`^g&hbub=fnn_>e;%Li1TB~MBsRMbW^jzf1( zx5&9oFPRT1?mfmg-Ek5+!y$D`lkj>v+fh%$X6O`W36moOWxNI}=^kM_(?mP5@W#BE z5qAr2$wxulCr{Z@K*B=779wz2%aT@-%9+tS{Bsd8)t8C%^`rn|urh2Xb^}l_&B&S! zUmIO_)H&0QJI{7x4YFKxMwM{!>%U5f5Cr zCr7aWkwd9jk@^O-T2*J&GZkp;?{U|&eswu#oQ@FXXA?>=grU3{TN`dC*^VMNTAKr( zy^`e;+aJK;U`QbIo6%>+`@0`=Y0LM>$BU z?8e=ZAvgnIbk2002M1R&V_g(GMt^v~K3L>^7F8MA-5;M5-t*-odrp30vuFPsq3vJV zwMJuKdE4a&aWt~qrS7Y~lSl4XLMf7Yuk>E@h&8k$!jGa7;EBKA2xje#vMy^DOE|6O zBpL%&x=5Pwm$q!4h|l^|*1RSu9hdK=(C~G@TqTT@U(lU31)Pb)_5pjp8m5!q+bKly z#}C}AYwVZd$=pTCz<#rEyI@qk=BKxIk$Y$AGUpU0#+l$U3)PJ0#3%N@Z>Lq@*^a{f=Gs`cV17bY>i?PbJ zjhY{q98;81WWhvuHAYw*Z#v=79jbWujq{1L_uqfR=AfhDEo?EoOM9Iy`s1;XMWCKt zoKpT*Q!a(XxzXxP)Q4VWQT>%$P|zgtbPYWqHS@AMG4ElWpD3mnf?cnxJ|`W25Ax8E z*Y#n&gGLwZm1y=CdPmFBfDNzlBmKME3qG5xXCc;w99QZuG5uxy_qjnK2FH!cS#m5H z|Hmhkbhg0cKgTK^-{0YHBxL_4ivc~5U^-aNv<&Hz3-qH^oH4%nWBo^-U} z)zja99c(B)b#7jx$nQ9f2Y+0*Gg7hF(4Y_m@98KgA3IXeKwkk*cJQR2piZHrpaxq? z=zl3x|9*Nlh5FBX=!?0b)@$GhjzK2VhJ=Az&jHpd+R|>@%eN<+>_C=Z1Tos?%r95;kEA3?Eg}5G_Vlnlc(Gnxo!=f^R?kOfV z*J21wPaM0X#NEbfk`f4^uly8VMJr03`B3fIIevevLSaenyYyZsi)A3e+}u3i#r3?r zyo7h%4*!TXq{p^AGMZlIeWRnAe%|0@Xmmnya&ndGWic`L_G3BMwy3&6f71b$dwCaL zszyjK=~Gl_T-G>b|D=!MgItIF`E1*-N6L9P*x7edNARzF#rc&t<8tPjnwq3|3-0nU zGblTZGUO+D)3p~)_Pi#w_r5DEbblDp?s7wZcxcGt$m7o+J&bFrw|g0z8f6G^XSDh| zIy&Ubbc#=Hq{;W_!7<@zDr_tNIg;i%0*M#VA920xsxnoGVv4mZN8U~e!-WjZ`pVry zgbwcSrpE}CU1CQDXj#-0!wtmBBTjdkmGQiIq#REpI-UPOSu&)K$amb~0)F)5CxNF< z)WWYY7qM;S&+lwq>v%?uhlRY-F7WNYba6cJL(5Rmjyi9-h5Cc>lQapc*JzdKu3yRB zkotI^^Fa8^O|-(QuFELP^WvZfon|2;CsKCfQ*GB28z^?gsN;kd@?O`!)OKNc&iZ9R z>`9PLy>JL@Bo#wBm4DPZK9qjhv3_TsY1w7ea`U&)nlfl7)F;df(Z0W*G}taf2}5m9+s6*a;Hg5vi+n1{ zC*w%RepF!uAM9vkGZi3uI`1eqellWPs;?Zo|9p>d;_%Qj_8PgoGhaFtEYo8bty&VY zW@(7T#O|>jI&G7%Y1HEa-^F9X*w-oA63cTePv#%=lCr*tQ_dckG01x8vrYx$MPnWg zIPF@QsZW0VsOcbs{jgkfC&f$@7s(WkJ&|O7JtFLY_H%y^%w<#dG~o|hl25N&qwn~D z+b&4m{jz#F;MVJkUVgiClg_Pt{QQ}6A77?cRaNzidvJ!G9(=uB{rO#HCeD1ECbkHJ zS&IGad4y(fZ;#91VZfQH&CN{|H8pkSOx@27U%9bsM{;H_$t~ni_nJ+w`RVp=9N2+X zNXp3}CEsY0EnE!M6eCPZ&;+ z4OkSo^*v`tPp^v?zfw|B(;T2Z$Y8|dW9Q-N=;mt7W94Dv;0XTG&$ z%ku;UWoQcG_%TggH9J2$+pE97)J;dP=i%n&6-=3V=rG&KQ|xE-d0f4noqLZQJ$9Ul z)lgGc)XC1z(*$gP@5q41#@Wi#GnMf~FjX*hDlrN7nD}l)YfCW2B#sT S3?7t_35Fg#zc&BAuKquJGeSuK literal 390922 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 KRU!fQB}n8Ml?_ONDa^ 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

*Qdq%p++f*3 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%0Agr~vp>JT z(-mgLq;gxn<+TD3pER{`lWu=OzcQUM6lsiaKSrOdJgeCu2M_2)>(O)^VEWu%Cl0E^ ze)qP8dRRW^JxCtPmBJ}Mk7kE3!y#uRy9{3{guFI=e)kd&s)H8%C=oz6fy~YHl`o3_ zN7Y-#McF>@!`Cjg^b*qD9l9W$(g+ABT_OSk($dS)C?%2t5|S#Cih#t@2+|#rQqm0) z`&``j{rx?kKd<%$FV4@L$IKja%$##677^;%+{d}QljBwia;=WADpde-`Q~OCOMwAu zQ%)R?orf9$-T~;=vDcrhiu5!5QVu?S&RKazb}3#Vw?%z!x3KyJGl*gUOVxJKL~aoy z47`Z!_XD1nQ1da|ESWoyTWvVi)(>0Thg=rlv^Kzt@yA_InmE^#;4447f;BIN!lb9ct+`j)i=`Ta^lXdRz;4$>ay*(fDCac>wdyD(i$H)*ljoWn}ozZjhc8#?ojy2 z$e?K0k7A``Y;*0xu~|-jUe}4XFCUHyz%75t5Ju3%Y$lC>HnOY0S0`*a%+6S*`+ZX{IIwk^yjND!B@4HKT`L5oidb2aUjodL}V7i zQ4j*?AnsACLxMPzfzFzqhi7zD6`(fCMCF59!bFI+z#`BxnKjXc65ri22z(q#_MXyTV-Ms@#2So1F zntmpZM^9SPJ?hLS28!El6w|73S*ACRB)fGljKOpuRTi5g|I2Ik_|pHA;2l+VR1y!& z%^{a?$Mx4BfPm6EU?1=pYuPGF5r!sOxOq`?aVSs>Hc}}8QLx;XZXcu8mG@nrbB!2c zNZV9JagH%l@MtP@osCWG5c53iucuX9iM_S~c;Jc^t7F<`AN-M@RE(7p% zLhw$~2}idxh(l1wiZ)C7I&itu5G`CufITv*H+Z?{{2W;y`1m*7Sn~eBJ01V3iN}5f z>gKmmCy?2A1$s9ka>a{Wb!L%eN+qPr!r?q)P8o{=E3mx%^7>aEe6X5CNnOIlO(z^R zOy1eXSd3QRr*v$omFL!Qo1JIAnD8M`2m7n53?M95FUgFt{?LZ(g%OVl(&Y3md6-zM zy%h3`yxnZE;h*U9E7=qjnK zMnloAQX$@FbP#)Xz$TZ%_Bci~R!I@vM~9A(@KR`o8Z4@x&2aCupyf0k^DfJ*&Jo%_ zOO8No%-%a*!`;(M*Ah-#j9655siFxZ3Ym2RQ{!*T;qgY8A1z(9ND8`{}h=}!Q)*}g;NtMu0X9N|v zY9$VcBIV+QEill`4c)O3`C|3PSLYn(0jstCt@n^5e8hFwn!Mh%!fu^$gM+9c2FLfl zPHjiaik zPO~vR6)Q80^dmyP72&?5Puoqikt$<2JomHSO8b!fRB|`fwm08c(m^)XPflW&tCCrYTgm+S6$%6J^^ur{&A;>Vr1Mb4{kaiYXI z+J$4ug#bDQWBSBxF+vaHqp+VC_E&zx5OaMNEcVreR@oXHaasRo2&7XP$nm{wg9E?n zzY3rjfwx48_(B;k@U((2ZzHe0hTXlvP&4r=^(D9^kVCj?b3(ihfdfOjOCS_rb-}P{ zl#82a!!4mmQndB!P^!;s!>?($F1!i!M2oPwB1tuu_QKfMD`azb0iy?fJJ92}NVEo` z)^PLLkJdBckeW9Ab|Q=_Yn34*yU0|IG2{Fzu|9YSBebbryny7aEs85QeW%0RwPJ$f ztl;B&fp$v|#2Ggj`m?~SxZHDgKBA$!VtVt^21<#`17iqh+0z3x6o&9eC~?Rr%*_`? zNGjTHAuK~jmCFSbFcUE+{?3a+|BM28BC9o5^1H38wq3|5CXBFRPxpcx@s?k$m1nRN z)2rJ-ejEc9hsPJrrFPz-zy?@pcAIuk#sZQ!F7M%LkN!dT;SIWN!uVD;_cz+zkN<-7 zxHR+YSE@0(E5i5jf zjmB#!Pv5)@MX$bYYO<23r_Ddn;*wO?sx~Qj*2Op4mUV-IZ(ft zYg2noyk}WpeWiQcOc1YnInpxG|Bm=3ZWAYO(-FT!HM79|UgkyPgk<5e%znO1yZ4B< z9n7KmcJD6)%yaksm?bjVm!!wJEHL)R@T=%-P3d+Zg_)wp`y zR!#~7hnt=m0E~DFqQMvfM~lVHq$zrdWfKy z*cx1=RiXyks-&yd_zZz zw9UzyeIIVrzPb@_j6R-IV)OV6#V6bg29&Y9_`bZRgTSCMBF_gy!z6)nWh|KqS#Ayq z2DpN8H?h`Iw>Sd|K3I8MCVmV@3x~{zqU4&{;}0e;g1W8_!wUf)!A6^6j0`eUM6sWe zL9RUNv@!sZnC_WEI#S3OG<>-}7yk^(^TfZ6{(;A~)o;?S0_??&NKDM=ZVD5BDGuo&nTIz4@b#2`8_6xYJu zi{FZ{^>DaeI2=f8vgwF^j5UU76JbSd&Sw{ERC*_RUTNiEvT$;Lm%BTQy#S{nv2N}) zEXw-610{Ahn=vV>2}q7r=Nr=F6*hg!cky4;iUgyUZBP5H{TN+-i$0w9c6{3jWY~l6 z8wYXS#?j9muyx+60%o}SbP;#wRZ&b(#ou7x!kwrM@{WeYI-8z^X18C2GMPD5=4mLA zKxb%M3W;+%bl1Q60gp`xrel zN}sY7dgyV)O?*F=DHZdMR4_^Dt+Y6z#0p%O#Mb-$SXk0DQzevKpCcgFwDFPM`-${F z$j{RT_hk)SYzq&4WvwXMg6551D`V-#s*{OBTONZCU7b)Pcr$tq1spJI2&-a(+)y(i zw=zg}$49X5x$09XM@!#jxgoBFPV*=Rjq)HIB-ikaD0R)74(h))|r|8 z;7|l`PF0ErR12>$L<`0rgwI8Q*K>U4yY|ii09I|(u zwsHm#hsWuirmCl6;|G*PC1lpF%%KYIcRNodWd@_>t~5l(^W%Ux97!is22gTM(Ivx* z3Jp0t93W@}qV&#xve8<)r5a#7|5yPb3J)|W03d_SK zmx4BMD~8trSl6#1SIo^FP)T|oaP)g!jz4x)<&-;UNFxjGBe;6exUc!}Pn`fB4?nJ; z!M^qJ+cLWAJXL@l(1Fvac0PvzB2)rGbghE`M|c$rz-ot6`s%mlYbX_U? zhsBwz$1sDFgM=4aL8AP8?%oO*EPoj zH9FPDGA3b`=BHvOhfXQu^|Tk>kCJxNUP{ZG7VkKje;|=9axc7{Vf2BhGPas<@DNev zC6|zLVDUSRR=96dAFgNH(gn5|V(yTaqP#J~vTq#1HrFVLFjC_hn1fFu1{H06SH+uF zP1JnY75G#{A*xE?eXIJLj*r73JLpo z2-bUIokiOh)VhUH8d*eazulvZDtzpoJwm|JqQk0eB8^IrPDqFxW|F(CdnAD2lkP3J zV~We0thd`#~&`tyUw8AFgY< z1+~XiiDhH@#xL?Hb(=H^w1hirciCVRHlo|xX+P#2VM;YDx~~NZ90wTP(rI-|ce3a( z_?dT*g$6v!IuA-a%Y!cS-6u{Cxie47*K;=4bh-Pa&Q%KH05K>S26j|q-(qdFVK`qt zysPd``vszm152%==$^-a!}Gia4kj*bz#*A?taMx8!#U%=a^FC9(@bO~!E93i=j1sv z`PO%f(B(7zw!D}p3q{n|Q-vZNFBh>Eo*iA!><_Kh?@`i<%+I9AHkiE$xT~?hSYCI$ zNZ2cs*!pokQgl+4_arOUU&JUY-O~Y5gA>7aiYB1MowU$C4j+d0`i7`+6S+tH!*JIB z@qrtHy)>NEm};dvTla6d&FJGIFQ2j6L;w}R?^gC3_3wIN!dsrKTz(nwBWFLb6c>i4 z5NgBu?4_pJ*ZWl-kqV7B0jyC5->J(OTeE%F|H6EL@p3b|8B;-ddTAQk6)eA}1+~~Y;b2=!1^`n&=o@VlQnK>qPC@9YF zRZjf)@@`k*C&_u?HpB{D=TKl{aK`ZuGz8yD zl>+#)Bx%Cl1ABc|Y2X;x+&y=lZKbg^sI1et+sz+WUTrpsV?XqOG+^y$5^sKo(-CkF zuR9a7N8c_RZfdvC+G8b+JOOv?k2I5jBh+e``>$MrMA&4ELRH|{f3t9Syx)^;%=ZiqKH``jAV~v)kRN2B;F*zYlXjVM}gAR``bc9$l zvNqBD?U$O3?#)UVb9qLi&VdB2t}zNhs}JS~;d&Il7A#vdgEQ2aIvY%>a<5a%>~Cn|TJfFv8QiKD zBU@QE%$-yF`yBh!i#d(H3rIMI)FMGXH{g*#9p8r+M4kG536{v@vtHvx{-3r#NMQID zB9s0E7o!AvY0`>&5g}9#cxPf!ig||=r1W9Ghb-RA9a;?!Umx$$m}!lKYO=-~Usf3i z=7)w_O*|R7i40)QZvL;Pzmpj66c+s1;qAIy@1vfPz$i%qg=+y0YU^Jp+2MmLqh68l zj#-tv)&=-E`u5alA3-lxmo~^XR)v==8|YWEaw+F?MdbSieY#lE(-U<}m<4z3#(KiY zp!I#`TC>n$LpjG5U+K{u8?;(Fw)}JSC{S`rC>ZpHK`MNy#3Bypk{ysZNw^^sKm5bEQ^go)w@!^%1 zIjwwfm19pr;P@2{-g;E#LQ<;w!H1yXgT{$&SW$Ys`H6f5he!j~;|TRw?A%gNM2eW~ z8IZf_lE|(01*mW$0~rXJ_Nf!L(%4paJn5{K7Q)Dh&=m;<+tJL=jZ1N5ff2h ze;_Hbzi@xbploRH!AI!nEy{Im7~MNyYAnCeJ#GNZuRutI{bv7P>mzrgQ;97`R@OLv2 zp1#8%F`ulwBN9VPnN8|d;#2YOAAYKPB4)>BkOS6pT^7AJe#`iOe#_`1+dOBQG9>j? zuJa>~1d$-xok-)jMl&x!bew2X_-#%D@eWrcXTZu#L3$(?iYm;|MG?O8v<*T~((ym) zy=q{l*%*YpoR#qp#5*Upn+9~br%8S+TJMKV7|j!MqLi5u=kY&nR|*g6O`X^n^sae#vTEGQXFQ5{1VRXhlCv|EN5Pk3A;lN>^n`!R z;{zoz9HI}>x3)V{ZYXPI%c(cHiU0zYRXOazxE zaOBUwo-l309V?m{VI-;3=N@u_7#Y6dNt_`gy4hqeBMjhm1PE^vI1kJOUdy z{mZz&oEg2FQ`Q}&%Sco>*cQB$#wN0(#Sm&UzW@nj-#>QV?udHL=a>A^#I>2c+ZjG~ zoo+cf&X4a;6rM*V1HNsQiI6$^J9rhQE765#%coaGlSEr>aDU1)<)ve5?bLq}?CpOM zEM=JT%lqTxll-X^9r?vs&4~B6R8IX!rXRHX11)4Q$hL1zt&kf8$E1ca1JzQ@ar`L( zO;cgzF>sZBDDyTHuvSvwL<_p&k}U{FnmLO=Sg7cvMVO$r#22luIqcV0ZrRm@OcxSO zx?QqoFsUwCm#pT5i9RyKDN zSYoJ};JB4G)S&4uw(=#m(==h{&dG>>mb-bAmFkG;qtoT3S`Xy4;mDmhF+25G%O8-* zvRWI!TqL3M4@!RS*m|#`;O-UHT(AQ)8-xGjg_lOX0QMlyV1Un(NL8S+b>vNMjD%zx zjirrVa_EU|u@^u1&Kt0pmJ=CtvD1Ee)%E)2T%y#DJ67SDLcc>oGx_kDi1czZrFq>+ z%h+z-0kUv7sh7RiEi+_+BFCx`v}v(Hr@T-7My>ey@jr_G--&|}_q9h!%z_3>J8Vy} zu-kmk!9D+$L=h%Trrc-AsYj{8N_z~+TZgWx&ZkN+$RK^)BH#eOW)5&=dOqboir;B5 z|8ZJN|DmImKrf2;g)N6I`;2dj-Os1W%GETsHRnXX?)YXzzI_^59>o;QJfb}kSDBZ$ z5xkn2y-S~ZLW70tmqbkqe$z}{{0*nsNBs{c+uJ^phZif7?pCv404___$VuJQ^2Gg^x75_37|J&(|V8h+pOoBLQZEw5^hq1S#_> zjaqiM_vvzWKlhW22ESlOAUCWt?d>5}iS-qdLJQjEVb{}KLcG9FHr~>8zTeOa#g&0+o=(VMlM%B^$Lw$B<9@;@`uvUbbrp($ecl5WW`bYKkdd zoIGXG`F+77zSEN0sMR&}Hc!p#@M7xkRqvM>s#h(v5V14pRvT4W`kRG6SUyVDWP`Fto||IDnOCI@aN!e^e2chsw;Y%B-4bmP)q;nAg6`O#ae3Nw6G52|AFf*8EOdSfQ|ixVTfKR z!~t-wjs9i@dA@0m++Lpe>OL^#`idbyL33cqhso)@?n`{sy0z~w#)dYMgl3KJvj_zo z>9g(o37C~5?2Ans;fVodtaU!1^J4$dtF1!CDpk0BVoA`M*0>=;89|kUx3;ce#l32` zxuE2|4hQxeFC`pfmIUV6DpoRoIeCzc0KFB^wZW9tuaG8E<3BwY0V5AxFR7fCQ!<6h_($oJJnQqiBvMCdr- zD`%hmX>qUH>CLgNNGdt|o{h6p5PEgFuky%L>g8V#Sn8a4jnQt;ptO>F^n!+hSYb0c^ zR8g<^BQv>gjGkS}UCqI`sS;5C!0XAZVU*S7&UYMl zK8%ZdUfHZAO+H{=l=2rhwu0j|(>w#DBJEa0gj!yupIU^ncU7QT9`BopRJ%pJIkq!4 zM2!Gp)PZS+OnO3g&Q3Z+z2Am%0k(V(m!?%g=UKIW2EWEJFN4b!wY;FyX`_|t-A3%~ z+jJ1Pc|(l?bO@M)=IP!`{CIZG86!-A+^^nzCcJo0PGFH={_xao>w-M;XO2d5vh>Aa z^+~)3+w*)k&a6DBJ$hPbOPq+kD8v(Q*1n{;o$!vKQuzq!5k^yXT;yL*BbdJNw5^w2 zc7m-w=7_M-uhcGY-M%*1nZ5N#;o)ZhX*WWdi-_-aR>n z51IYD`ET8#gJ%M_*JO#tnVb1^+}rpfZW9BYQPZ^WX%zH{>i~qU<6API3upguX{RqJGiXc*N(i zEL{Dz$nsxeeQ3;M5Oku&7JPn31S&%Ab|Jf|3OvHCh<3pKjW4p)$qU|otU(4vFJZuv zXYuX3u8lk3I+CKGzwU|oZhxe&dA%M_*4p24T9Is)4{_~dmB=V5I^LQd1 zS3M28l@u+B6)!@((1|*X`D4xdyP+36r=#FpD=S^hK-ghy3VgodQpF*NPF|-;#of<) z&&{H=o-J|^{4e$TKZfC|hx$c>R~`^{AZoG+Q0_WyxXqs1NH_xFZi?IhVzI4rP^<6C z6I2y+TRPg^wOHtY<)do zBRU2yymOv-IV+G_%%}8sdD!M2ne{#(x{Q(ol5YhB@)18|pyN}Hb1FG&sDKe4Myv}U zjng&zrUO~!YOYf|mx3hj+3yoLmB=9a!HJs@y?r`9Ibi{%wm?>?p6IHjU4|kE)ewmU z@q!KpQZ}&?i>m)pKFyypqN{NwJkRPxEI<~xXm*<&Si>8<#!ZkQAJlp+>Oy%Fl_@vw zKbwnRI$b@bce}SF(tNlcWjo(`XUk%k;yjmfgwTSd`EU7X%xUBUR6#svh*Q2cRtakI zB4LAom#!B{NtZN%N)4bPvEvC9R-)jOOul>1iqb0Fm5gp0OzS@)s4nfSfvwgrZ)eDB z6;?|HYbuqkY3=Pt<@Y>?(eABr)EJ%@6=muvau9c^+;xgLFJ*PmuF5bM{py0li}hHE zQCG$bDq-;VY(9oae8)s)H91$?Hu(B>Q?!NE!`!xvQF>u>;giwz0#TjJy}7i7QDBNVH-M# z7w&HlbeIT0Bm7Kx1jb|g>CZ0_s8DwDwAB^)$p_PGsTtw4LW3l(bpSw&RguNSKjrX8yBZvuY{c zWH>7<{fn+hxW*RjhmJg#I)a>+$?+nck~& zkY>!H0yDkNh{mr%K-6wK=4I_G$|Bio(#scLY{ z8X{66Rh}nbr5Z8yeqD)h5SVK zkom{ubStTv*g1vx-n)39&HPEcPoR((^w}w<9$_kRZ#^KGF+PL_KiAfp0iQ;-LR2>% z`#t0}d$NWSXW*2(#pUbIs0hQIWiR#yvD71L=~ZfiiSv zOUKG#HNMWACp~^+7G#xVDEB114kJzi;%S})DR%o;3$IJ3sK#HPa}+_cAizCB z(hgVVv;bgtLIm; z^i5om5MBFysIqla1qMj07x!P0(`eryS=*9cnYbfP(0|ZVZzGf9e0(r-L95y8Xc+{x zC(Wun0o{Tx+dL7&#cay)D|&-!{w#iJV;YNOdlwQb*GU?l5;5p|>#k3@s5c@_4-z6C z_J4Qw1M~K`iWTZsvkb*WxbDqw=2lWo+l`o3ftlc%pEFwHqitGx*VH0~h?pHQuX`fr zl=XV}*HL6FlXX>pr%ttojZ?Y|L51@ixKN`OLQ@`zX$9!H7Y*F^Sjp)llQs2JPLe)EbkJtsksv+IbuX-wQ`k zvyRrccGS;_N>~rRgmb?dT;>D)Zu!>4%gBQlut@AzdyEl9>T`Ny%6>5mF@wKTdb!Xs ztS6}+{U{lF6mE-zP))BRgPnzx@bLiVgBjys?dg2XRvn!xp!!+D|KU>fcr5{gS|NLa zMw$Ww5Wm7-bYfQanH~Fd=VyYH#KZQu0Fid9P^0FoD@`e3i>`?chUSxpKf?V>?l&j$ z=PGoMZWB2aL43KC@O46hgk|tfj|WJMa_*;o=w_#*zCZ6z#Q_`Zx}kBV|5PMko!7N; zczRRk{X>{P^kVvzS%nQ8u@+yvs=BA#ihwSBd1dgu;G_dX-|C>g947)jVGL=uQPDIO zM5lIdhb`aY1n?^)_oy4*L*SHs=@b$_6Rf6lo*Z8Agy#Ef8(4MD%8l7DNn zgbIIX(ckUANq{mp3DAPOR~Y2ar(xfe#{W8h2smHX1g_&_ZRyZ3*tS@U`#8f+dC&%? z!xF1^xZzY@^Wslt;VZjRI|2Jb-z9Zaq6u~w$dwiJ5Vo4#tEVHv)IWFgJ*}-0b6p({ zt(nRe*IovuHQ~#Km+SVc3^4ad+02Z@eUMA+TOnT<(?Q7C8S+7V+u|tt!)1Mu`k#!I@LVfd#B$KpUU~1F_xbW(gyRf zUwMg(#+7yL-}Q{nd6(t6Wzf+){raRbLGyf)yCCq-qSuw2JnbL7OMf;ia7nmcAKT1x z`~_OOIm{0P!)K~WhKjGr7_s?xWTGnC)GA@c3OZ2LPhlpK~; zxKl!~p=R*@3zLhcQ?0{#>b$_`j9GLL=bU{wEBiOt3k}fqES6}*9M?APdoPjL)Vy{W!W zbLOCSC;|*p*B&>h_)+DBk+G!LJR3+W{5u-P7L3cjAQ;TiM{hMO3e}w4;%mWEK|o)@ zyw-+5o-8mR^YF5axtlULb60w9;P)2AWG&v|#Q;*Z$G$nXP^LKd%%_HdRFDDTc7()ZMCeImYoqykY#s)G7GwPUcZqc1fcpyf^K=}I|Oq;MXO=&Mj33VekIj0T71%bA~Xpd2vls3!@kTzJa6iy zh1kVnC-bNK-+TC;?Dc8x3vnSjfL#{zvvR;2cZ0h5VtVcJ`iF4s{QymFH<5vea@#n` z)b#y5TB#FB|7&-&x>)qvE>4IHp&ZGXHHR^kv1teXE64JwX22dB<;;*UvbNY|LJzu| z=QDE@2e%OkUwik`MT=o%;DZC9%)7!t#^#oONE4(?dFgvZ7B1>}Dn&YOEm_2b`$(*7 zy9zrngZk!^QsBR(B?3jNj_+JxInE*zMiD(-j{!gd(72~)SmEu4zlPVIh>C+>o~+Rl zqinKSDX}gff1=9HgN!e?^O-v)uES_n*E(efa`VH)6uO$GoQB_|^I9hHLP$O=0fplI z1|VvQTN9`P{WTKT>7y9(_>j{^-Hd@?!Pu}P zc%D8;l^%2(S)MomLG2!64nNn{b_yq?0Jov8$6#U+`M} zyEl1mYgZO;v4d}gzEgzmHwEv(8H4?#FEBqyyafkqHVBMN$^Us?O;5+_k307QrOaFj z&E!A=N=r$y|HYRushN4=HrUNtYo;*%RZU9o`_Mfpi)x|qdAkZ$jec6VD*6L=;n6(u z(Ic~97N>cS@=+V?WWP5oe+8M?nToN*mmtpa*+ank>CfDwI%JM8k^J1o?;-T6| zTtI~%sq9}n+E>g@UcX)j_EVHFAEwK>le@j+$%53~Ss;IeB|?(V(wwHo?v@s5@wOo*F;F*>dOMswst2?&1o?fo%mhvxT@O zDOI%P8H23gF=+$Ecid|{lYk-8`VAmY7hvM}L>-5UL((J-$kPFN_Q||RE}s`$Z5O>{ zSHFMe>s=bRVHj3V2Oz7RvfhDW{fE}szAjGqd#GEn(_bp-(2VfkC)n1ybIYxReEtRq zq8Fd$>>g0nJoz8pG{Br)Zcq3|r{!=b2;HM-UE5y|*?c^5OY|*B^dk#4uVV%$8&qso zKK(^P*tOCLUSp->@~}S`i8-K8j#mYy-8{zRK4b+y(qz8GF=@j!>Px$<^(3PFi(S$9 zxC`xoO~g0LA0tNxq{-?Ucdd6*_#ciuQl0OYyKU0;+{Io$!#mM zty6ZtUWo(MpE1BFjm70#Q#j@sU5(@5`uutINTO#eHTANeW{vV%N#`MV`^ZuZx<*`c zAYego%|bIN?WsGf6v&JOb@z#GaqYs*3(U3d@HqE=^>eujr0e8Wn~eWKzy==QBJNPe zK|tKCTC(p)6%*|XRiLQa8atUvN8?I)_f6;Y8^kWsew70CV&_JYLw8rrbrQXY4Ep&p z{F%6>$2%-pvTBhL(fOTZFZy#}B~a#W_PD3F`0=0J-wEhj?2s4P4|niUf=2Y_#Ap&} z83Huf`;fn$RwgA22g$ibjt+;W#v`t|Io?FYB$1;v{Gkq3} z5w09L&OkJ+89gX>z>ZbvoJs%Dj{t6W?9M$5Ue5N^l`OQ93VHXnHZ|w)!Vr4|Z~wNF zeREunZ>fJU{$338bnAUA!wPPNW~@;EcTG=kg$hcBe?zcJB!7c7!TNGnBG+SUliWbSS3;S+xVg#^!x4tO)XcS z(RDos4Sq>yBIjaR?B!Mo>B+0LuDzl~olJ@G3fp4mMxNX*V-F>qzvC1t=Ssy6 z(XuZ%shn>&Y!Cfnd1ZEn{-8O=sMRCR90VnZ@oL52SeP34;Tc5(OzF$XRERhHm5L8a zpLZQe%3-?V&O4*d#)ZroN}ae*H2H4p;a7C6K7j`+f}e-*+c)uAAdFsX5aK9=pa(5+ zl9kh{z8z8ZFaM}g>go9{mb>z%HSga4`O^eED>eQ4D}ss{MVJ^B4dxNCvOKG%4zqMG zr1@dwo&(c!jRg~Jh?^MrF(2YVw6b9_dtdV+D}OpIq*nyWboQ;J>-`tY!WqXA;g@(G6e>V|u`swK`n zR`2kp|A(fL-j1#E%Sds6IaqGvl6H4!{Cu7-tL_(#yHxh4(U( zs<2#?i$Alv?uzueB(JAK+RRZs#rb*}eK`*#1)zhghG`-IH*Gh+4Qx8Szuw88M1S!B zYQ&ws5tK0x88nyqg*&RHsA|Rt7jG~eUEE3y?~Ln&$p@-oCrnLaD?%DFl(~y)^jh1VpS+lWLbIuhF;c z0FL$Csj^>}$fC3Jq13Fa46{ydiS#I@s}-)M)siFovKMU@Gs_P;OrO8RE;(9+trta% z_veY`DXvI{y>G1h^l9Ss8G~juXv{6v%Unci6OWAM6sY~UO#S~k+3Xrj-CE0SSL>4_ z9+C^ZmnKT|87=DUSHRzu!(LkZtgDqHOT-$XK4vyJq@h z?7^DaJ1kiceq*vXgLlzP@OF|}T5N_9&e)v!4;Sug>sR=oE@XKU^8O!U(L1{&$nd`M z46@iec__B)W0A_stsKooD!+9&`uInZ{K29J+HQ-kWd#-B2t09w)oi^dLnY+BF@HVH zj(Mp0`JqV|+2CX_V<5E3F4S0Pa^S6V?;mDDCJpG!B!CtPKJjn|G3-uiS@Hyb?!ve= z&5aoIGD^gY5KqYR*pCPKvk^SCH5|Vp(H()G2~Ba|sdqan(Q0$rCBafqe6hu9r;@>D z^p7OiYapW>Ve%AKb6km_k|$tTa@?0Ibtk?$0KuFp1jfN|!Cw^>n4f~of(ea+{kRVD z-@(^2wRFJS@dKDx8&?F)m`8vm`t|3a4Ph|i2{^fSYJ}psD&e@jVd*Db$c8k$XI*G_ z>$seHfr~-(@tb3#9g|IwSn`Su45#+`U8 z!UHxX&0n|Zs_f_fPpR_33>O~`Y9a!=&5ulbAoDL3?-BO70N0TDD-W+$C2wuV&9s&J(h)4!FEzwAF7x07R(iz!wVe0H2ZmtjZt0 zmgPBP1!}|U-h!=n@7aP$1Px#0z5tWf`j%izw?HM4 z_7Q^qqEVYgCXz!3(G67648DF5i``(AG0_bB+!#t)>VU1?YD;It$TbRpihz3>eriD} z^Uvzo>aWc#9$OHe>w!9ob4`Zqj=>b|ZN@Zhwj3UaE_AEI2HQ}?wbwSME^sssx^Qem zPOM{rv#`Rz_lKX@?(zP=XSq>269{I?_u=Jw?*xKCubb~$t#bBUl*yJ`gd^%qq75?> z>7k2(z*LxcfkgA{=T~6qp)>tm=K6MiuHDjsWy8-uyTxdR_<*hMy>;r9${!j_E)2u{z@WbV_Qre0_n zxH?Y=Vmn@6dr|7vxr9r#ae2+rD2ml9_jK|(`GNz5c)X?ru>uy_F}jqvUI#AHXmGdM zd;GxW-BbD1Ls$X+MM^ zVw~KPl@F{8mh~=KEv&)A`jG#pXy#R&zbr``K8p-p(y+Jbn;>*`#ErPBy7Xmgh9ZJA zd@%@Ue;crn4P1y2RBS|Ht^6`4iFe8R^kLOU>wJ_#AA=s~HQhWdI2UyF_yp~_UrK@w zAd5pWOu1l?pZ^JWhqC0V3G3;1-<-X6aOT>*;%5(6*#4 zta5&lFu(A1%;`EH7VQQfGU4 zYTqU<9PqogF0U8-P0#PAqJfH|wz{{2V#y+(L_uD=q-D%;1)OM)gi}U?C+y+9NfqF9 z0?3dx2ZzBU%fhl%6LojH1YJ3e=!j+Mx(r4TKlAt9ua;DNO)?a11apMgo#kjCJmm-c z^r4_M|A9IVIO#$_g&30l;srmTbJ7|P+|ac#r5b?@!O};$C#o&!p935fL|;w5Q=AW~ zRWWM{Wuf=3mEXu5x-)ddT%8*YEO4SyB-_rfe&&6&AG3X&jDD&Gyz?sBo0+tK-*Ci0 zcN^U0h^02I`YyXjSg(BM7@TM+Z^$o-=&Aaz|JOptVGuDF^7VW+UdpTGL);A=Qo1G%Ra8Q8(GdN#qAnk$4ARv)IT5y=ICJ)F1BrGjd>t7gANj`Z8X9`-Yr0RZ)Uq&$} z!Duh^M?~{lj&v8AP8Ir|OvF!D&@i7^6d0Dg_9|;8UKu!^EA|0hhOz%1{#{q(ErSZ%0&ogRgBi9;=r$*XA8uVQQU}PBoSX1fp>}|dg2;c=J1K<&U?B*k78Ia`E%)*{p0r;wqs=;n{1*;LY&CX$lfCv z$2?@uV;5OvW$%&f3RwrC$gU_dv&qan^1JnUp6C1f2i(qmU)TG3y3J?=TH`8!zZomZgMqF#-dsMeOQGzm?A;3JyLR{yBhHg#{hFS+ z1h=$fG5z(nKJTM$?y~dR|G@S-ZRqk%}(i{gpexRdF zXQt3g@}kMw?A<&XrIFlq|G+M%=Y@vfjyc80mF;o!A#}LdnkG*Jkwwlr`?+RC(D6iZ zbE~lQ-as;N&YzthyPfjtz*W=sCUBhpv)le-@REnTkK%$x3Rx-!CVFTD|fF+yW`V*FWM*xp53LgqAZ_w z8Wdpb|2{NnNLDm7_oITWqTfJw+3sTTV7CcdcNb?n2vp1xdd#H20;@DnWtA05iWBjwMGW(g$0czBaw<-x<=1-uv*Xxpiuy!uqOr~MnAO^ORD6{kc z#uLahZr$6{+W{$)#Ju$cAJh>7karFgXNwuu$I#-0*C3Z$S`o8{vA!!>vWp<-c`?+L zS;H_hMoyZjYsg+U?9HPNxYopbTyvTK zu|WS-Rv^h$FRMgS@8a8k;D1|5?`q;8d$?kd3p-n3-DQib;0MxP=8ds!aT}wCgO{$5PEk$MqAD$wav^_EH-Dxm)ovs5Y%8&wRw#XCygM* zJO$MIwX}YxqCfH7V^DLM7}tHpPL)%GQj5B*% z8I3&=LR+r4KYzIRt?hHeVC>~j>&!7bi3H=_1T*CqodOLM9S7&$1W9+poT+|5H@QAV zsskbstY+Rb@z4~*YlXRJXAe3_>j?yTxP#u_+PNRYzHp%g@>Jr3b7r)^1gJB|?9rDD z?6u(bkOc4S%;e~|yNd^2yfyg13F^}27`D&_yjL$85R)YnvL;bplBKdemw;`@x6e`P zb*0qc&O*0-Flg8w{n1r1`ssGF&X-Ch%p=av$S>Twl~)DI{0P_~+^yZU8;;PUce}Wa zwhAzPzVx{I?i(}2s(;Y@W22jqbOHJ;?BE0~#*h>4c$-+hYs@6p?VqvyGThkX&nOOg za@kHo0xKl-oT8Mtn7N#!fyf-Kxp)7G-LI&p(WK zmvR1VBeFZ1si}FQdb?`eeyJH}r#kQvb;#6)X1$AVu%W?4SZ75n8ZuX!3C2w`VV-m; z_=5!PJK~-OO=G)M6T=nB#JsR-6 zw^MEMMu4{K<`>&$W19h?h=v-^EpKUwYcE4}rE`zdEr~}(-w#AR6GzA=M9)82?7i9e zaf~d4C9B28)CIvFHsvYJ-PV({^@VQ`;7zvND6gM@?Ib6(*t z-dnM#ZjWvS7y106MeA3zdUZ9FOv$*Lbq9%(%J0x#?fQEa1*qIfqbx*ngEsM3M~+-V zCFv?uPj1%`Ha~f8Y|4)ajp2w_CYJGuDWmQrEk1Efl8T5B#TJzmD4705MFcH*9S-bz zC~NVF_VSpsO<(Dz@f*?MY-t+-NWaPKOD(cc?(HiPXdU`wuvjl&yrJ^gq?AN?&T>ciIWimKyxOE8 zH3dx+KO(FC=z1m*lKp%KW9j8*62)i&`Zm=5L)eK|C{kSqh(Uru(w&$BG@h&o-BtR; z9j^V5c8>mlY?3lR68+_XmFP-eOeoejm;lAan!O+zqt+eLZ>O~;gAfn2l3^D>IN6ST6FaZ6PU!^c?^HaWi0<`yg`kVChBx+Xy*T|}NeUDSD3)`~A0J-r)#fBFg0Tf*Zx%8+c_T%3mK4zKo}kFs*~ zW3<4v9+(f|{eJhK{0c86B#hr7*{j`}g!pLrO5T_=_|~*mMhq;j*Cjk2`?zYX{a4?# z+E%w2nq^5W5X$T;HZG3j3k3C(itFQ_HvAm?rDctYF1X@*oXr*ULOw|4nGp0hbSL{8oD9MoPmJ`GL%(Sgg2ebN{Rm* zf$ofN+~<+LxO3%TQiC#JTtlAfCR=w^I&KmH%;>(tk2+!=G&^OtD88L?RMm0%!pX`r zO#I{NxX`t9wSk5EZ?^UM++!?B#&s%0i}Y@!Q5w%~r?|D%ot~(!VJ3etE+YK|bWJJD zUt2M0Q42??lNF>b9*f;kEdI`;xads3IWI z70L6;SCicKy`I5m+Qg;my~WqtlV z>_IR$Jp0sDOhT%(?%I7{ub=1?f9XO6WL8?Qg=N|bsYSZ&X;8gi^?cH|`tdqxHVM0L z{>AsHeNSYfsCKSR!=&Foa$=aa9Qp0>p4r0U{WX1GVWTIBAcm%Q`i~pu$0XOsjzq4{ zt^8Rm2#Tc~1)XR&*%f>C{Tl@SsXfXp;}y1}Z?7_B*1z$Ido8zZPmU_oe4F3otn)$t z-E_$N6aiO3H$g{1=Y{f}94?31dr?C=yJ)tMDw$S2yv~kRGmMC5NY*Wn{+F}E34x!{ zb-ZSlxKQk^$YAzaB{<$-gwJrda$d1$rWMN_KA?m5{-vf8o-8n^$YFVfC#(($eCx6; z8u25GosB04`Y0??E7?syIc6?I#}>VQy;R?3Z$#>~z@*8iC3x=(cEmhLO-2~&;=nY< z5D^=3)WgQnBR0F_&FhnssO!T_%@l9=7nM&Qf0O`>#v>HiMnL&-jNzx2$=sO#$_1K zeoK1XF0#DSrhAi(h5g%0-8pf)+e|LGbuUOd68vVXUP%avk7dhneI?T_+gq6Gaq&-I zxOsqnG9iI@?5Lo|I@S(nvI9BGJ_27sBHZ3)jCR(WlJ%k4M22xtN2J+Xy_3ygG0dt? zJm(+C6NI;NY}3gNoUfU$d@r2Jlg+f5HgUIr>(_+eQ>%TqB;CB%kxX zg=NrA4V4<3vy{If9}K(JWjC_-ZC8LjEpK6r!xh%wqDSBF?TcD^{nnGtE+j##_^Zcn zgnq9Uq^$WaR`&a2j?GeaYl#t6kMV2z3u}(V=d!x6FhV%`MnnXmmc2ez9+FoezU#A@ zjl~VqZ!dZi#qa5akVKPoRMY!}R=%k=P2qM3HG3tLJ|_D9^((Dn6N5kgUJ4~^9FkN! z1AB|YKfwOux=~GBu+azFN4uQHpT2J@)Ej2nD4M-nve~7-rXC?n60mp!zii)eVj$4a zY~jt=f5PG=ODmG%ST+Ew8n18}|E*5fNMGq*SY&i{HM=Tl$@-$gYqFWg0AD=cy-gc= zL#-t8+MPHmOi&Lw0&EondP)(`ovk?YM&9Smc<3-(dGahTn+&D92dixnx2RyRL?fAw z{E@w>xv9U1!Y6^q0S~6F0QKIPQEBh3N9jJC$fH1Wxq&|pGXikB@xTXvi@ln?r&*4c z4rJSfRJ*4hHCcXrlY^nPZ(|--%EyQCX_c5wWE^qM=IdKNEmvDrg#T+kj>Sw;dk6!ZS?_tW+E`x>dn@zu)ox{Xx#9 zYjfxAIA5|W zz!=$MmL1hHJ`t!^y9~qRyc`qr@`HJKK6)eBCf?RLLmG)!_mI)x%B^3St*#!FbzjQ1 z|6Tp~8=DEGxd0I(QBId$P$u7EA`Z#SD51o&1Cvv;Z#aEpSM7cGn^Viu=Kk!pz`V1_ z`*{K6(NM>a%9Sbg!=!c8u$9rwM??v6y(?x{+5YL<{{MOH!1T{2$qy6D>{m3YCErbk zV7g4&Q%lYNd?hM5slTP>?Pj@NsgW_$S1V2XYIZm|Z{Z;LokxePre16B_Zbpr^Kqub zE_CL%c#ke5*;^u`j zVakDae(36dQ2;iys4HA`zoO=-xGx*7luzM#G_j)-%R8vrkld2k{W zU-J0lu|wfioezNZmA8Xl<;=u4BdOXQIdc-;I}#?kCE=COeQFblM*MdokKAUJ0!Jyb zlzZFumP=Mfuavn))@paZDfBD(TJLJ^LB6$=-uK3hWj%79wAuyTNnHz_ji6(>(ux`1 zc(nZ@^xE5!A~9MgMiLy_{pY!l>HX1LLSQ6gF}wwC%}w~uP9XDWW%0ae%)UUw@PAoF zeK2Se#HO|8%J@H)_mJR8?g*=`EbUJR;#R5O5RDq%0lk{h9w8R91PIqd*=$X|Y!z@n zj0(zUsn|r*8~$L_s)nC30hkcwqvdaTn#-Dw5zOy=ihgYy!Xv&~kF+YS#f^Rcao8{J zf;>6umr2-*OQC+H$kxuFHARB<$|Gwd>hXB1QQ6G9wVonT6O#OTvqR5mV7QZsiWxqt zmo;U3)bjcUXBGQ!_tNNrki+DGj>$hVV&T@Fv-v>n63wM01N4_*u)Oykej@8kqn?9L zWu~Mt-}v*A@>9QW+ui;Q!tw=2@1d%x8t1&mcMsUN`_4xHXz+E&X3Az;`8?B3yZiw! z45mmb2l){pDXp}Mx%Eh8S)~)&66R93HoqfvA>D8GzZ{q(NT;XyQq00@&Lt(4O`1;R zUWOh*gsIJwC69>n#|>Z_m6P*lMUY&YkHKltz1ZerZtghRx$$EULoUj6qvk@d%!x5G z&}H)9E|V8z5ggtdEaFT!%gpJKlg>K{GzsKehAmh7Se{k~+l2rHf4L(YdzL%9mj@Q< zJf>7G6JBz|uPRFy18icJ#07wf&JZQ0#Dw4Y=(T)yK3fK)-hx-S|K0J@7tRvxQx z-AD?#2Ah)uz0V=H3;Z6)wXFuhu+EGd#_!+0-*_TCy%X@=cV2CCqn(39nc(>kmOBLV zYr!OEWSv3?*5DmoyMh93)z(sUxdd_|$&XCPf~}oDXRr34yX)^8)RV-tmkd8-C4Vl6 zWUF+0X}lnUIgI|K9`I7l_hj3!2rh z=U&vkswuduYS`#*sSxScKSaO09Sr#xM6aS!MVcUAW%DA<)76yTJ*4eT>7i=HQ<0gb zW=QDd^(2QUmmd-h;Ju9cFyA34==@yg{8l!H7uxwX5Oi@0o{PFhXiTfJkRYAEib(&1WAR{~pj8AD8EurhfI7J=5 zdrqkiP22JpjH|Y4)eUtoC}1oZ zs28&Oiio$G9QXQ-%*)BaYQAg>VgZVgNL69~YqC#Xn-G^l9Qi_)8lGq0o-c)%9-k%} zrQn(_KZJ+cjlJ)qG{#1M*LHNy?PXC22)DerbdK?aI? z_*x9F^Bv~=)8q6K{L*kKGgDXoFS;^FbTH<6UMlFHe=Whq!Xs7)cO=FLf`ejts(77s zb2IxSaCb0-A1nb^M&Pef9)N`E8FPxo2|#{n@CDy>Ons84y?D6_E0<^y|0sFRb|psz z|G;_0pi3Sy{gSaAr_{Ea-3Vt#t>NoaI`+_NNMpCyMW5RUDpp7!iAX8k<>O=31;>;~ z$T=WL;DDeUd{wXNeHh1qK(`2mJ_+C*nR4UIU_2p^(^5Ml15RMFv(gtc{KUT*8gHhh zZtJm#-9J7B&t@Yx>de-lHq3wOJeX~~baFhH4_UgN69PEi_$n&PvE_oq$u~KDar%Il zF}kd0&BJmtCmB3Rg6Dshp1L7{B8b7~8Q#f3*R`F2x&-E!_tp-$YBW$q6b~SYjG2-? z+eG1L140EM;yhGiOcv4MdmD7omz#f`zDkQ?Az2N$as5XAWxgdJ$K{`bk|$Z60o()u4X88Yp{T82 z=x*Bfi{&pNoA4)hAmKm4)mC?tMPJ5Hi$%~u_3!r*ucrQ~e;-Agz{B#7&H%a3$z`yt z#yARx=u7G6F3FH;cC-c^f=)ba1JDls4Wv}m^GX#zq@5S>8*R?6{|OU{*gvIN<$;s!LnB?8U_(uROYr{;DeocM&x1^+-h&z5?QYPE$@iI^tz(LIm76`~ z*MbSUFbD};hGYz&=j4EEcv0GweHD^TVv_PbhmW9pduO`(U0R7mlx?{CS%{k8lkhxH45NsTSux08q^E)SW`Q=fA8P)>N5WpzqN@ zo@8$koG=L`56h1nBG)QY3U~!kk1u`zHL8V6$Ie#4`E3lW0rapBiU1V@H<|CE^N-V!Z@MfW<=KKsgjAjLa1yvZC3KPOEdl$=GDrT zy2MfbupA+XH(~Kzo%tbbI4pc!yx#M?viN2jC8?}~Ha4kga&-Ry^_!?8W+-fi6ms@1 z+K)Vfau-x&r*41;dYZj{(`DrDz9lTdaN`p8im5*y2XF?t$FDw4jDH0@kk)Vds2(55 zJ(K9?Q|C~(hLfzS0*J61t*1g6ZB@7wx8E&_^fhf{d0xghKJG(2`(EyoMib^+0nbRj zHxLz(FfuF~JPOyMi;YGP{i!irxT)DKi|mO~kgqA&P+yOQKM_WNmW_`t{+OB?4-NO& zHgfV&lOXwwwR1;&xJa8OH(O%Mv#-G0M0|-1lTH~#*d!ACBFU&4YV6(Pdq4QY_#xa7 z!B9(bG*HZ$27gG4vOgN20eMV}Fy?6yz*O~VhPjv;$gO8)Cfw@!9TpVlEsYbTA~Q?4 zG{O;H>zV)$%e4QAYz_Y(5&6#Uu@ZkGaqm28OM{^}ikCheMo;$$6fwZ+xK~W$@c?R@ zhI)?#6O@zRs$y;M%LOg-Jfg!~3A|87O9I843HKI3-y1srV($55+ zzf%qxU`>3S986pq$=`&?WNyce|yxjPu#_^JQq>{Bh)BA7_fwBs{) zA(j|Ziq23eYT}Ym&th0!TA}XDCOjT1yV{HyLO^W_45#VDv_q&>NPe}YvVOV;%jb?I zzDMGc4WDiXFz{cUC|TzG*MZQ@klZXn{^lylfcDDy{$@Jp@j=bvK1Ti-_O>I57Uj;Z z&D64>kCzGi0r1BP4JI{Ke7DHxOD6&Qhpg}5;gnC3Y`m8|$3>7tDDNu?boHmRr;ROI zc_udXuyT(Q9^BHkc(}~U0|KSZ@;+8~p9Y@%?hE0G69`5LkR*IH>K*D+BW!WuB)t2o ztO$sZhW*GY2zTrv#wK%~)!xT2D8pHXsIJd!BcpheZef2{t3Bb5Y;5jRvh}BrQnUjh znuyh9A&T}pob>y!v@)c6GD`IGkcz}7^Zqo+3rSmW-Jf2j0MG4c1q$KHX#fIZ37(MZ z?|<}4puA1f+(Nhy;Zjd*@Nz_Ox~ecUPHg>Q7oRodtz?znR$C&_m01fWq(J+V_44r9 zkH#Po7k_ZIfnIERQuE^1ToMJ+k$cgr!Ls|0ZvvZr>x%4s-+@V5;x<40=@9|lqS7Tc z;?j+k0GECeY8{sJo7A|o{jWjLr?-bQf*KPuh~IQx>(h+<+O`zNQo&F^4{uxuBlPA@ zF|}BK3f7kKSnpni36e}mW5$Qga$JQZZU-@X8LAEbCxx;sJax#hj*fw;f;ZTkst?P~ zvpI*e@_Z$>W&|B}T$jN&Y5}E8{xIsR`Qv~zDXs!=BiDDfp#}QjqSL46W7R`lz#QbR ztr%czBu%7Cz1ho;`zi)4-Fc;mHn)cxTNKnr2Mi+}%4@-X!VeML+N)TQm*^#@wTL`z zz2rvs9chgsmC^fMTqh!f{IyncWe~00WEwC*qTw~533Ew_T47*YG>V0P0cth()tejr z*dIWz@Iai2Q+9d`!^EvibYHx6?$9$lnwh8d2|$f7#sgX;pS#%SkiS`;&_TaYn+uj3 z&1A_Z)a=T(3xk{R^&h6_-sPXfQu^9vX`m2%epc@v6Lz~L0#bCUBFFKmtMHAV?jv)A z*t4s?UTil3ez&o+-%7&Pd8{J?;H!;mCCT8O>xeO+F`TDNhS#t;Ru) zRSz~bOlVce)H^H4XckBcCg|hf4f%6xhje^xj-wQIXmbzCPzK+tZe0k@W*6<}OLU_$ zFEmIS*7T3q(diI_S*Q3Ocer`6a9(d>gC*Ng9EH_B75Bnhhb^Tdo->KhacJz`%Z5u- zq(Qb;g}gskB6J zg9cbQp|vc3#W?-Q@&2U2GF3LLCj1453iNn&ef57SJ-BB48k_mALM zaqDI|zJXiqhNhrB={I>(Cxa0&=4=ivOeq_gjJ3EBHy0?vOaq8{R#Gkr}}t}rl4T-zUg z;xgTp#&RfGO&{mVXrsc?~DKw%dK_~#-S}p&A?MjLNkH}kdP&H11C3aER#w5i6wf-JYMv%Fwykq z;Gefyal;p|eMSV1G)($E5fZ`_;Fuhll5V#Oa$RG~^TLTXph;-qJ>a&783&t-bbj4InX}IP>U`Cf=H*uo>amQtp(?Z@lboQ-q*_5V0FVr1Azz9jzof1K~umpi5Xdq__K{jLx4<8;6VK#m+Br*;n zEO96WM{%Kz!Kt~Dmyr(1kI$f$1mqG^OD8a`W8}=ssVbKLKciNg^^ST|i}AoNO4>sPp5&oE`kK=5FnyTh9Cc_VXy(&7TbJNsEACc4!xWIm261a9C;J*d52b| zzocw2AsSWr<$7-rtJW3S4{Z)%-Rbr!^U2CJ53H9uNA?83Nht+*Iqi7oj6TKxY^ou$ zDUJL&gR^8{2s&4D>1B~_$N?uf)~DJ~rU)3N+965gxcCb5M0D4Q z;ZLE>9o31%QX&$QXG?n1_5#8X$6qcV+Vk-=$XPe}A*UkIHT38dBqU z1RO7nPJHg`^GiXc;25vwD`RDt0e7DFZs@Hx&9v(CYy6@tR9_Yxj_BK>^-*3FzhWaJ zMsD1~oLPT~8i(Xs=-xB3D4o*}QMz&IJ89j+nD+A9JOR(t$uzrv^(=^*QTEC)Wap*6 z+{pvAp={MM$dlR6saKWOk!W7!e?{~~P6qQ+x~DXg2{bxAH8$_BQjG%{BO;pHX-gZH z3Fkjoz`JGRwv&d!^m)&&&j)d5!&bz8-{-~-!2OrL^SxWC#bk1y|Cd(_dLWhP&X#~z z@H6|?&VDQngw!QKt8+^w{3izc3uK0zZv!!lhB=Wb?cfhM=h?so~4KTqjwG!%m$O@ zoY>LWvH8kkFPJj4JSa^^F{kR|#+^Nk(!iDy!veS*-nD`~K8SB-L5N8NLd+tMXV4VU zc}&GHKIhGR>-XN-yN;0HM)>1uc<1&+adUh}F}c13@-Deh*+A|Ly)OSFI6Y>OLr) zW=S56Tdm5-1{JXbt*Z5^wyDT~s5sn&{M*6x=faz(^e4;Cp=P;3Q-OB7rCBBSxKTf2 zzEahy4|W}<3AYow2sx~Y%*4cv2*gMG%Svb}mW(zM`J&H~uYm}{>OgN&H=u71cimpWEI798sD-~avG9lv_^3-3F0 zz_IU*xDxHQw7T{FRqIrF8@4Ovno@^(sD=;pcSI-R=@j6OAv|Ao4fJ~z(DDp|NZVQ(H5KDHNQ@*$&iFK`+94md|*a*j!%42eg8*UuZsxEzpNic7x4#k*=a z!O&X-I5dEN1uox1EGRmes`Y#G&s60R^4FQ+=zA)Se)7jPwwpMOi{G$7_kTHfeZMoz zgH0Lb8j_fO8g^lkdtP9bzHFeUdzPpRT|+yaE&EIi(%t~xdwu|i!>8b)HE>91 z1`&=J@F9Gy{b{|RrT99L1L_))mki9!&tQ*i?gWlM?W>MTcWc%D5$K*K-~#BxJg@k= zp_`TYJfMxYK@7T%LCGAw_Z=7wJ=}h@^bsOpE1kbh8fF=*>0B&<6tq+XNjJqTWkx@F zH8p7)tMF$xKp|M}_0NXHi7uiZXE{dkPvmTro4xCO7a*+69Vmrh6CGgXDLz4r2rTO? zyb$2kgc_bya$7U?zYVtvykM>OI&R_dAcDK@N&xA92hF+D-7YvQwB{?>SKvl-p-uq$2r0Atp_W{%fQVZ@Z6r;fDp0Dc0aT5fw0&+CKnV zVoMrqz?fNHOhc>ZT(vNAUIM@af>!4$$$acQPZmoiE<2AT?vJd|v4l8^z`0$Y#zase zX*vg{oq!;d{fxPaN(^e`2*-qBzyn_KKkaAr4*w)7-D7Z%v|R{W`J~@0^43Z1l@9*T zPz@nCuOFB4`AyoRcW?QHM1vw&g8M?#$S&YQaGl^r1+3z>6WryXs@(HnfYWkgBrf^{ z#1+wA%)uw#JBz}3MSzCpGicDq9Fmc)FV9XPE?$4QEOub2A@NFt7Zbr# zcL^GOwlwTqkE$}jAvm&T*AW1LvD4f}sFVEi-wtiTw4T0O6{QE~%HZB1+cq_eJ_lJML z_T8n@rCl@*F!H~exiA`Q#|-_{0@WmN$_fhtn{$p|{Ha|If1euqJszIY#05CFJg=k} z*egiCy?sWLz0+HH`-~(q_o4!}Fy>v8()(4E_WoJR+S6D;{AXfJKRbq183=|RXLXT= zos^6lb7C4~kA`Q2_-6188$$2^SN6|NCUy=sW_Fh<@qhX|r!r@&o%A*2fSwI__Pz=_ z7ZA8}dg4VUkbR?K2!E$Vp=;Xa1@cVhI^w704 z7cdWR;;K4zYxdd?*3JCM=gk5$?x7L?HmYSNHZ%(Sb&`OK(dcAl_MY735xxQ@T`CVh zRj{AV{+g6O*F?|x+5D!PGbEnm^r>VKamlj;H!E?>Dj1IU*6->Qa_^avKC=^uUmg{U zobW=NjWjfxvgpUny~!umKDzTjYt);3}UUS?0`xgOF$GsYHitrTX(m(!V;*l z+OE>jhmTR{Es*-52x)1F(hY3Lh7{mU=nXl9*^enqT7EB8g!gGhWoPPy63h~htN{+h z7zt}|bk=V>pWQd&q(dEltv-(C{XI&rq0(8J+PHf{n)n8E(XZ^1jsBY7$N0-CHtB?1 zvL#@IlwuTv1RNxG%a_;7k{ylMLWtZ!*`_%9#GUuddNN@w(uwrIoyf-+OIGu$7@2RE>df? z!vy`SD%sap!Ny+#y2@zWmx3cNrM0is$NY(^Nw<~1u=>@dv8`o9JaRk9NVKPen)HQT z^fA~Ry;K2p!P-)Bau5bUny8p*=AX=sHPclDkq1I0uAm>ndBFypYKKmX27wjAL;9ws zW@z%cmX>IpB>S|Qdaql!w6*w+w+%7Xw)Q^2#s}qG2PvA+rmgKRP4}e3YUUiphpCDe z$0kwkJZ`&ASIZxBD7qo_`&4n{&ya4&FRdpszb0k=zQ_(3G`nX#(X-otc${ z$A>zJ5gRkO8GIHEtm0D)G-;iQNPtUm1Kf~lWk15UQG6F#z#{lXHvZ`a|8U!%^x9d- zGr)y?lThm8H^F;mU`o*#9k67OY17@h7i9U5J{x4e6dlDbspCgFCqIg~#Gou1jMf1P z))MdllAV4{AtwM+nE+0O_}6FZKh^bk&;EW#aAtbWatr%d&&M+cW*d|X{b~~nSYx~)ksR7;20MGNniGb_m7HP`h1wW3Cyy!F^iDZ1=YZ|O$ziq48P{pV;zJ!!&xD)eL;Ix;R{o61V)&N-PB8}OD?XIotWgFVz|~-}N0xh|qu8O+yBYKu z7G_CI!ZPN6f3v?R>Nr-ZKMtQ7r-MpGe6;X?7hQ9_CwP-zlP%F>!6jHB2%Jeg6yz_p z6eGd*>2pO&KX>Ajp!3R#DSj2mf)fB1NwPB}Afv^#8(jqF)q(1#wd(sz_dNCYXQTNt z9at%Bb!MR&slavwdJUE;LPcE8S};?T?;D6;?fjVVzHov&w#CM3tuei#&W{GlV17@i zZXq(2zc*AGbM6#Q42)VGU%BmjH1KVhD!;49I6y$IDoJHgDOK?Efc>PSUz_CosWGza zwO;PsU*k5&{GiiteKEucD3c6S5jv_kpsciHu3CNp_{ZM(Jo&ibs!ZYn&dEiuGc;xq z;vjeFHp!d3e%_hPVjsc|dJKIVtpV_2+O1xzZrOKt90`xfyBxjc4Or;JU2 zi+M!@*|3eKzVAKaW9@%;$?_J(4cSzGg;?&=7O+=8C2EouJv1{BY71$R*RRuQ3 zpriGOUI^YlF)hp&x_6PXD1UlQO{{Dy8@5)snF#lb)!z7i(^Mz2^o0jGs$6y;fHt$W zm0pGMMmP5dVqEu_-034}1QyMB6Ux}@ymHwm$*h?4$^2ZV(OIgoQ87`N=W8H(wD$4N z>i3QB+2*^yA!`&5v8cuwf6VXBx-7d z+Rw2Vcanzb>E^Vk54HZewKO?(5ifD5rN+b!F<%UMNljJWHK}j@FT(u|oC5jJNMa)m zvow9)4-4(;?)v-~HT9R%?axB^ySMPykU4OO0OW3} zlLftdvr(ovQNtaG^43Vf+&sR|HI$)l%N>2>{e7%Me{Ex09y9@&2WUIN%OUxCP!^JM zo0l9p@D)t)4sABoaL2rb=fMgl8iz2_U?L((HPU$zzuFx8WDK-G(dx3fsm^=Xt;aG( zf2fpAiFSa^VK{Cfu-#$Lqcq0CuTLbzz?eF>STM5g+e67lt>a*sNd@SxiW+3N(E{!s zbg@luw|%5w54C|!;??EfGHn-g2GQ!6slU~Ov-}#3tt6EQ``YabB%b^_J}>xu>OHxo zLI_2hD8fI~LiutPioxyc_Bk7=EQ1J!sE$kIQ=%B!QRT;F(HLccXy&T^65;~Lfsv6EW!M0U4ahNax1mn6*NCKlY%SP=Jc zvpsJ8B%}s4ye(}7eEwuqcdg?yEZpty?jtFR3 z=_(2J`rECK{bpl5LvVxNJ$eXNPy;Jtmm-~0hWfq6uxh}K?5gXqbkLdz>YYB%-+`6_ zJT6f<+o+!j-fe1&q^`BEfYU1=qjrRIWb8N+scoqIV18mf&D%Ii{1} z;YWde%mb{_&b(o_ftyrhuENA$=VoRR;k53!f*IQhFF*xm4gYdIcTgNINL2IUiu@lL zPki4Dk83s6+>N_VlC#9M7KKqJ8JCQ(rUN5*THDOYwqIh*)GOeqohc}Hx$Iwq;vPo*l8kOhuf{wcLItaIRX$QB!erX#Y=s? zq2<@+)L)0&rwO6l&P4V()FURG)*8cl3I0-94#rX+(*15~1&lg2gSyx|tB;-@Bf2La zZnIG18#l&*Eh)r^wwIA^fIJMSRHQMDT%5M}rT*NiHT`lsVFi^}$gma=f0RxZ5!~YJ z27mfpU&3F#@)e`Cn4gs;9)oeXMA<91@HKW7x-+kt9sE!CRiIK_IC1#;xEOSfL#iRj zvh=#S$FAjTa0ear@42ds(Lou1Yn319&!46?_D`0YlvLJ6tCx91lY)`g*ol!o=j;M) z+p+i0-*a&m0=fRpEL4dtdr`xxo@?P#SMuo)0C(*cVqIo@ekfhP{GEdsysLlkN&HJ( znkxe0J1YhUJ0C}Q6CHG*9>3T4NxTEk=efo+`+JD0949(v;RL6Bknbc z{-4idid2BD0HnClsVeNrV-xM!U}MI#-!F$}VYzV8CZY9@_9w*7wtjyUFvRVmz5Brw zqVC^DiZo1 zPK(2Bt`%$xsc5UO?dN%N1K}1t1?M>sok*qPmyRSl?lGnbm43O9BwrP!wY@!M^GhCu zP!%VrD5wyyY9xk0#k75!$+9Dfo!%nBE_u$^xmPhF0Jk$4ZU&F_JZl0Vk-2oG1IZ}t zPIIlzot2T9><%UCZshZiS|P_B;c~vDI|E9@Ayz51$UT)6}%UXH?2{a zPxnKO#MeZLvr`hUuaG~n%v&LPlUZMXL}AkQ_v`Nr8wbGJ@#pR!%g&qERcYiKode%o zgK2?En9jDKBzd7c5RV-Tt0KMH#Et`q?t5L>q z993oKay&?`gZ-u!56IAk={&u~%a!BTv_?qp<+ja$PTmJfO zMBrEML}dg)mS|$ani6PIrfsqc_S-&AP0UFe=T@|{Uk zi9c!wcly)RTU+?UT)7~E@|HdsGptw02`n?e$JvH=FvJFv4q-77l!$rTAJ`&zeDlVm z-9vVqZWmhkyqjM^5?|A5l8~n2r(2!GIhRKAJ{c_AkvYHZ(=pMgw^!3=j>$YX(`WfK z8reORQA~v%R;NlSe&r087G}=>b;(Ru3YQMf9qv9gYP(Pzvoyvyz&@a{58!g6{w=18 zxe#j-;{Eg^r~3yMz5Plgn-V0e=@@AQ4i;|zh~VtFv6S-BIB@uNs5k-<+V3_s`&`)k z0*T&k(_Al+)cRZWAj~yXoTyt(AAfjqs*Kel0)2LrGz*8Ft!))zBM(#^lA-|)Rd_@JExzT-1 z3&v>U!c8^oijbFi_Shuuqd4Ffcl8VVVsV@@z(Wo8J0vf#f({1ZpxM>kg&?-Ic}3Yo z7EjvRnK9rFN{@9e)lu;g^tnfdpU)RJB4`SwsL8!j7 z$f@A%f|Q6FP59n3J_bs{4mR-YV1yyDH7zcO6KAO%_!J{JobK0niVYw~(6l#HcC3{m?IHyrSIR%a*UY(+gRYQsusFk&{-?G)BskP>|I zg2CTCU1KT90q*txG4&NtQEuPc?+gPB4U)o8f`mv3(lInjDoU3kCEW})11O*%AV{}J zC@Insqeyp1N=SEiey{gl|G$s5STn#Z-cx%&&))kv=P2V?S$)RWyzylzgRT!7HRq-#F@pGAHb#&7eOP2FisV2ds?nH~5La zi~4-tl9kZb(I5$?1e-T?VTDHoISXo_kg20tG62SKWgN$Ns?+rFd$;($H5)7+FPt9o zPQ{uXAa(S(%(b?ppWx_8ljO53Bp18*vh{XOcF)naEBNrXk49}%N%+d{b3~cSg#WEHJb@6iRJ>C8Un0)37n>o6XH%edkvwT}Kva!A z4Agai1?l|VEkeOiGrJO1+e`YI?IPLmn`VO#4eK!CS4!NX&VJh++}6WpwL7M^OqYBg zT_(&n*)YF%??|8*Dqd9yR=zLaB-RPG@t0s>B*4N6@^F?BVJn#N{nS+7wUYKPSCd<9 zt9RWVf--W*qiOhPn5n=&`ox@P|I|+FUZOIj7-ob?ADe8dxWL$(+XtM9aM+4%OwARv$q>X)^jPOt`Q z%1RsE_qntnyFq-x-fa~dQ7HP`v-(88l`D|(CgheRp#@Fuw0*;Pw2g9+6$(e`OSA>K>lnR?8jOI8gcik+anH zxM%}k(NZIjJL{A3)VHh*QSn^xs^vb=8(sjM=S@D&2hTiLrR0u<_yN@qMd$%#0g8xg ziHZcJ!MWF#5>n1)b7-YzR`7D69e3AvqPhc%FG=0^Nf3BK;SZ)m)GKI9*P|5X5BArl zyRNimrAc)-9~%=_XqAiEh@7{!;YZ}`<_MJ?fA^gq{d%QHk3MH8yHY^&QWNJ^dS*Qv zzZRf1`X!t(x3bN`o4yo0Sq#xt`*zfd3u;F#KJe`eBt1a)7TI|ky8v+QcG?RlHjLt# z1u=K`wWe3`SY!dPyZIxjM*t9mlAFlyu~UI!T}lqfEfL1eTtV%ZgGRNyjz){g)|Pw* z(Mhffix4e^lac2heIGieBZ2M8NB1;Gc}X8L*3-t3Sq{07x_81@@ihrD3sM@L<>zyq zz&Ld}mhx(!v-$=p8z)yh;m?ED3Xi_snqw`C;#Dg-Z6eEb|H!)#Dzl=CQ~q(^7p)js zWcap!^d=G~bLpoO3`5G|;HS~YIb7xIdnfYMAFq(Y54j~O;UM@(N#$mq0OR>FuKH5( zwR7P3r&>;lEaQ#o^JFK@SMPAP%oe^y%bJ?7DnsutX|?TMD!8tuZM|K*Y;rxwXi$0X zOlrT0C#cm;!o7dv*rmU8)@Na7zUahTw&(nMq&1GS){E7qjD!}^jCY5OUbXzP#JD<0 z!-vFGfv~=wgq`du($muukopOG(;$64JmQK4zzrFAWYW5V_mR}s<7!MlE$5#f&*g}P zoGz5$VRCIRdAR56$JA7y`{^SJbdW?+{q*MRP}#$h51)_d#rIVjxph=ro-;*YU@1%P ze2q&(FUU;?uhW2MP5wDGDE#QRI@=>A^!*Mo@PY|sP=6L|8iOElzKl*kf33?o;7|

=^7w0VUeI;N@O9>$5mO#?Jx=bx+kAwpcgQC-!;h5$^P-@ zqff36$Ew|60*u-j_x0fFRm0DIH)Of`ez`wUq3uSt65`m+`j@c811&QGc#` zZ9+Z4YjBy)9BqAsh%T7EVkkSCBm3PcX2gnBZ`zMm+KrIcVc)u%o=U)sJ$`JE;j{Jg z9UPW%dznezgqP(P}Y1@;+hYWrW-1wcQG!FHt2(PBE7Viw}tmx896% zhYi5nl41vIR?G!5`2$u8HyT3B`20>QVCLkOE(R#B)~;8t7i;@Gc2QZYEn6=(63k-K zMSB;5@9m5f`Y)`$xi48@ZOHClhggX1Y*}?}KUpuF>bMmw;ek^)M*cdU{}ta@>t{9_ zT=UEiz{5N-es$P(YIzVp`hhsN8IVa?jfXU|uwWzF<-??s*A7r{*~8|49lR_kM`UQw z9;QW@ZiGSZ>5~_v1p)2^@1ErRc%3`mcNAY0vWh zeY{v$MFOmAAzS)Q0i!C%0{|H&<^^jJgt|J<&K>J2*R6h6EV^NT^8q=sXC~8ebk|ZOFJ;t>&A3;S>Qg+v=rcFavsz@|S?a^H^yTyEw`cE0 zLc0T@9B-**gAahppNb}cbP^4~Oe8>u!F@Z8v(#$<6h;KRmArUp518BWHrbSQuKp}w z=qH)s1!!0k7$GX=C5p&EKs*?N3vF&DhL%3KR!N;}-2agIe*Z0P^nz??cg9!F@@?kPK6Q@)$Dh1bZ;DtQ!0%~DmN~Ir&O`wcLS#|Z|?y0`0(cPC@A*V!B6xZnJ674&% zA6T&OD+i54Vw3t+?8#I1^QyUr#*M}j*Uvqxl9XFc`t1Qnit_=rWxP>(UhpV%#Ct1C zCy0PK^@q{mm9rWsCLpex8t6mHj@b<1r+nM)tEtG0Wt)MELC=VxgwXYBOh6#eiu>-# z$xM2&K$eT|vh+%-w#VSblQXk=QNsuP24wlm5eLfMFO6la9UMZRT5N>gTH+BEaxWxf zzIfF=%3!{^^&ZH?FJhh|5qRW$ly9Qt=H^CO3lWA3EXDTFg2sxE2G8UR^ZFi$(Tv1^ z&tBJo3&2^p>6V!Rs?eC2YvnNW5MU~Ify78b?0i()P1+i6OnsWE2DZtD%0vp@c5*+G zuVM|o8)tiMIb99FAkDv2;YB&rHUz4g;=)4#r=3~5Uqqh}JXvpR zW5GD&@364o#~dy&SZ;lw>$rEF!M8Zhfud$V$w#@9F?&z6#`_8U=i@07a~B@_8ip@N z^a7-qU=i01V+!d5V_x8JiQEI?%+8v8jh^T%px*PJjz{o831Mv;#1LE@1VTS1iB;R! zkZJYmP??zYJgU!U{~POLqO0DDv0Yq<-`?s54^tx}xZ)~0^QuJN?Ty{j(j0;CzcsGl zU|+o8lgPoJWa@v9y#2iu3cUQzrU~&r_^HP*^A+C#(x&HoK^)`Vrhl!LktFw@Vx zX6nz{BZ1Az0co;dao=Cyh$&!-AkHzA0s^IVRg&e#yZzdzPA~br>#fRzuvm-9_)nrI z$S6)ni@{M=fd?ZLG3aB5Ww~%yA15G#M1VZiSAs0~a3Y@1>0@*EvMU!D0yKFuMWh^N<60XYKnSh2(bn_Lw{d`PEE!*`^xOHG^}Dy1 zP$`)eJ5pxaeS+*dP|hv-X*3pZaiH5{ZE>Ky*|dm6G({WlyTTu*2u%WXbelXl^zR7O z6bI1?Iy#irn>(~Ec}{4E!5AJ;vxy1m4*U7NxOC0;C() zf+w8#-jrrw`668E1tG?pVd^a5=i!+f3=d7baIb*^^rP8fIs~Q6fDs@Cj9T;#@~?wt z_A&%R0;L1;C9$3aAH+0D^F<%6=MyNYAebuy0zC7izmksTUPI?=4Au!UyI6DY&YI4iatj*-MM}{4Ne~a-90JGwwPW-Y77%Hyh6H zSWr^JytY#y&a-h}1q+S>AqAuoh_<&wR!U-upa@D#un??6VnTi|=Ze$5Va_*eA>uk~ zAWD~@@^cyd;1_9Y{~AKqoTWq0N=CZ#DN_rS>aJJF{8oDFbBzBeL#CJ{d0#Ll5MbV` z(~TIL7#|+C!U1HyrKJm?pG$HJ{mhY(RJ0r`v*gt`X!{D>nGtjQV*xC*ptH620v7V` zV&s54g7(_PryH+cg&lo&~bHTOMFnIXSjR6!P4}Sc?;fq&vh*AIDv8>bZqn8foy@aeN{|#et z?F_R@`?HWrR~d$aD%S?LA`Rn3Q0nD6)}dYQ{$PltZ|)0ZAd_l%I{tBi?&BNq8DZ?P zNIo%hIpsbv7 z*2+KGzng{cwxwh2<50?i9hP%)E(k|&2=OPF80VE&_cVc?o~Ra*?jyYa)NaNUcE^wm zYXrT$?W@_cSzk1L(&P214;M=V6fdaG#+GXdJsbyE9wy2TCx%0CZ{Nl=-^L03BnBe> zAJ`#=K=2^!t|X*gU{l`9(NSs#@!NXhQ*FtLuOIKzDlELI3hfCl4F&MZx`Y zY`LJIzyiQl5B(j1F!(4R#1nrzlW*cCh6QuS8vc$`Cu`@^n!-Xt1NFEyg6g3Sg3g%? zVuW8`lM|lzu{S670-3sGDW&|hyH>m0M$ShBJ$5ZP!1ZSEc9EBdyar_-@FsyUl{9d<|5X%UoHZ;02>WM7GkzI>kF zAR?`hndtOHVs3fRo|Z>2b+Axn2376&K9`k!>5?>(`LSGDJ%hOzCNkNfI|!F(%Es3A zHx;%^MDwj#lBC?Q~<8)y4L7Yt_eO20>QlEaF@e^ihpA>P%E&ZAVAp6TR8&hM4#z zN7Q}9Ow`mqPU5qAInopx1hD@RwlnOq4QZZFa&7-?b`}Xod zPKlkrZ)5VdwNRgy9H%k_(1j9*349X#?rhTdQ0n)8v)>7~F~-#5PywYkStP1$$f1F| zk(Jt!(lA55##@g97ACS*OgKM?UYjL`H0&OX_a5o?=0%P834HDHc>R1;At)H)5->!9 zy#%81Ar!vpmk zQ{%)OLd*r!G~XoIGf;Q-pW5h?t!h~R?wN*4L3r5Cr82{`7Qx_8{-migTJu3Y-{SX_@)vSc*hXaBRqLyxs#2RSC%e0SGBV27oklLJ@6vUUPym_VC6 z6MXcL1Ia7f&`<|6EE9C((tkM#W9cII(lfXx_i#z+3mCBQV`}yX1DB)q-*zYy;UO0b48_C&n9%|m# zXDobm>1}7UW`+-A1oua^r!3}-x-etBvA-_=9eL>-)ZPwsetgWvhC$x~Q(2?cU$iuy zwU#dQIK5cZnWA!Fe`ll6e8+56^6>*FPb+=0XrB7Pb}`%~XAywA!ubK*PWMCF%U(Ry z;5(J*34tTDnvxQ3MkOAw+9ZAH{^hO?!19uqH?J#5^}%m_8*_$Q2n}0zGv2?Z=nPXP z03AQbO1sIqc$=#+hq_(YYzQ2-&L*@`M^y@QD9%v!@#nG0tfi6%*|crcs?Vg99+Wr_jjXj)B88ug)3mF6=#dO7c-vj#N4;sr zillSZBu97{zJp&vSylDYyHZmm(KuBP9z6+c&|BZ%sI5e zM444vS1{82b=%)_4-Y-fXvBzei2gCV2qq{!T|NtP5||~1-7ocXzHT~6Em;W?EZeNp z&S_#J*$_|&)u&)0Gg?dJE2*48&ALyW_a;WIpQrA*k_52r2!#L2@9a$AM{g|2UZJS@ zp5Xwe&eFGb0z9%lcbAqCe~e8}eVJRzt?g!F!WbXeu_*U{z1D!)vzX)KTUo<1B{Qjb zaqS6I&B+4C(KV8frkzceB{I1_2)L(6o+vrWI~`0G*)RGEJ*b!dknSz)3ZEh={hCR- zcAjh58DBJ6?UFtGqFlxo8)Q#}xe)(hnd=aa6wF1Gn@eM4x!A$=a+nQuyg`MKeBqhx5UPc~9LW^CkQPKjrY zy9s8?mmWkI01o<;nH%+6{##0xmX@&wVgE*1k=RidM)N;G7Ixf<@ z&!S6@xG#EF8G;mkoxvy1UX@i|-Oum<%-RL<5}9mdEuG7fDGla@vaeaK z9&uVED3b>|+V`CahybV3h7hrxSQ%r@456drYIkG=*BN|H(EJw?_al&ldYj(LjIQ&U zsB~a(k8%6Y`+ZixXr^n*$_NNNrvL-T%$Fh(RqPFv*uF16-&sZ3UINI`V;+o@!-9NO4mXakq6^F#mq8z?1fv{JWV6 zc4vFtn)I)GBPV8l*1(GiHnoL43{{_6B)4U;s6O#eRi+BmEXQ8?9j=cxDgoFi z*HbsoAKUF9!_`v*hHMAsbPbK8baBVZ4I#(EUzr1re^=09O652uy#B?9Q6YHSN^C1W zewh)*4)@*riOlx_Dyj$x>7mQUukt@NL|+zP2r2-)kg@B~%2S^+1#3mSxA8(5v9I1N z<9Q#%l^=b(3$i5Zd}Y-yxN282FL5#8^{(3*QK80n_~W#CT6~3HQ!>^kQ|cq7x|eUf zybC!ce|bA}Jsb*w{fmx=>`)Q-OhTg-yi}4U`6iYRQjYgX`0k6C-Cb?34cgM8ZRsqF z@c`DBf`8gD>@dnuc3R!lEARb!=!;gU%sNS5_}bBXBJ5YlZ44XRTmgD;q~Wl_k}kS; z5glT--_L%s=6>s9MCN1RlqW>Hy|p!%eay9zZX4msL=5UN4yi;x@a6BF_`;^4g2^+M&$JMr3wr{A>=$KauFD64xKJs3`&(P%!E zslzd%cK?zFvLT@s&Hm@sWH0i(M9gPv;rsI1`qFpHswU9+~uWWBC=;W;GpbHnM%@;$#oseH~Q)H}AwgV3-1 z)iXiuoax@P;(bqoRsXg{`VE*z(WgD5W@_&{U`49BdxXFYaU>$8S<6!clvUS95giFd z1O&I~hFYgA8#We5ST+?qaF&9QZyi4I@7G=7WWncvYiV2=!Q?KyKW+2w7z;jwRoaj3 zu0Pf@IbiF8vW)N7AkI1GPlVl(T{7a*H&<_T{II)!I5({S@~zOPnU_BdlnH|&v=%8d zORSRr#gtTVsB5h~WabGzK8>3cK<3C3kvmT?VW%+d!ucY(#E;GX;;djGAe9&5J$J+n zFHQe8Wue?#53xx;ZAv8#hKF@;^weCrw93v0&G7yY4e~gO@fYHJGAUrJQaqKFo7yI?n zto`E%AF|YI$easedsyr0B76!GDQ_pJn913qxFEtSa6Z|894 zY08GDuMFmK@;4mM>TFv`d@y^J{wMbYy5Z3|cwfKK(_~F?LV(4slt~5P5ai2r`VNCZ zXkYXMbB31bErtx7Mz$3w^7M4_lnU@z6Gr7y%1`U1B1N%gN|V4ncOj~qbqv_qMxI@s zlDgfdwc@XvwyEKabT_U#X@Cl7bnO14S*f&?69)hKqrnf2rymFSnjyAHZVcK=}54Z|ioBZCpSCP=+<*bQt4J^+V9t` zbFFV=hJTAM8B8N1f!H6rO&3*7owDOWI`{`q><(mcf!Sahi6HEQrvtHJD zN$jRUc0c9J>^}^bS48%tdwdDrFS`>Ah&g%^xNFHu3D@t{^^FXZcbFL<9v&aA|6F1r zitcQ0Q&MMZTx&v8zP@$qy;7i`1k1PUGEdqsoTfcSOnQsW8q>{=6-_j*W{39Z?zCqu zNwOY_WfKj=`}l6Zw+~^t$%LAJ+if>ed?Eczx9dM1pNXN!{4$b&YP1bXQVM>U$e|BS zA&{&Lo#n<4-S9g1%|A)#4ecRlkN$25Q8JEf@uBp=Cw+i(^V4&Aei4?}a2(8{EVW%D?#(LfSw-5D<$YFu<>!Q=q?Mjr7>UWb4fV6s#?*&Ix6{&&9PbMEIvFuJj`{A$#&^&T^H6iO64d0-2kRc zJ7F)%Epc64#43Dgkq1dT@Dk<1bYEq`95wU!4v^fpYfMF0 zU}a)r!n0XD7kQ;PB9Zc-dX?Fqm+XeRW=yJ_bP-~G3kf>Cgs7Nj%pcu}nYh9SH5Wd= zx=~(H@zd1#8?H)RTwHyU?O#;*u8ib`%7NQec3 zM`4A-9yg*_&WE)a7rE4j`X!jPN0~v)9RX4OCSynyRz$#MHuAJaQ=DSi=i*?5`Fylh z=8(&E#i?RDs^O9vPVOpxCDv;o5a&9IB8g^Q(qd?zXLpscU|Pk??CK`)Nw{tBP#Q$? z3+t{#7snR7|64iH6wz++!Idj*1brwrayVE!X6XY}2}0H(&lXy=E1zp%MF5J5Ua=eH z=WC52?_)Jdxr<@&B1WgoU83vZ(gvc$pRS~JFH-7l`fn7U>P0H>ZdU$GvnjY~uK$zq zIe?X4I7bP#*N9~Z9<1kaeOHz{K=06^UG!0?lYZ5|@DxD_E1a{AbC8JHxyh`tv4*`B zsFU|Ha~xJFdG8JlChHtZztod&&=JZsJ{82djz96FBW*`3&zu7=TiwxPSY+`zgCP8W*@HY&L}O7<#~%ml1G! z(q`R>`AcoYsrBPmBws9?|2%hUybPT`_E1nD0BqDkHDmUc zlnTG(P30Q!c~F!T7Z*2feI9+aA6Aeuo#iGf^?l z_dZe$6U-!_TUL1BrIr!Qu$JQ70=<$3TD8kd!tl%O_xnYstF#Gwy$1)f^XBIH5P(Mx z?4ZSx()@mog^UOL!dp(kuqS8zD$J8U9o%`TZ_2%J$yo`A3yT5ZI>$XlxkvxnMhgXW zc<0Nw>-_2asN}=n>#^;R=8qS)@8)QGN;n}VPxW;@WOUC{F1DMVtz4Sm^PE@xL&1Fgpuk-;2*>oxR9DJE1+9q6FZL)&;DAUOBg2AYkpnG|8(a7 zS_&A?JYkgGP$Fc1=b5gQ35mRtW%60hI_OjHvRP1TUfB0qTg$K{%frPS))+$8M;f2G zq&MaDWWy$bjZxmxRj_yiUO^Y4kht<+HdWw~JepDui7d{9*p&1$mLSo+JnL=ewOoRz0Z( zK3#&X&QgHK|IH6MWUX&u-_2!AkS=rm9c5rm#@Vl>O~1o2>zXMvF6rGfyFO+dh`2v4 zJelxdsOS@2>}4#6hQuq*ztx5aGuZsh zoH41{>5gw`w&~s{r+~c_vxdDM$)(@-&v)~-hDI8pfz^A=l}%C8&6{|@ZLJ;?NZ^3W zQm=3nm9ogNMbb>NSL4~FQ#08QQKB2K|84dt_t{fQFqo0s2Bqe5KZic*RArzRlTxV# z0$ctLMkKc31t1fG_HQB)^;?V6GqwHhukv*z$PSy4DpO+!+@9vm_q+?tC{e?RA3?+~ zyjjQ(E-Xqg9kE(6HHg<^uHF$ zV2~FUQPQ4gvKNE0^PKq7=-z)3AP8jU{K}aYQ*|gW^rBG4$<5sJ{#Rcf|B?Vb*(#KU zs(gYsv{(N28+RbHgB#vgvAlk7HYQ1v*QnCo&dzQvKAf+1S@8qe)7<}@99VS_y;15i z*MeW%aJuT0jax@@)GFxgen|+-?^DBmFgBhS9`h-be}w@2x2^ddd9q6a#<+`+7*VWc zAf?-4mjQY?D^$c>dnQTsEE9QS@o!NCIg zs9hBX6o#cXBI*VzV`_G(;H4*QCj)ByMUorkgX2~pD$xuW3;nIeft=ikJkfVhLv-@s zVhfGF>lnsd>%M%tyF}XzkJDVAeH z9__CTYK2~?{)`&=%V9xX0Tq;Iv*B!0(y8&{uqGc=7|8nFoi>ZiNLB1%!N#OERCiC@ zM6oj#dTj1=w6&}CmN#5})Cmw2A$sn+Q86;yFvqyHEIl8sp!sI3fA~L#4Q7$G;Eyh6 zX&b9S#6JEZlrOAzYC+`1NxF8tu)lD;vRo7~-!`BM7Gsh~pz}jN>CN|^@i26%i8xLD zs&ii%c)XPE>$o!C9;+p?uq*YS&jKgCjzv5C@{-@oYtln&=;zP=CD&gm4d)JfjR={v zhWTUZhq6zFlOdQ}+)Kr;g}O`7DY?7{?86`Fve{EgrDj*X>eo!D8UUZg&cBb`Y4jYDJ=hO@4w+%>kTo1z&7XFlUjZ=GF>JKV`7vb_ z3A{KjW-IJQhD$)T*3UwNFNY~&F0)2)E5H7wSy&1#XIQ1|`F4|+|2!M>$vp=L-p19M z0p>KnUnfh1fV-XR>FhuhocRs-Ph%Bmqt@Joo)ffL(t_IzjcZ&bZ{$5*O7oifad9}& z8;qeqt(%7ZBm9ZPa@{Ds$dkQTX*5AC#L2F%tYl@(xyy>2b)E>ZWU8B~CdmQ!R@|Sz zyNdJ#u&aYLo!>fl)biYaMcO{3g55T2@RKye(M<=1dkgpoXY53#9_sDezk>l5++l%5 zjVIks4ZFX|(8rwh_4SCAUW%*XlffMxAbO9J(;$P(K*~Wd2(1EUbgAbwlSSni#o2De zINo;blv;VuV&43k+5-edQ>Y2SYk$C&#U_m#PX1 zIR11g7Y9FkOZaUmfGl1^bVZ2IQf_wgZ+HQxMc~U7pec(WG&Y1RwutX2DAFh z)3pqcrR2^nwsJR~&kbG-oolt0;5@CQHXllp;pdCBZhH9U^u$5rUnTCVI`P=!wAkrDuLKT>sn>+o>XRYXqQ_Vtr&FFA~|E25YPA*!) z@9xRq*2LXtEGsZgiyZinZJ7%$z?xHW3&<&^US^>M(bnm8uD3_gAislx0pJVKO6nAUrZ<@sM!ZITD(y3H=Wkp*m56qGcaa_%kl zmNc~^)>X_b85UjqJnRNryGLcAZssa;*v& zJ^y@k>i}<RSAK#BG=>YC+nuU7)~@9GHXJweU&`$L?Bzh8(o3Kv zJjH!^KxXJ!Ne#4z%@-t=x=MHvUv0M20F$|?jj3Wakz!(HziULI%67R_x`n*W>%pAM zeuz>yP4^P;O*A;VikbBP%nTIT)GsTW9#3CgOq(@=o*4c5uC+*0SY!rs0yr;Y6985s zphIdoYPNy!Q&^#Ct>D5-a$q}TrA`UfoLhvz*Fn*!+EIECn6qWIfB>@TaeJT?Q3Rnx z+LLg-^BwV*{F}o50)Ny9S~8jcikew1t=Yxi=UscwPfa)d$9xJou8hsD2#J@`>w4&4 zqO6iP3KAT~S<`TNP~pUg zMyRc&6e6k^2Hjb4fjSrQL*p{sH)R@YQmb5@CtnaNVkQDFSAsmet2@_LSBEoinoIiN zawwo#NdBf74tZe$ZBE~u&}S2&jtwV^_**qg>3ZG!GSF`vm&aKp{%gl8*7IImYnahq zy$5Cj?5zd@)bdL9X|s0*&);)eZ_AIlcJ$W*Ax4ar>7Ai{fq{YC#M_A=(CC@ov1p0- zk|jwO`Zp{zjRX)^cM2KzW_tq;zvPv^+v@TP>GrQbpBm~;1VbPs6 zu}0V1!#?QvM7gb*A9-7<d1LyHmqa{Z`RvxvdU^`!4=I zXXVG~fQ8QfLA^d@2*%^w^{}l64{%9Z3A!OZ6!hs);hj&})n!SG-|$t7`TcN#`GNMa ziE^g8AUv5NQp78RFIJ3xW0nbwZYwznJrakY^f0u?iyj95_u&yju;o&{?lj4xdwo)* zuvU2&I*3oocI6DEfR90 z@3qGn?fFg=IyE@pQtva@ukjI6-y+Dt{8>t5#uiG#Pr`%I{WNA_{h)&1$Tg-X!5(F7 zRm*a(r<{d{w%}b+!Lv^8z0#gkTU@*$9szA~bBCfx9~tvYcr7W2MXu{7e%GKuI@5=h zRrS=9IK;5(AEkdE{+p%L4`dOY{X>oGuQ=27w`YRMifwIevn)ownng-(E^p9+F#}Kc z*GEXKtK!MC1=`yQIJ~2TEw`-J>@1V}ZFM;L3?RT@O#4A_ru~6Px7)GvLH3ID)%jjt z07%Bf8QnQ_X{9_tzAH(5BBKki{2TX`;*;l(*LtkssqdJ!@CWQ~@qeFn>dwcXUSMx% zz2`awQg%YTb-jkE6W7aKoZFmyIx6o2jNf9e>%}QsI@I4Z(oDh!mGLmw-2rZmVsi{i zeN8*rSe7X)%L|N#_?yK7SD25n_?pr?KPY<>Wx&8YQMb+Z1*J>h)ZaYEJcT)}gN2Tc z&fVp^`&+%uR?^`D31~Yrvtj(bi{2wKYS-BlM8hsM(DrRD&1vwq9xX-at%7VR$1qVL z)Ar%Xjyh%u^VRil%s2-fvG!?=aSr52qa0SNvsbT6KbfzjOzr1BjGz#k|4zg&wb>=q zD|LOPij__b;YlqvIz9gv+1KFCxw>pN-QZZz^d<>ew}a}5YSQitlH*;c7R03u2d(`+ zX@XFmTNSCP9Hu)@-I`BwZF^xpC)hyNy2Nj_m9d#|sroDA(dbn0GZzWR7?0Dg*u5%a z()5##OzxeW9BG9#jXM&T1TRuO$^Rlhm~$94DnUObfB|mCb*c5Ew|2Y2mQ3 zx@!35;5dQbpzIk*>cy$(ly^3bQN5E{weu64_*F|ajKAm?MR7lIx158!y~3Tk4f{j) zLg?BD`Z={ZUbQZ8xz$~~%|=&WVdz8|K|6xs;f+<=e~3~MyX_PVw2x;yW>?lLw$x(DI` zyKDRX*w{juqU)__g4HSI!*thn_fhu62OJ57QoDYkP#~pbFD_5GCP3iy!2`W_s_X)$ zIs7bKTs1R6M5IaLZi`O_b2TKxK;b4G)58Z3j~-{;?>c<58dqUGu>|e zXXOXV%VRXF8S!Z!+co)|InWi3M5G1JJrb_%bxeD_dg%*3R}b^-^hrG)1)Qg8)Q27VQg3u?{+Kf2 zOOjwb&$`D^)sse+YJ1k~wD*zoo^>!_6yK3obn*MaVhw~B*xqYrza)b~UtkXKJILwO zQD+m=0o!j?m|i&$lBP%Kn_t7D+YC)3KEla(q^m1JFi8-5UvB0T=NdK`=czXrN&mn7 zVP(xcqH6r{GeQ&pe$ChV`ZN{E)0GrSNy(J$<|zQ*EGig0`lrfaLN`?AtjKv=YISB` z^2Bs)Wo6}MQ)tOnoKU>Q!WqwH`a6rN9^<9ALb7`4tBwviUl4g)zL6QC8aGCLg_^f| zb8m)s22zr(zN@^m_hBUJu3j>!-jV^I!P1@X;1A3a=+r~=fakM6UU8SxP{j`RH|^w+ z1MI(#C~dg7nvR2Bg);eY84=yj;#a~TZ-ttO+jo!~zsr00@!AjCh&%7Wdr9X=NY&Nl z_?o|6C+e4_oR3jY9?|pPzDmiIUehvBEVby9|EK;P!3b5dQCe^L<`p`{7N`-+&Q&Js{3K_zk6Cr81B026-UKu#ECOI?DMsZos=zq{{ zQ|1(8A{uEbcIo)cGx%s``TKpp$s{X3@h3kYY!T)j@I_2X7V0gUk2g@xm34fmw=dH4 z=`4yE^mIKR>Q{bdxpH``7{5$!@=;{UtLZ!qHIAyXfJ7HQ$<;ZO>v?&59CMYP0r=x3 zFozGC*T?R`yT8N3PnVsPt2gZJVGV_&DI-O*>hn$Fn@wuss{XwD!WY*}$D8!?Blr;ZTOj42Xw z3~b?=q|o+f%{nCWUuW9ca}O}?E#GZhIM2~((CAb~-O@3x>VZ{zOloh?O)_Vc%8#1!b68yA=yo#bB~ z<<`lTYFdoYOV&94{Lah*FZUCb|A)||Hl=6l68CT##O~n9bG2N1p_{Yv&(+* zc?oZa_7gEi(R(L;*6jv5dBP6tMn+>lJj$z3_l=km+;Ton*xe)ZD5?J@B}&uiloD?* zzF-{cF{@iy=~8b|t31CXi-9K!p4lf=1> zEe<|l?)_40T(%x3N?v8QHLMwksqW5BRpU={HaGm?rl_0CmmWW9+I@78fI7c)kl+*I zWn>g>mvCO>=AAH>a?BR)?6l-h>rRj&uR^`Mcf0eUl=P64-BKCIuBk+zIO0{_=^92! zUitgTRFsI>N?>(rWp%M-?}PN8%?rn<`?2BPkvZPuiyH^KNK*5XMwDBy3t~6tV--rl zV@kq_rDv6x)9mMnxQKLOmtVT*Bl^eUjut>?p) zI&%GWn*HqIpD{|}_#EM%e%?HF#TiXRRuJBKKelxt(7k3?pK`@5uGtR{!JgtYs2fk> z@!{KmZNV?}+|pvDYtf&E6GEF@oL!7knAEKr?Af>OON@x0bg;F!_!eZV$7o1YxEY@M z$Df5uA7%H3hW}J!0@K3P2(2$1Lk9Kkvp5U=AyifO?5;laCdAA1JT^7nvIW}@1txY8@o;|`>@*nDj3Q`PSinik zzEyDBE``U5C2cpPW8-e9Pvpd(J$-GgrC&AqrcYez|IFlj_f)cXv{jG6G0{~?dbTl` zyg%*dV>joD7kGuccw#uXMw40zfM55NG!={G&4X+$1jGTz_5D}cnkpoO^n~D_NbadB zJ_G*KlMII>bL9Bp3C|c^@v(nH2Zh`ON03_5Ffc^Oh_)QOf z0{~7Y1i%4bA%A|C3H|$5D3FQszxRJWNOWBB^6z=h-jMZrf>cHo559m?$1lA$ANn2J z%h(n66sRT!F-Yn3wu;4?)PiQFKL;qmT=)PV$?R~1%?22?eHej8B0DE zUpJ#vY1tlQY4>Hg-`>l2TF<{XEqQn&Nm9tmYBSCE{_4loKVKzhhhD2-VIWXn05(ej zpCuckP{5MsyTM+2Ov%_yA=u2BkHrIk!MZx>Mq8*&9s?9Sw3b2uV$sp}v-OoS%fSxf zeNle1+eanFe$TN6R&%&8EwqB=#BiwJIKOvblKx)TwLZawB;w0hZU#5;1d{@vmaid< zLNMaM7P(AanDm$rhf#wIxkGe3{q?S%;7>G5hH)wR={u28UiO}S$r*aTTYF01pesYP zq(myj?l6r-dPR(+Z@M^KDITa-rp8x!zlM+E+rGwXIFBn2BQ6u)qwHz+JO=$+ zXow+TcM?gV1gTw4kpW)Mm6j=g3ia=-{L<0MC?G5QD3|}OJ1W%T*XR2u0qGfwWGqn* zU1Y3q=a`c3+!Tb@w|+8PyQqvDw{pkz_d(nE-OOG!mk(w3T43`T z(VY8^yN1 z1@>Ge{@;BceSiCSn{HyEgH_g0B-sqfg;vvt9GzT0a+{I^)ez%hA>> zF_TfE49niwA#G-2*g{KHt~x52$g^ zdCqg*&-?v;p7Ug8`R0@QL*A~=D==-;aqUBDhZ}j+pO}8EM^m-+RW#cXIWGr@^ly_ngXB;~pzdy-ewm`jx18 z|17%UozmtH-K{)K*P5gG(Y1Av1s4XF>rcsR-R)Rsg@^!mK7ZH3FBOd7`=^i0-%fxZ zTsL}q&@ds~sLZwTvcZ{K!y*gIS3dVv1`5_kUAAcntj^eY?J$l14=u6}lo$B!r|awHilGC&fRN-LdLAj-z+E|0yWD z*~q7gdLoG6;2hmP+kc!H^((8yL+Io|O^K$Dk|Wl`Jo@&UTodC`D7*omAde1}oL22! zyD?}m^2vud5n?<1!QBGUhKh{L%^r}Dk}Swzs!yRSAGPfts=U~)Jw0>u(reH1hl?R> z2Ni=HG9JR;aQ--nqpV@>@45<&zIHJPVZpaYLG;IMskR7W^kB%HTMfu z{5@6Z`hzmnnW>*p&o{^8`RD3~f*yMf&_ziE8H<-zwPUlycsfcw^y0A za~9)1j^Bs*9fg#!sG4W6OEhq6^j7B)Ei&ivj9cV(eo-;8TTO`h-rOfhM)-}lZ7*nh zrWX9-Bk-w@BK%~K>81ClskAfxlbo+rUM@^U4PW9VxIu61YTv9?5yO@o*LUm;)ISQ; z($g1)O0b9scz&>}PmUY0nD=RlHm1~tO$5oE1k~SWEn93307k4?c_fBuEqg5fG_N#y zvoTkfdWFEEOyKD4fwRrk0gJbu$zA8q=0<*9*!m7l&j$*}UAnh)?1PoF{ZH@-z!$_y z&ot*XTBC=_U!Ptz@;`KZ^N-e2h2Nxc(ArbdXkd@l%-e`JH`RkTi;{Ikrv|TRGmnUQ z+Kf1%g!1K%5k@c-ecGRZ_mroYSH@(*s+e#`Ef_PwTbd&dd|;7J#;bx_$H|2X+-m(g#1)sfWT`W#9FmUYbjsOy{2yu1gkZ*xeIw{xBN0UdISS z7q@ilyxCgIPCUJ#8@x$@|HYk-We8kGyRQEJV)uL4X!u-{acAf=fw+8TID^AK8X+c) zVQQ8g-rpQ>*b^1L4y!GrJW)-uyW0II7ZcAOsgN!8dA{bve}Kx9zGFFNH|hFg5dII;#rodFRglPLs_GOk1B|?kyXu+ z;uGSS|08^JKtjIp=Qmqy#rBr1VsSn(O9jQ6cq<(z18hJv)#OHBNPk!YBaWzZ znqKfM;7QG9Mag1tBd4=($F7Z4jf{=)66O4NkQ(@|Uq=PxZD2=gg4QxGAK!ioyO)Eu z(a;(?$lws$^(3^|2d=2;xR5n+iN%A2aPz*9zOdHNyAP?QqW&-Zu!)CfF2TYsBKxck z?av1yc#M2Xe8kH09{^BAP47jH_-UiRls3%la@lm^ugD{@yC8+VaQM_hrz3|h2Ve&)(apzq#^VjE|ZApc= znnuL$KM~6y876su$LX%;b)$FslGX!$)7iFtw>?gkNKYPgIPv@J_ExS(Li&0YF`*Vz z3SI5Qf>T&$UywQjA?WL9$sqU3A9k}_EXGD>QeVUqVq1Lx(tNKl`RLP+-BWr7~WRgH>~o-_O4d_ z_9cP0;ld(i_lhlrk<+5dPGyFxr@=)MxX4)&I(7IokL2`c!&IIKw$sLDTO%t^05gpQ zfzYO*(!n5*pCWbz@Ssh()eHn{8&$Ph6}k zsb23l|MaoET%r%t%~0}s`^UAg(ijDUN{BHF|B^&piqysn*>-{P2S z(6u~=*K5UT7ZX37UlKZ7@i!V8x}?TG7t8su0g3cgq3-1%lhjWyX6m7HN>^jUtvD7Q z>uLHT+M=4+$avun<@$>c;(G#+c)_)MGrv^vkv;pNfx)*9{-P&SAHy~W-IW0Xc$=+= zM?i2&fDpH?(>=iWoVZ~;Uy*{cMtskbBj&acL**eolbc^k!WM7ZH3UMW+qZAmh_wm7 zFa0koBPb_ZX;t!lYi&cvATlGhX7YfkL<{ny93*F}YDZB)2$SRT0d0JWx{Bc3MaBF2 z!sMhR{|-Li9QfgtA-ABD&%h&hV@@$|x{mPdJ6RsMFjy>zY)6y#D_Bq!9#Lc+HmaP6 zNW6e<%0PK!PuQ#UZLM0LSy-G6VO7$^Zf4Ku%rFh(Y+rN9{M#`RI8@(ksw~xspTea= z40#ICu$}NGyz;D`53X=orsG|3j$D6n>Or2WF-T_+*jC{Tx+bgBl7stx!EO=z`SzRv znm)nXp~aR$cd_7O!)=I3(zsAl&LoDTRbb8O$QMbG^fIz3(qN3g0(Wo! zz5PhcyG1#zx}B5kKle6D=pMeE*E5DoyAIIzzUI^>#(Mow>^)AZ^&!CgLclC#SmKI2S>Zuify+$|j$JgF2?yKCHFPbvP z?(`R_RR2-iq+5Ks_TNeXY=#|Z-lm>3`X|O2D<@sK#)e6ewYZ-IXR!5**VaT7jYP+j z)Arq3&);k2*BIO(cPsUryj;4OcDFwK>{TfKoW8>Pk6FC#kAVSy$w48@vjFvt)xBF6 zU#fk0QV@NzXm7FaQD$RTc^vxMlhp6yPNbc|cl8jh9;f|KZ7d<|1EmBgyebOc7XC7- z8T9zy?UI&)`$6eoaAifKa&HbJ15c+?72LnDCPGQKvz1N{)rh1qeSRq~l45hx+Lp1P ziV5Xj15JEjPuqu_)ram9QL4T}aGRN{vWmriYwxR$>PVD%P_k_2?idD;c;>*G?H~Vlul{#ZrBq|-c{{{rFO}}^@x0+qR)LISRI~lg z$3qnNWrFerq}E5WS;vt&6UW{)i>RXlsxtXIBuV7;TPxar5Hb41XSNZ1wT91_jtymh zA^pv$aKenl39s>s>T(=xTa1Jj;t9&W{jvUpG}20}Mh)v6y7|?N%s<={F>RcC2AuV6 z^4j;7p$Gm6(Ouy-9b*IvJZyOBB_0C)B#7~MUM9~!l2xcb6ZuZ4KNY_!87t5~ zXY)Y}NMscm$_Sc{`4ELFKXG!}?=rY~YZQP8aWVC{14i?0hKrXOd1}BIgx@Yv$ zQ(%ip+Jf`ilOf-5sPo!B`RZI4-iaXZJOs9Nx#Ys%4z}gs5`Vp-)yZ^(pxHI*+M0sE zt5@gmYD5uz`QsUax6~@fB}6snf>L|RVT=dG=B1}belH)XwsJ+Tfxqe<$EY4rx9{&f2bVroZ~CH~EV{1Y+{O(;%yG>2OSpySe%M zgQDL!OYUApV7P&{qSx$6DQ!7*-oHLi732iZm(;H&_(*)w)w6r|oi#VKU^N?~zW4Xj zu~NyKKNVo>1D4e5j;8$>z;1mW@_Rz6@Q+Ns^zAQrKWT*bY|;YV!cT*iv^08Dh_1?O zn(h%j{!Z%0^>oLQ(PMqx@atj^KVNeaHvhQ5#TV{qWiOzK`NefsbJ0hp;m|(#<&3yp zi_-;76Po%1H}WU5>>_$x^9OO8LywD#b~L`0d)L%ifPbjGVc;48y{~9HoNsP#DgJ-3 zo)3{ot@gvUNURl9;CPr`-4D@~ea(tyrLfMFD;;XQaD?i=1l=nNbm@DkR!--LXspPe zpeEJgHg~$WOXf9JB!*GzSM>5mKn83vxjU!CvqyC$!jRg#FRL5%fNsEY7}M#b{qjSK%SH=pT57?b#+&Zu zz>3d94{r|SNWVxDSf^Dc*9!iJQ@Iel5o*+^nP-h8DchM5`cYF|iqNB` znevwfHlKgy;OuqqA5XTsAKk(guM^ghrXM%VSaP6YS^+Rlq!HQ<1HmRkazTx-M=Y&X zM!!D#Yy;m78*m_Q&s5u!i{($ut{DJ@xBWTrW(J3V_2%IcabyGb#cKAv`+rHY!2nNQ z4yDPe$l>00eWJcd9oWFNaB-r=mz0aB|)Q}r95LVWS$2Xn&4TlYnAF|p5Une}veZl;cq^k{%^SRpL0 zBU^OQp*Z;}1_>j- zI7_vNqu<|e%M-m-pVxE8p1K^9>b(%LK|mD>osr?sq` zOTWxr12?V}Sv@7DTYqkMJNKl+IpC%E<^3fc2~Dh@CSXT$Asfb-jT`8Y^m+fkL~PWc z07-CBZnY(v-5OxUfDjMI96)tV|M{SkdV_noU^*(#P@0;00BEgrLZcC;6T&D$OGkHF--+4Y2gz zdkHZ@=^ziS=w^VsZOXsT2M~!{*1*Ar7?ln*j*ORErsL%TK%j+JW8K4ZKn53Sh#0RV zt8q@XKgl$I?(g6+LFipg5(D1wsq(r!>vWopO3U5I+P@7CtRWmyH>9Rie|_9{`}Ot3 z=kVmgb>sDE5&wazWF|@4a9huIEs1vO+*WmEz^AL~@STX4?%ihVZN@&P?}5?4kGLF& zCbznsbkvd~9hcCKKG+n2kyc?kWs%mHPK;R~*?OEMPtb7R)+9R!Cjj9akqu80#5I(o z`BrM-BHR7P#Kh%WWfXap@q(MT8qLzXqJdoQEm!&Q*5DUWD~lvrVqneW*}G*RWR~zj z=PzIJL@1&!2mO#?0 zDrlb6!+>FrXWlh7Pka(SVzMm>`aS66^K8$H21ia{C*b;-e3PBgnTpD?Ei{`sG&)od zZlLFumcm06c~kzk>l)ojZ*UJgW>%TImr2qc+G8sB6(CMB?{fI-k76n4ve;Fux8?id zPV(@ROq2I7O5TEY-|HP9V!O7fvyS8m->u~zA7=8Zmp;eq<8M*kiZG{U-xLb%A3Et! z?|lf>J1fm;fwL>NFZ->MJgxTNfAuvUpNf+Oro4mVBwTkvd#5LI;)jZldn{*1dz#z6S{4jsfpaJ`a#kXh6{H_67X`v4Hty3;l z=k^;Px$&*_M%Po9aorF`jqpI*uH~mVywhon5}vQp@c%&UQHSIyNTMz)<`i$!IPWQl z5!eM#_uS$O@y2k7oYQX3)pL8_Jhz?)tgg*$sK^R_Z&y4A^7v zqC?1UW`Je?mg}pEEn?Q%KH3Dg;zkm*o#fMs+@tZxTkyX{ej<(#qYLG35;MPnF~8~& z)E6_*w~S*=3of>zSmDwJ04W6(h8h0If=olED zssgnUASwad__PXx zGz!1T)i0jNKMjTx(Hoa!l5rg0VN!lpr+2; zP4FxO{ouP&zHp<;xxFXbNnb1huc=4c?q@hvFLC27KwaHKT(jH{VfQRICwBe$-dc$m z<#kTSpMSx^HA5K1QFSiTBI&E&m2@|6YJ67-auaXIDSoyV(R#*DQF#qX;~$onq=ybU znl>$9IlN3TK<-b{G@aPt6x40*Oi8udT(4w)7AlPq-_uqV9BOrxJ@}2Dc+;ACch()N z(sAQSw4*u?>^&sZiiLwd`eJK#{}}Jy8n)=&!xFSkFB|6Rz(J$Cfo5ggr*Ol_ zE-vbxKsKOf2YrNL{_fF5QdNIs5aeM3e5MdM5U)VO_pReU`upE|Gj=x6B-jL{i>ed- zdEV|Urdupu$f7|1gr#`L&TT>@Af6qz>kkoYg*?_-mxcZvr0dS8P>MTI^2Lf(C|M!3 zK?fS&o|M8pq`Gp9cfp5O<;o7$mh#w0t$YR9E_USQ9PTn9Ip3!Rt+9O26F3*L8jq!K z?hYhaStmR5o-ho$08=mPkMy_86>x{do5$PCz_)20jtt(*;?%Epb(CF`eu?sw?E8Nt z(3&)c5-83M_QGXVXEXZIw+vo$)pFjQ^QrZl&#rM0&M!a_%rjqmACT_6!yUUXQ3Ji~ z9Du&<;9fai-bjpZ@K7LxQZjy32cqveApV#fwmV$`d~KYx6%H)56$1u|v8B4+o=OF3 zg1edlw$!a7^`?2yz5f!%o9;9&l+-(ldo~RT&sx?S@^G@kqu9=Wu+u^CA zmWj5X2ZexP8alD;q0A_wj@ve2=)#+J%HL}8It$7KEMGspg)5(d8Z_kY5ZmNMw74kC zOkDKPp5xR#UWL$Flv@8stHd07+{&R*P7)-WN(qMEfJ0gC4q10lwgzm&JQ|Jla8J>( z7~to(l$#s!t6F!>5+=npo{ekZJ%j+wxbwR%=+22>v-5Ko8+z3LV)PV#%XHjh`YM%Y ziMH4D*I5c$>?HNEI)(QV)Ze{=S!Nb+S;BGnL)P-0xJByC(e_GW+{YJt7;knN z7?us)nR7H@g(Ac~=WN>O!NGsMN;M_|#lI|}ncX-yU^}P<9i^01 z2W~vHKBqMWRj=sJ7$kiJ$PR?+^eFXrJ1lgwH@dHFEX5m7-af2E~FLr zeuedL7;4P2JxoQ{n!eO?of&(7kx3(-v_&2(&GmowWGvv^(hodXEwZykNKatG_h{@%XJ z<(GfXS~l8H^sV#dzsNdbTJJBqTX^5>U^==HnEG>v$`>s>^ZO1DFfj@#874+^1rX$8 z64Rw{;qB7dE=Q%*cLwhAh+WT=kc>F?4mK>KBQ!2$JU^Oyt2AfIzkK?v$cNO|DEaW5 z&g0C$3}x%d&39FNoF+AR*8k3@5?gO?$-UR%xi-?&8J0NtGOBCp=nirFVsk(|ImrX> zFH}jvO83b$pK>=%o@+W?ZD~u3a|G5v4LjniCkp`q0nXIj8s*P!8_SnF2k{>AxK|27 zZ}@@oTL~M;(XE%sO_Jb*q%wN);j!x*q}MS@Cw9+>OP%a^yJY-kG_10ZHsIwx!h`oE zsfRwFw(nLMI8{Ji-hQ5(=Gm!M2oaI11*7X|EQ9E7$Q>KAV+as$9PwNLXJI`iKi)-* zNo`x=okX#p{gv!`uwzp2u;i65pO2=^_;X01#@rCj@i`T~6Z#8`J)*lLU#}pWpecPc z*NoVht2~4=6bKAAOdSE4$w?`e>mO&{&k!vFnj9bnxBQ#6f8yO zYTl_deLkrWa^%AMp<(Ugez#;0n8V+*)YZDzL~fq^U`xw7hkxWgTbBoy`2AcDHaKYr|)WTQ=svS{=g!SL002PlosRQ}^$eV+4x zwQ}{J_wHlxMe1=KrCE^HIOBIqEvj|GxeE)mWXVi<+7_m(4F*9$$K_TtKGjT(!qeiM zEtS34|H9Piqe$->f-7hS#%-DX-sCl>lr1-0GS_aGl+C-7XH^hnd(PM~4_rRQIRKW9 z^VUG}0;Z<9i(&`a>edba)_3K5HM3tC*EHqGeqRI<_jb7Ty$SxymD$S?8fwBa?P{J zgu^&5C!vS$=v+JQ+bVC}$j5ab*V^JtJY9o)>l`BY81hl3!X1T4b|Bm+d`c(oDF-}& zQT#-?OO8wkR2oqBHyt$4jqqeFK;1iGfhM4+lB4pCi;|DNEfE^4C6yS~<$YIX-tI^0 z4#e==L!UZ(f1CgMid#7|9t{0i6{ik0AA53JTma^ZtN*Bgzg2>*Uq8Bm2vxSL8`RuH zf~I9LW~`yV-M@?$tYUX|=~8A@P}}P{$Dhi7MgIf*(@6^o@x=^p=AT45ug;;45t2&B zsZVBQLOkK)u9E(Ug&AQFdR)nd<b0D4z(*3b}9w&<07mcZTa zUH5gTqtj(~ndI3f9xbgP{r(wtvEL}5*w8h@{mD}fWH~5_M?J2Bo1RNf2Xp@?EOcq3 zZU<+};=1ODQHEs*3_%o_!Z?U^%CO7>l1Db{F z)(AmcrB5bf2PL#_k>{G5?X6{OG>ob)Ryj>RC^WQqV`E}UD63x`)v4KY1hWiT8k8UJ|$W{5InK(%XgR}R)TN6on4*0G58nv`e2~$59atyxMzr~rf#bS6E7X5To zs^Q+W-I8mc#WHN~Ub4I4@h_N}U{?N%jtyi6T8uGOKxb2RO6BEnJsTz3l(=AmD>S>v ztE_49z$^YT73*6BJ>J3T);wPMIP@ck{~GC3(Tk`P3i=m-pdg)d?o~(gtS-w33$G81 z4sojXG|fO)x=cg&_h0qTxr!E!j= zNK4>g)5fypa;qhScL6u-nSKQH8m*teey@OSDj^4A5$yxVb);2j*~K0S7L}KCRL{GJ z9%*}UTfDIbim@-+{_#@B@IP1>in`rJ@Mo-*ZW4cU+TW$0Tc;nL#@#*Kj$?0^Ov{;n zH&Zg)yv?i2X8hCElxGaGdYwN2pk6BC%s{aP2Vo6iWM{?^?X{OGVXxmE>26IUbPSc{ z6ZOR&4d209^bZr=9e#0SZDwjN*Q}k>8#{Ewt?XX}CpKIsqS0nx660$El{HTC&<6eJ zlH(_G(p;D&)Z8s;3pRiK(`zHgq)am}f_%aHv(U};Pscscv53JMn7R);xt*0=`~mT% z4(<*fC(Lpp&U|<~Jp~Vz_<6Mytmg}|pZ@x9ITMl^4pR5Z+09e;euDI2T>&d_T9WxO zT+UH9CMJ9&YRXnDlq)c?A;c8JH!r`@;%3ln2xD+^eDH4Exkj4?Qj;nWl$8_l=*7ml z+gR7`z}34*fb)71LBZdD>hc}?8p_whLrRY2_YOl2{}l2G{)3pSOQE!xc#&m`#%9TH zU=n!IDli-q30}(kNgyxRlngE`{yx@S1=&D>Z!<1#y)Ff3zT%8DKnu!{%RJ8LdEVsl zhk!~WQg1%mBFIrIWb~Q4feduL7yTFYy^kJ7B&Nv3t56+Ey7n{a&8`M)ppB? zsY>WPr~1RMyWs>dp60t;&4z7gg@FO21!7IM8g?L=La2&@6`lt2HtJJwlXV4?<)Mx0 zLl^zoPkd(1-v=;hIR)v6RU_$>oWN9%Kjnq`#G$vA)YA z`ot(J&xQ9kNS&3lre0LGYqn_St-1t5aQ24*1KTnaTVL+2q}D#w!&p{Fdl zDP#TYBR`q2I+=eb6eL<`1L%WPTF}(`?l!KvWt>My@kT`fEck+r^>v*D=Kny+J+_DP zxVQ6dcfKz{Px6g9`wH7%2BpJTc>lRwa{KrS&w$vJZ?y!x zK!v0$D2EH*f5)VPe~B*)R|$5z3pa15yoJ&{G(dtUrF}>2yEzZRmffu2mnde6I)WXTf?<_ z`AgNJqAP{-!65yQx&ZaX78bKC`9Y9H*jWm(B>k-L&(5c^oQ#T(W~iShJcoS`yqf;- zLU&9RPpK-hWyV+DEEGJid>Vr6>8!e{|7;t*_Apk(HB@xTYiFm8j}as2=qTcJvI%G0 zdGQ1~l}mpH&HUCx(*z-906SltI<_t1;2}jG4mTAdFgLoNsL#|;(n~IW_1MuYNfjQC zp8wjiU#kg=hpT|4y@>DUe^0?O{2O>^uO*YqznG8Jb5WuyG;GPHR?-GiYnGvL|NG~x zIWyMpVT@$cdJjY(4+mPh3BKs2+*NyLA(@-Nv2=CB7bHL{RS2hIf}5Eynbl@}*! z42r1TArnXL(Yyy4N1o5YwBA-rj{qUiHNc)-y>r(r`&l1<3X&0CR1{?DNTnx9rnO`w zMbPUXcyo^y6#Q88AvaV(^zpq{3)gJA7zI0$wc!u6Uyjv#0Af_?xi^c7XNXv&G@jmV zT1@tuT6rL}>T>+iOC|{y$4~k=96Ic(N_>tB?XMT%n>aF&-nXVQE}j)tfdhvxv!B4h zxVP>Ak~c`2s^MEwkJ7vZP46l8WrUo#2yMdaI9m2;HfaM~SnSR&+eE>`h%auXX4bS& zQLPu&r#7|1y1rZh?g{sX$>VGVUFh|!V64Z1zphC5yNq18VEPQJNqHop9c(%bQYMK|B_f_%+TuWelNK=mB7#g8R72~>t_agMz2aN9X; zW`NKZ^yJpbffYe5u~vzLSC1tL2}(KS+e%A$iQxq_g?B|+h7<;FJ~szL0;n$^(bnTGL0B1kKUf2ULU_N}m_EUPhWLQR!5hy*+ z{+6C;5zr}R3!1|p)M~Y2ssyz35WM{vp?`KhBmw0cr>ZU{O1wJ()EynqVkyg9POBwc z(_8v*X1{dA121mi`IX(YG%XQvlx#7jQD;MCjL4PE9Y}^s^eJ&Zbn0nvTghMp8~xF> z(Ek}(+pgNV-k;$#&v?q>(t{;x-2`kGF8RVH4!u& ze9MhTH2zktANfTLK!or{gh72%4y&9gg;ekHh&~fjffM}IyWt~k(z#j}4}%)kw^eP4 zj5vdazBSK!Q9eBX_;b6O-$I8kS6c84r6baZ*!8r!k?D~ZpplYta@FR~o0$QDfuC#+ zc?SJkFkz&3w}0?;lm@2O_Cy0%VEj}mUU-m!%n&)_8g<$jXt#M6&* z0UPzH^{v4fU(Uv0c)2$B>K)7nauacEn76=qTAi@c%y|HR8PRf694V!_dpo&o@*Nah z;bxlaTjAC1IQoNoqK{xsd6#6?TW_5o1AB<-q2i~to84pSnp-&3Amq!4Plxio9_O#z zXI<8&xNDoxjlmCFhV$!YqHIyMFQtL>d!3<6pMDGhHcAammJ0c0T)w=iCs5-r+;@wi ztn;X*qqt=ByWj1E_YJ#L?k}7|X zA+J`TZ}hl6)Q+n=vzq5)IzMJ%qI$d35IlZc8ArS^7Q6FC)drezv@`Q=WHB`mPvwf8 z*wOft=|RL!?%b%ZxORdcuR5Htg-7$Cx5>->fncB*=!bpoBl^Ril10gCA2+ zdv#;}`$@ND|C3J7=}X~8PxzhKRQ56h%Fn(2K_O9C47XrKU!}~*!G@4O-@sIZq*pIR zJ0wM19%ExCHm&7Ichs^W{Cd>ytTG&|p)ifR+}J^zXDYv3t6LJ_6U;jtyXpz7N6W}{ z2|6qJBlGXsd&1dY{d7YLx|nhP!vfX)=q&V9#cUoV#-e8135-YAMAz)@>1|RceM28* zMAW%gj^SdhpUJM}8|r9$1Q!Q*S&G843^V6f)mu~c*d6q~(DYKUCR2khEjqXv=qOuLi8lf&p; zNOi4bGW7L9CT+a(_2rJ$b>?yZFzSAV`R{ut&L3nqjhuvp4j&wH`$u~nxDQvG28&4^ zUR8N-<(BFkQl0AAShqy(bSYsH;73X1aFM167t}m-LUjHVZ*qAvY~VxSTXE7bE3`*} zlOLt&U&6E;8$gzgYrgc1Wp*!RKoAf(b?THL@Z6u{u3*i(v_ra=7Kg|0 zmcQ;mw`iusEnpvR^KRxGj`^tT!OoEy$%pAy*1)o{5lic1@di>%Obr1wvSdGS{Lw&L z!yW~oG+CQpDBlHj51T(C>HmK5Ul)id>QE}Q8gA-Iy(cHhH~^D4Hyge$(y`wP#J;Wk zf)!=m4<^Q+iIJ;V&R~eS5b~hAld;^9XD_lO%Dgr%8uqixliJMvJ)O^D)1rufg|M{w zizrNGVayWbo=y%18EtZYGjV-u5KBAZ6iyc6voG9=zs+#s`VReC$Zo_6JgX|*lFVXp z>GyH5ewN%6($B+v{_&r~qYQRynthhuB=T^stQ7e%FrHh6hSy%z0cG3)RJ=7@3cS7djo0*1sI0Jm!w1nx=XtSZ5!y5c6;5Ecy(B{t7e$fsD9tGTAKZ`To>1_mXmOA=|>ukuWi1EC{17;PhOm~>O?->JA~1XpY#1H2uQ{*0t0Rv63H zuhH^e;+_PwPAyw`Uh4M8&qHs?P8l7&O$Dw~=pF`9pEFr`i~f|AvwA>L3R8EW{@5ln zV0)ow4L%Z@(wKzg20lzDJF8Oj-;$c0?_e4(;s#EHCeNfOF~&rJa^(Ubx$H?oYh}GC zJ;=n0fxX2TDYK>QD|#tZspnypvqiiN1oSlVO`iK@ms#%}>#P*&{zTP0CD@ z?y&03eXgJsR1jc7N#r%XMf8%wDb1(FMx9@v+Tr;Yq+#ZKU8WL2T_%RO)Dm zcE(yv6yZ?{?y6MYAdz>%(u_q|=h6fF9Zlvo^ogx{HOCC`B%tuA!Ir}Mj=8&Py=ESO z*SC?jv3_S$Vgv_H?_0Kq(zq@=;_qYD!~XU8s^3*szX>O!gF(|_K_?=5T4-V${SE5i z5uL9#5ty@O176I-9tn3GK^Rm;C@NZTlfLJhi6d49yc1C? zWD8Dm++*TYY2v!?ZCX8sGuin_!Rp)!$d^HSupw@sG~WT1t5R>2-Xl>D7XKB|nuv&_ zr*QI6+X>SfoWUT>!BJIOFfuegV^9IFaUjYcT1)LzdgQq!TDk*g7oVkiVfnFF%$CQM za)1c4QRhug3^(Q_(oumKaAzwN75*!b<+9nxK)*LfQqO{uD7xgcR~=iUqv00}fbEopj_;QS&EVn+ zR!d->>F9Ufv8G>56-gl14Tv|M>koSf*fUZYru!yHG!h9@lckH6TR#Lehw6hgFSFY* zCgIkX%H4f3Y>@oCrM)A>4AkQXv5FQ+4!gJL*$2DHIu3n{E{l%-3CY^m?DiU_h z!BwcR#h%UuB|R=F{uuiJ!x!!aNU6L;v|!0D9ql)CyF%TmYT6K3W@pCxY1O2%;1y<# z$pVG#pANX?>>6{fTkU3015)O0-wzc5Z;3M0!&+0Dr8iw5a$wK9)o5KrjdA01Lhm1sHv~Vvu{EpRI$CGe7=A#bKW6 z!{BL$Uda5AH3qFiH3~tZ{}NgUk{@49Vmf4c9dVsX?6!fdQG@5i_eQLufKz=fca56< z{wKb>>IhR5GIQFq%j-MV-of%G zU0!VxkZ%IMwy@a<0Nb>HTHNyOr}dK&mrV_FfACpSR0JPbnY_R~VMT7?gy5TRo4QYF zgZ_e$aLvHu(3bfIq-s-aDtfWBZz7B1fvXMVc$gW%8H=f48xQkn6yC=o;vX!Ja5)pv zpI94|Zdq3I3WM+Qy7=jnTSW1pqgyX9Ng}_F#WjaAFf=kjf!aKZu3R=x{k(jw5NT|7 z3U?*9{rH!g=U+UH1^^O7wb8HztGQZnzKp}O424p_(v*RH!Resh9oG3)zLoKXvIVofkq!C>%5q}&oUTh0^|43MC%!G;ct#dKb|`(rqMX8~4W z=Z9lB@mF9%?hFB0GZBj807hZT)EeW`lt*J%2VTbiR0-vn9Z^iUk1+vr)%mapgX`~R zpxz^?J9FGJjM=jD5@R1Oktd+!rVhxCTyAF?-n}L*s1)TlO6Nm8qQ7PwjHItMYnhJH zc%^WoDslRb!)r5Z6&B6kNVi<<+D&;{aX-emQ_r|(1IZ@WfYpPmYYtg_s&^he-R`n{ zAi)ak0a_7lJnAaQM8IPu7Ha~|ruE;VX&WX+(MKZKaklg+3{%cU{^TV;w-VSfQV=YpT@u9KP~EH^+A4%>J!LX$mg-&+slWEzD^RzDPl{bw zm7{g6UgDQ>W6Cq>xg!6w;H^UTgN&BcB%h2fqO-!B4SQA>Ko^6UXm(lvL#RJ;t2%`QI!6J|M8bjJ|JV{XPl+-+Q163AMuy{=nEql22rj z@tl>bY5L-pPQs|F?m{H-&Kdu^8Ige9XQPv=|XC-v~>{KfS6 zdTA6h@86$NoXDY`J_ zW11W*6DEW>?JzlwbZ)J@znXcws z6<&l?rsru3F9~gXg#(kDiU*2}$M4hR*P`sqcSt3%QY*Zv=#K??$B|3m++xz9O{i`)_w5wu6L< z=*YYAQX#3qu;rbAp@T>kUH%W3L2enJ6g37RyfRxj6)&pzs^bq^u*pClmIZ!^!}2md z;zLVMwfq_bo%Sv8U4+yMF8{8l&o55o)gwTAp{g&&DkMP%<(Q$@K z5cx72Li3tFK)QE`iN$W5h9)dMlGcPwfB!OTrdn7!Qj^x83v7k&^$%ZTJHsAvzjd=p z7&x3$IQmH0TR{}L@c_REX|g$sc;Ul>$lW6s7ls8~ChuTfr^|-A2;6bZ+no`MF7svD zhNVKbV@g#Yu!=DQ?=r80{G%`r-)7{7v}M7Kxk#h-TKr-*p4B(@7V_>oSq=6 za$+cBxWcF(9bTLdrME^B(&?*VcU)z2pCnnbv1LCaJmfM_y(O4%TI863{bwzui+dV` ze31sI`wkrzo9~c=K>6+Fc8*qD??+!2yyO|q@fVlp z9%Ec&5cnaolh$T;_Wca|XR(-5GUIm>4S-)0B^YKP;f2@cu92@^iUT2H>Y`Rf(?|uu zBDjyYNcH#%Zo!yuB?d@@_EKagSQ}E(#`wH*C44nZM+Ji!_g{?2`DN<^$C)O7oOwj_ z>M;b)tj+BgU8?4jJ!DT+X}>a6Z&S79(?ZH#{&I2jjye(;xr%JKsI#wnI$IVWu3G-n zW1H!q2XLsOP(Y8RPYVi&7XSJo-4r z)kn8qdtXRMC4XVb+};Lu1f%-=evPl9NMRk63wVutEs>)Z+k(4%l=M ze%nZ>fpG2yZJ*WXDn|$5)@#8N^w(sIusYPfun*p{d~YB>qQqpI(!G{(J+3ISG}303 z-KB)&f!zNkp%MSy|3V?V?+HZvjUC`hn=iZjBQB-Sg0k|9s{9etsE>kgz_w2x=gzAE z*LWi|5e+^Fl1a$nFhiwZ5^TwZed0X5X-8g#G=~HP9sRV-iTa-Jp>!|t)_G=x7^gQa zUGNiRMk!KGrW;p^=rUsXP{JXRz`4jTnjz$h1DqG2xWG7qPV1YfiKt465>rG&{c8~} z8#c|4`(_N%dYPqx0OX3iguni=t4!$Yrtgc*-R@2VrJBKXMZ-2+85_+74emTXvFCF@ zN!sb$pVIh_Ay0RBR6ru0c5onHlAKAr9Tz{gn$x-`u4vpuQrIpVcaY8H;4|?ei^WQV zep2&#V+p7n%Tfo-gs^5)D)FzcFc&^}ol{cb-l#^!%uXobuk3$wpPviit1Ne6=lhs= z9Fyhg=eTOQ#6{mod_#ShKP#IjGn?MsOqRXbtWL?gU9>o7W@6gY*U(eiVpdVL2EyfC z@~4HtBgmiPvU^}GN4AUZ%NQ6s%zi`Xdv)P$-L+6XfcAP{DgXAgr1|{e6{WjFGZUdc zgkC17P|8w!Z*$%bfo$<^MhOrpXk=+P>m+`R$>sS|V{Sntp8!K!8s(|Nj<`H#=uRX~ z+Ca@)XkXEbY?Jl3fHs8efik0-CQ0e>5MDXKoFI?+e!*7~Sr4J1xc&qp6e~Dj3HnyD%dn`zwrhCLFu>45cXxvV(kU$=pdgKafQXXP!_X+* zh@_;7fS?FU42>e)A>G{#^KS0vexC36_%%QHaUIt_*SXf2SN6l%E*mlBNFc%33$0W8 z4t!nDJ4+c|P)d>sBgPf8nDb9*eVmeiBA&EqN`7(`>;{b%6x9bR!I_uSr+?3hJ`;h7 zSck=l7e@Sjpy&R^c@ZfkpDaFqZjTu zbaf&o&_6*N>?cjX{>9;aB^rY*oY*22#8!9La_$8z>r|40z`Ayo1E+@4?7PzLlkUSo zPvcGV>lS$b$VXgm@*!?O4DZcNryF}E-kKElDU=m3oX@g`m}X%heb9y=x@6+x9ATv? zwg=bzlC27y$iT;ReL)Ylh&Le+N?;>ja1=)+PnQ&>kD7Ur__mVg-Q^|HuU>{XRVKeS zmsH0Pk>_u-hRJ5x>#txXyrSy}S=G9!H`d-M+hm0cxDWl&_z2fO6r9_Au<>E~xOn)XvsQK3snEqXjr$N)>#uWPzigtcDI>9?un`Pnuod@6|qE{(~7LnD!m6{G$>>nPO z;=k;)^u zf9K}T3s}xuI5fGMG!H;n*UjdMnCL`*;t9p)g`pq0x(37-#>o>Bp@D-uJXf5E`j6){ zEPypn5sh8t0ka<_LnmqBPf*q+v)h%eDeC;}YV$JZ0Z_WTYWwBAEo@wAIkGOpF&yZp ztWm4evR%1YH?65NX!tu6O9yc+wa#YRxJV+I6?#|ENLYCjugn;6ls*nS$Kr~)>CW?=NXrzp>`Uz>o(>w^x?<1S#rV^#Z zq+so$fV$OJbf}2{s@Gq5poQIq{fF;eI?|0VNM0T1#?A&8KR=dAb6xLh%T3 zVXf*}`XX|nt&VV5YTst)njY|v12eY+evu9Q0Q21js%qay6XJ= z;}KrwN%$A2O5O}9&9z2Bk*l>~9ue9TNtD`^$#Qm%oW$+wI~_8O*giOXw^AGeFyiOi zW=~(tCY`UQYi&dux2ny3wx0N+)B}z_2l7mngpImsQq#mBcibtI z(JD!E;@MwW=w|wZ8!$S!v{1Q3=5nXs+s$bQ12@8e(-gdIUuJ%@TSL)HqSbdZ;gEX-=yz=ekuj`* z`^Q6^QkpZ^7pH^NSA`|^v;{F#ht+x-osB;L#QlGGn z5bEfx(@v08v+evZIL2!9$--~?qja9xvVw`-THP8e5WjB;Mz!<3L|tJSx^PKIzH~22 zBvj(?JME4+_xX-jQpBVJC7PWrkTseVn#E?e=%Ekm_AvmZA zw>|8+2(Xa#rDn3$W8vW1&-qb=SC!DqVR%X`c65?oLJl^@Z1A%@Z@4z5#Ln0XLJvF` zDCnST7~SKzf0t^U2M%#1XIPpK0wf^qOp+YW%?t)%)?e&!Z(_vrA}Cb=9zvVgh}%~7 z;T~6wW`xS>&7txIQWV?}@Rt(G1^lHvc>OOz5%noZcgmd~+Cp#Ll~uGOClx*Wssp)q zdVS>i=WJD%d;3SE6PN~^-VuW$U`%!DemV6@lWDnF(Z}4@XXDsd8dQpNE-Eycb?BcT z@z5r!NR1?QrVh^i3YRCEa7A{;@nhZ0S`tU#;9dJ|JIGQAp*2(RKJzoV6hchQnZu4? zRpw`PGz_)zwJJ#`N>RhRALuuo5ro6IB~%6M$cf~IFPsF`d*9Mi_1`g!<+l(vH8!Vp zNuGrF>$^HCPUaE8joHIY8*vTsq!A#2PATC-?sCB^^BoC|iNZ)N7P{Dpe<*`P2q^gH ziwj~S%;B|07eW?8DU+rhQ8}OXVd<5!VxYqBXO7u;K+j&vHWPO^pzwEtuq(T(*&L>e zCE(8atBe~6i=5tneq;1VwmbnO#cP7gbEI_n1F8vv)zRQ> ztzCd%JpY@)g61zk;zO|E5OwAj`C{(ZW%mnwEJ%WyuDuc?08||Y`{&K}1dmcNfxe9n z_Pw24*RP<~Y7eba10YvPx7}EZ3{aa2qA*xKY6!>%&@CegpRI}wGJR7IK7YwweolHN zQ7OMgeQrOu@(t6EVgN(cHqk_G5n~LZm~`nO&l{-u2u_ylT?l0>cD41RmbL+x`J|S5 zLvObKh}D%(KX`H)M`QpN$QR2Ytzx+ebE6FP)m?6=wCEX?qF~D1V%aHw>Zp zjm%~;V$cSbRiPIY&@2g{Q+tx^%Lgt|W1=NjAPl(Rf}a z{MHgett}Oj&v4(p`TYB{P3i*@5J1I|x!L~+;k8aEYehKl4a>FRHD{;hbkL)cHW1I( z--51duYRZPcROb)lVC%hV~fbng`pt$(0-hw7RPuAC=t?3sc@G)gey2l*_L_kTKjZ%6Q4$I{FkyMx7r3pv} z(&aI^3jaK(kFWeb3*J>@MDTu;9A>s=RDMI5aPdXE(_O7uHD_vlLZ&kDCObA^RZ><)lum2s2luOq9wT{YQldPnUF9dQgH&uvw%1Ce( z#RPucG_)PxB;VP}QXdHSd}Ap61!0?mF2#1)-A0YCI72N;=r4`s zc_y`+X4_q0BIPI-<0~&YODg;OhL;APseKeXR*^XZhe{dYDirZ>oQNpzubncg?#-GT zt_m)P8@yG#q2y@?PVtKs*H}@a+y_M?DMbJ}6=Q1WIv=i&@mAbV482fTH^SVU1&M!u zLaSm8wz#bQrwOD(1<3WeYDED5ets7~F#_)hmGFczU*l>AUEM+6cn-RGfv#rkZQ2`f zOCX1E)#jK)oftM8=_VJ;r$iy~S!*O$UdB$l`K!t?jOv-2TMy=BweNgF5y z4iB6mjAc(B%%L!ZJw{1DhT*P0C;}4EHVa`{I;uP_ppco6IdLgJ68$$4)QPOtTq)UG z*R8vdVN57N<(}Rpnbpr}-ZktfP<<0%|Hn-yoP#!m>{WpkxSx?=v4ujaqswx3=!IAy`v$*a>{}ge; zv(y05KH7VED0*TP0w7X65D5buVbgbQkzcT=`2IAjdcJO+NYeN&y{Z5f$~@1ys5zVi zoj!wZNC@3IFgDC#Ia+QAnF>f2lp#}CIE(OeZ`zmZdt=HbV%WbPpFu-xMzq)eF zTvf*o#zH{XEGp?IQTBW6l~L6=`dwDeihYNh9+?1~Xab_i7>q!R$4;dw!qIgZzZ8y9 z(QZ3II35_$Yhk?Be!B#j{8NSFi|q$0c`NWWhcff8cz`{RfDJrG)%pdAkllCG&a?G^ z2-d&&L#ZdnQC7WroBR8{$K4Mk^CFSC8AG#Qz& z7R*u!ZJUV>{le2`gEdK@&yGI)lPkT2rnjoi+Czk))b(MTxZi|Tq+~l=jKYAUgO5t+ znDF_yem8FukU8q zNk(~N-6dghTw9rqDDTl=CSJ{FgabZ3 zV*zBwS&tRFeM)*v?)ZIKlNV+H1K2*3MLu)0igpQvN=I9wlWX1Pc07v*2|Q~CJDUZd z59XBYdVFU_FgY3!PmkN`e6tlz0syU>M7O;rd5O$wK7n6mZw^ZTwLi{z@4T*L8T|*iQSL|U@mus@f3WAIiKj&@NZ3CYlyb7fX=a&qwp?YriUJf-}?7s*)nmj2*oF<-Cr$^D6j(7q+t3> zPlcsS->Zg@8F2W=m^M7N|1g%Zf&4OQs3T|SVq0|RBWFe48aQi`pn|0rqd_VGZGH+4 zx;mqVaHsSg3pwD{5LTsl`GF<^ZWU1Mjt;@@zv9`trvAEuw%!e&pAOO>Kf+Y(zF{_g zUbPGs;=nEG!10k-nV?rRu*S^ni-3v&=Tv35K(+8HLzH0LLD)<<_<4@cd{!^)JNQ?} z%nH6)={!26a{1h(P+T<_?3lCTyp`K0c6gl8VXAg2K6*ewSW0UBiaA8l?Ow;Jlx%SIu!pYusP3}v!dhcq_Nyx^2liewxW3*fi;5~GNrt{KGo!x{zpq|^87I?s;At6 z1DaU~Z^4zzhJCF^8+8J>Jp4F!y*6|V!h)@X#(Y5pg9AQ-~ z0IN03@chENz=cx>2$WCB6{REURA9iS+mL4521=Dkg60gCBFO7{0vz!(6UBLbcsG74Ijx5O>%-q^bbfDcdi?EyXRbZ}^10UoaYo~c z+zO|TMixct)_yQnQRIPV5#j}d-;NbwmybsiK(-wLO7dQMVnxbIY920wJHxRvLE7ns zA@$(8mZJ_#>{ZEy;&y$VB52NaivP-`Jm8Wla<4_z>$s=+Ee2&Q|IprB!2K6EOsfLq zRd}!BT7OWrPYLMw+>m)^F`L<2pxp95KJ-NGQ&a^AezLmq+Qt&yr3*mk!df!V#4w?F_@BH#8Kys4jjm#qQeIx z7`hF&C$^m|`fSJ~WU%&e8Zp%+iN^jLD@_qk{kMVia||nlF%Vm6lb=K0dE zR4FAoh#U8Q800&|mD$^y>xSc@I-S~6*(afv=BMH(ht8>^KWQ($9w+anzmZWeE!lB4 z|41xX>{fIq)A%Fd*O+R8{zI{HPx<)N1B<0}TH&5e1BAY9b0=74h`vi!hVsG;$|X65 zZmv=gVx&hkF$bST3@clEu1hwp8makUm3UNy!D`Cj_g3>W9UVnL$P^5=TB-YqY%`}H z%2pYNY|kdn{kD30q!9c-s5c~DOz@`%)>)K8VXbQ@g|S8W_Pafb$fBoiIYam?&AO~A zPh?Q>GV$>dgG};Qb&mxwd@|jIcTI74b6tH{ekv5Z#(FQ5w+Be%?)%t(lNw1Gs9J1y zJC5;=V~Wn9|2O82G}oaOtgxs391EynfjLB($b3@t;cj@j!*QtlQ44kV&0QGVht9sl$ z(&ws$v4A)fbOSqTG4HU}TQQt(9^KP$qx}X^!G@>Rk$27FCGos$Mu5ci0B}s<9x2-v z_;}8^uhP?((>N9J6@R+XpL6`2nQZHqMabfrL2G`r-CQyC%|ww1$D4Vqx#veWQ~Lue zKldnTMP{c`mCaH(mEX;WneUi-JPtN+Uj01g}fQ zci6A<^%LHT6qSlA|KGX$0cALFT*VL@&gXBm%)aYXxko5A+&ZuZSv==X6PQ-puHU73 zALG?#R1>C>;`GWiq%%mU*{~_m+EthsmBF|#ERc8y2R9;KQ^cLYJl2@Onxd!q51WmyylBbuCQQL19SKMA$)KvZ{osWiFW=MtQ(ABQuhxTrM#&8 zFmpO6fc3kD8hKQAF24)ma&+2XU zWDyj~p9D+B`b{?b13QqW@t4P&ZWt4>FZSQ$pL???80>UUUuGO3SNoQI@FRj9ZkVRA z3pw7{2dkt)y8AU!6u}7+;=k4hl zpSq%DW^W}%>VGAM-aU(TzrU@I!=|Hjn+lm{I4v;ybhLjQIGgrO$D!Y}pp9520(muE zVW@R^Y?&Y`@WByls^%K)cJ{gW-9y_Azssm-TyKraMRk^&seZ#*9L#0toX^qP#A3-^ zrldOd8-st-tDb0z#&HqAQw_TO@@4quW?fmei<=2b1+P}ub?M;`&es9zN!!|-BMp|O zR5`-e(Ye9SXjXlE!*=&?bOcyaayC)?ZC6?iZcWMYl!ate6 zgkFxMeDt(T^|k%PT)p^c4s_-f8q2R+*2Lo5gHGhQwiW!o6WV{}n>!ayW5KdTGrWMB zQ0IV@DxZ*6?ri9ms zChRciiMK?ioOPSb^Z&K|O$^7g5E=KwzZ}NbPnS{J3lFAp#61&_RLVajC!r5r8n8&3 zIkXxaygA;ZG1DFj(PE7=xvDZ0EC>m)8nYX^^$Z|qH~lxJznd8692)e+@!gty_v1f9 z0g+PpiZ=or)Ykt{a)Srg#@!-e?bE9FtPAmS4IHS^-h!U2F0GIotV&NgHV{{G@~P)D z#bo=2J$hI&lVf#Em^rrx4L=DY0@wDLYt2FijpUu0ePo7rY|!c%Fol=sVW9MsKrk?g zK{{-q)FKw>llZ7*>zO;i&hH4URDaSY`P<*i4y4R!U|0rHt3|aTP5L~9x zv{UQBZPp=dT;?X_6ZASv79imxz!Y_K~>M;nM9HgNl*iM{l8LloV?Z;B;?b#k4wX6NQiJeG3=;xcZ#7G-(-jLbGGxyHc zzA?>g1sz+!>#r~P1#hBD`Ma11PO~vc%x5dF@WhZZ<|jW@Hf+AE5Z9ej+*{P#O{ACNWoCH+ILpLAY&XKeV z7B1&n%O89P0x{B=%Uzi9k&OGkV0>p6tcke|qIL z85CIFVFGX?uy8mrzjj+L8So)5mGSioSitG^(z~}Pt;QYP>)9W^vh6rk-}^cpzkkiB zkYKIAaLQ0%!z}+nY*@RsQt!B8i1X$S>MXNbaG1;W)7+jCLq7432PB)7O`X^fnBBBHUNvgvJsL?g z1R+2`$=DexA`uHQkdn*$`oh0w@qp534$+4hTiflaw~{?5@K$%Gyx|8ocRv1^NpQdW z{wenm>UR#k@l4;C7+&srs0a>C@Z*nIWJ+SCTULW#X6QCKJOuAMy^%&Tiz9^$4FSz-x{=#&L*;>%@ATUI|m71 z-#>n_-5#01=bQ5B$*U%^t`~@rn+(hGQGPr>!mxZQS#Y*hHeB}TqW?NnPqGu&mQTNm zCYiR{P-nt4^^H?Y?ZkgQ*t`FFu+%|{Zy%0RP6{Scbrt5PwZcD8s-F51Pd;q(1DZ+U zkZqsbS|L{m_LCaMOjL6T$MNTQG)<+Id*5}&q3pX5z*l?!ywg_tK)sfm`0}@y4%7IZyC*|_S#IWyR%%10 zk53mDYTc1HMniXF#qBj>EPq4B%WG`_bCLLt4V1#nvGrbM;k|3DnIK1K4hHY{YfsIe z0xf%!jDX}AkE9P@ap;S0v6npj#p^$xo*NN(xzl!a-I?%aCQ*9F z4Xfx(vDY!aiEQvpL}syx!o2RJd1N>L09iDc+|AzY`aXD$JlCoLyweiH4h8R@>$MW+ z$N$ObUyL0Lxvf4w}5$~QwR75fbF%LZ$iv60OzaF&mK4+Ic?Suvk$2Xap7JSo8Ln4XO?32OAlkIJ9 zsl&@vgFg8U-hRupVLb=8e_n}zvSF{YFU4~{yM@+`=8dTl11U5sqm0yl%EeT z^?fYj0{La{GU8*_Nm{>>5F=&Zrc=x9c0XIp>E*V|toIFa0`fvT(%&6om0DjT$+e-K z?)HD0N{Qz9Nk^MI&-d&7sPcbz-y;+Nm_kw5=B#Pql1!#YLceB2Y;=YqYzeKyCf@c;OqN&c^7H`SDX0-K9$&iJj)O2JOy)clqj`hnEu<*WKTysNOcy zLd4IYTdh>(8A)>+Sl-Ikq=JY~_YT~5(yM9Hbl^2FaEiYA-hF(Lcw zS^c7aRDwwYqrd&X>(U38xNs800Ff?E2N5FIsLv1+RA zr$u!bzmHt+NKpeQM;OeGVSrvJ*b#V98}-8q@^aH0xxF~{-K}rp)msLCMXkOCZzkvS zx^HojYt}yh80%Y!pO^YdF%bacN#AB9^V3(UV!ef0ZSZjPh$0hi-WoxCXRhn?y z*n;2-T9f*46)~z@+|@NjEAAEh%{gVSHSno+rz=UP=mmjUw#w!A|D4@Phk))%=xTrJ z%6CX3iOI$v?~f;VSoBdtZT%9+HawR5o1K8BZnWY@^w&Zl^ofwlcZ&>{kxKik72nsywj~f0P#q1_wA+UlyO&cFs`U?*OqiN7$V`=vD`ZH{2Y+^M61d#`(nX(!2Ik`I-5RG0NiaGe=eH@w=McwDs z2ATYt$Gi+K*VGDv&ZiAlruQ0P+jr<72=n?HMd$!94$arQpZMwQoHJUO9Jyb;`CNGZ zzP!LZzrx|E>((V%#NS-arWBdW!|Ibbcea-WuAEu2T!1uz#02BSAd-DA(_ZKs(2+F%%?{#qdD`V(!j{RsvUCjSu3mkPiXSL^n0V{{v zP1^fbKE&@&0&wC2$G^tYpYGk4XZZNOcemi3YgEuw!1k&f;V5$xpRQXgU-%s&pd)gU z7BPu}+P&&y(UV$wWMg7ZdLtjp+{Y`ULH3}_M%gH81~lafo*ehK#jb`Fu6u5OHJStz zdKV}&F;ol6MpMFL;#Px%aAJ2V6%|9C+cDSm3%LbHnTTbiCGq(s@~` zNx`3JZJ<@Eoq6LO_esPdf5-7y298ELtc3(Eg%u}4G}nPTjNY*3U8?T}&*>yM)51y@ z-4}WolZu$FzfyG!q*KssRCV+9+HGs_u$Z>Su|H&k9RBEx%=HR5In=*m zZjB3+%vfEx*Y9L=huo_3PU!XD3bFRSORroz&lid$7PG0no$j`IM`qm*39lmMffP#r z06wBe40L=dvCgGu^_6g zPhMC+xix@Q`cG8V!Y)HGgld3Tl4wpB11TR{jzRtWRx!z+I;5w0Ej-KWOe8=WFmHB; z9azQfzrl%@B0R$Hh%_CpMcU4`+}*MmBtOri7$UGB zZn~%#jy{ceh$@WZ40bMffK`ebzl>kU=cVgLQqU!jq0;&kMCRC$P- zblw_ytfz_wc&{pO7lZ1;!^^c8$>CRwmsG;w@96>zp~TJ;*_D*M2ev^scN(KCtRCgH zW)9N}n+u-|uN8{wzTcZkpF2glm_{CA@#s5h6jCYhyomnpD~Lp7oJ99^#;@+vQ|mD8 zhSZkxd8!g(fn>qD{u9F{CLwG?2l2#Naz}@X05rnSRfga^wx2iti9m&NQYNjg$xc3+ zCUZ1`+?2rWK`VPKZyM2^p*7~<+x4@C_rpEBbDR)Nx@>`cjZiMYD zcfXX)VvaqJEJOU1Tod!ge$9%dM5EEPu*^TYVwp;%=(0Ifo@bud-UlZ=bpKP#Rz$GB z+g|%tr~mTt5Ka&MhaWx!QwJ1!Dy)UWDIF_QJmbRM@zv(ctDT)s?j1Z6*7^lz=uz}6 zg;FMftU&2n`$<%2Rg%S}D4)05M$lomq!Udf{NJ_iUWW#7g6E3+@;-ZB>3wz!K1kzt zxe7<%h@ub1{jBwhp+(PoOZ(DcOkLqrb!$BGdk4)z|Ec$=m~fUs)lVxhpA<$3wJ;)^agma?RYgyjdjVX;V*JP7|9u@j%#~_0%c; zvfwQcKPmFOifZI(gwH;7e7i(6GSc^c!{u}DM`qCtiS<~f({3)*3W%&*Wz5=__ zlwNdsX*~zqm#RiBlUF`tsOuNkszezPu_%Zt-ER+01QE*o>kD!Bz(uCNd|Dy@+Q&I7 zg*A0=*cmP>Q+Cg|2L@yzo$@qLhK?MW7^R>?;4c42iG31T?k*lAut zcxYj=Nass}E+2u<58_PIEtgF*Ej`}_FMhJ!wEGX}B>o+o4qeygRv2gbg5g2jZ{G)4dr@<= zo)s#*L4r{aoM32C*Y&bth2tQNg0Cz+W7oulH@+XMY+coWK4Ry+D)EEi=a_^(5xun)6My?%@Q(PPNyEfr8lhR&*GOcp|MDD za3QvOHBQ4*Dh~Z%-T4^@l_b*mFh2ZI@2?lWAaDPuT&8X@%T$_2=-vKiZXwaKU5{=N zmo=?VgM1FdUq!>HX(wyS9gTCsQr3fSVcc)~7x_TkEmDrXi8y!- zkAS`1V+=3Wn9(0m@r|B~?q5pn=0Zoao}{_=qGah&IL(qmHQi1O_7>8@$955{2#5LZ$GqZ~K^vLJCf8(VkAGO8$i?msV z7&m2IYe@@RbdIevG@U&99p+c6)0D`cr`R>TP3Tw*@!?X&(+v(3mc>0i?jttN)k*u< z#ZE`9GwVmi0UznSm2sy3iAcaWuXFkE^fu1>k6`}Tjpb^>g7S1;m5 z%Ci8Es-5$hGHn$rQTd#Dfs65sjt>VyMZdM_@AcjipzJLHT5xv@gZlY2^oR23#fy*r z=ZjjvO5wq>-`xTaYpcY(SB{6)Oy%>dZvxUA@#MlP^m3e0fn-FE?d0qe1fU9h!TOWUN81pwli&sDQLxslQ`IZ5hp@z^ zHS5nKf)xJ6U!ME5-*omI8<9UqLOuvbcd?jb3QxwZY&JF= z3ipdowGQ{P4cg<WJL^+emRzWN)Gk+GqBC(NC3BtwVF>sD3B{^i$U!*Q@$c<%g28WYj$GOE0<@4rL3% zVV@HW;^?8b8We?Ujc@Taw)d9iYvnEMv*;p-&U``Vwhg!_Q7JoFiWJEEf0VY`ur>uTRg zbdBfjx=)10p?v{LZLzSce6g2}-Lw$<7+4B_hTr{1A4n5U^Il5`(E;pon7?29yl~d3 zn=U6;uWo(|*XsCdal4B2g;&_dN~LA&@6k%1Ncr8kp*6&#-gR<9WC`SnÂs7y@T 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

8}9NIxHxGO^l zbu)66zN?-6KFo;wi6g0OD-+GvYu4G;tQirF2}J{`WF!##qo-2^6_Y3Ic#sZ(fn&RU zd0b#7_^Q+(fQ;6oDdPipgHLir0UXHqXOXREwgcIz5R>{H{DLIX@Z*n4F;t*p;<$k+0iYNdzUkVyR<4kX?a^(XlFZoRV)WxmenJ@=~1Zn*GV)g-0 z?_GQqpj+iJE9oz%#>{heWj}ZPem`G94}04NH>rd2Up|G9CeRNA#6k!R@N4G~tScf* zCM-j}MYU#zJu3+j2rJ1h$84OJ4kX$sBC(DbIT%?g)1^MAl(Vav)m2zWIsXv~n|a3U z!^6YFRJ-ujF0JkRxwVaQ>2Y5dfGN>R+>L&kw02j_Dq?Yg2T9W(;_bqCM|B?MJ^k=E zA?A7??RL=$rgcEW&Tyt^lk%0YDu;bD!l^`Qx!iW)baEuLOl8R2U(pQd@ZBW2*V=<^ z5rmUgUQdz36=wX98yAf0adDT=n2IpZ%EZKkXQOg9>hjjGRPz1G6()Z^GS<5qu_+3& z1&FmxBJES2aF9zV40fKUDatg5-nDZC``t zd*8RZJq5$VyHQ=Oc*>O%GNi3R`0)pi(((;^+{hjUAC^K~UX&8wM){9ao4o5N{T~cZ0IcHtnYU1Tl|;JG{#p*_R~3bQ^fnFJMc>=| zxKHgLJVjE%@@K8%9i(EnuQT0SU&V3D(8R6nanoecc&;SEG%r;`bu;ty@kcm4D9|F zk|S794D}YL)S4zi_}S1c^#)oVc)}JIz&>8mPSQx~0A=^6%x(r%@<{iG6>=9xvxk!& z;|@eFkGk{U%RdB|L63gnr60v~K(T%Yz*17f)o$nk%&GQwghDbQ(zFjv0*>c}UrC1G z{iEEo_z=l}ol3;=mV1wY-@$qIbabrq?T=JL1k;J=mSrAzv1KF^tfeqJPp_z+M*ZS~ zFydnC-Cn`T3Qgi}&;Gvr914{S0eBR^37Rh|&+TQI%ek}9zv2)Ie{|ZX$~58A!IhKp zveXlooP~fmzYqYf-MD>ALFYf)XrX`(ZGRbaojZ9K{r2G3T3ox%+|m4&XqJ|TloMj& zL|@lkPWLSNe5;AfsYO|GJ-R-@?A-NYW^ffF;TQXbapO%b=kpYba8lh!{QX!17gE%c z61pWWsq+Y7@z45P!Z9hHb8Eu>C)@kbV!(L%5rh1?G9mkGk2K{BNYte~qt8<2e(&Ay zHuLJu^Lw7FtLc_xIk=dEDnrQHaD#l8zDz{}5XCND3SROL_7lf@inY|sJcaRb}q(e{!7xX`vq(Xmtj zqgNW0W-IBNmlI{{L9$NIS8a$igUwCP8k3rxZ2N}2H{Jc@6tJ6YR=?XVz4+_S*-p;p z;BW&puyU8FyeWFBc>@pN)$BHb1opcu_J~ANsfZ1kznOmP*>F1H)J*nGoQU69Pa#H_iU%@@kOV z9(!^T1~bfSP>fReG5ArtBHer8O$xPOV9US7h{D!C1LQ){{!Jv}eyj0%rnX=GRcn@m z?6B!6a#e-^?-XCIhbSWvF_Z6~n-^g^;xy%|7L7tmO%X*y3pAX2_h2KLT&G(R5?H}6Bp?@9| zU6u5ASq^LVOKqbR` zvew%Zy&#-^d_DWD@A;R9KczrVwgP3QDjnww>rv!==>}wUaKU@amey|1#JY zv$I=Gh~TeYy7htVarR#)2UZ=#S&Lm}Tks3(Pgb1X_7_Q6f-a zC^lZ3oLQsJf}U87U&UhZd?l}_P=O73xVJo@8FsGrBYOBBhXr*7R8XFc`qK?*r-t)` zs$5WEAnzwSWfqm5a;uve8=F#J*)@LMo1G!wePg?$tzEsRwEp6wc7Tu=(G%bGvf-in zS%%Fe*|``cjhCZ+Lw_AMm_^ov>s-vxG*p6!ee_K@S48i`oXC@dboFR{Z~ka`sUUK$ ztzQi+#=Iec&JF&cL+x7d(08hfIZghobzAO#xR~baxIEV$rztkSBlFj1fty~-tQB!_ zAz(Au+Gl$&z`9`Ntw}AsBA1#ljcDT}9~RY`%T=p^voh z*^`T9W>!4wR!ykuRgljj{u4KV<1~Y>dF}P7Zk~jpkHXCAwp-}Wz7F4P@EDZe-wS&J znP%vaHymBbopPXC1~AmIY&1-{u_Y9Vd^pc$%It=Ria@p2k9>nK2gwpHGe+^tKmVgy zSPD*OSh@V!R+Fdy92?W|Z3hRwhLx&*rc}S5$BTr3o1N>)On)?-=_UBlI3=3sRX5=$ z1Z|cy;59?zDpzUNoQI34o|E6s55{|fF%;fwrs02tKT%jt*5dOV`Saxl6Yu$W`IY76 z%=B3|d9l;ZV`1iuyJl){6oA{yZckocMtK0(m4T|x#?Ec^9JilQwhyRayk_-&(uO#? zX`pa#9v|V19naA7e)a0#Vt@sASYScJahFs5&Mz|b5l3BJ9b&nM;&SMCV4DYs+2!Cc zNar+=aS#eZtAZI_>RFAq;tC9sY^<@4ypEkR%kP*`%`d3kK~OYxX}M;-ckj*3kW;)! zs|j!a|Lvg!Tt{wyP}}VIs8#+#O-TvIpEmh?|3^=epKtG_5Z|IEe>&}A8=W_u0|z$; zKVw6%pU)_lJRy`E5P6K>I2l4i1i~Q;;E4|Jo7gL_>8=t6)ZO9m;+WUB!F4of9$uJ!A9q$gI2xLjWj^lmsEonQ`r zLVuEyfAODZi)QI9Ml}Zc3XN=DfXUVDtB2i%HYe9516%{vBUU@pqtfxulSsqOH_yEL zK6@m%gz;N_}e+U|iLGl^CZ3qhtkWZ2IJ?IBTF((=%2XVWJP1Y!+s=%V=WlOLW zBkSr}LH^nOMPF`U`eplZ1SQb^U2n{F<@Pc5aUyaCgwnBMukD%Zs!aYO!$e7hsXbSi zpZr7BCPiSj%j~?7EMTiFuc-cnV|THqsHq*XrfO!%(BQC>cvrqTI1unwkVFq!e{Ti0 z-X?&vh)?WnB>OOX++j_wRcqDtwpta8o`2|Y@8b;-jW88JoPtbO$(E%4$xjf0#&8jo z-HEDW^>Vgv{ZX^Ph1~9so*U>BIw`c2homnL$P7Kose$(JxxA!eS1C{8%Z>J{z(jUR zLyAOIl!QdduPU+Vk{wRfE@3ZJ9hh_33ssJ|+O-HYiU-G3Fp>VBnSnx^x+N9Uqp8dD zDYFL96Qf^N2N0*g8MQ$4q&AMI%JljXX*(*h3A`A3(bd+16!fXwaT#O>;eS7 zw)a&vJ4$x~6kBEs2p}8oy#2+90thA2o`mzY@36o0zZCWtxK0CT$z=Y^>Son6X6L(~ zckDSnHC^`~^~t|+X>4{$NW6qz(?kChXOU*jOLYA1%_6BF`7{v4Ai3)W7a29APs{P^ zh^$xhbH1+6lR>0_Z2=h_U$Thp1L_uh9V%+-dl9^6(SKcbeIybe?-iJ9QX-r19CxUY z4Q!lyIMOb#qJhV`cir`(s{UfX%!vVwP+v{XM^w-cxUt{@wJwqe#wEBfOYW`8tZ;T7 ze?crumR(8e1VN0~+bt4GV$bDo^5n2{d6`(}ddtpGdBm$-f>uODUP~!^i>0) zMhuo|ongI!fq`7aTS*|$=$YO$Z;AYpDNP&pFDx{T0uYxs^BHz$dIAo<npX;c1aI#@Gsl7`~N^tSw;GU1v#+}^O>?|Aoc z(sxr}qh_<-vQqja#->((LF30y%^XJ@02kNwgb-L7p$3Y1B~K)JsLUiHeVp#Vs0o~ZW;RO?k=o(D zONRc%A%EQNRDW2vSuj#+t4;5=gTKd7{&6Z`zO!#YuU7?vaX)iCXzRuUT;41Pu}TgG zebULl`RRRS$(w~ne6>OWKU`q0zkPJPl(9AlPi~MD@!a5x6@%ZXWg^4V<*dYRsRK}Y z7}o7c2ZR6j^GIRXQn6lFs`TOQUKvtYtD=kX_b}3Av-3R$(0^~a9l7oe9jix42V_$N z;Y#s8?(?h7bVcKr?7zNS7<`Ca)X33@)z%Y4F*F$B=4&)UC7DozYr$6omE?~a$ za5W@W^S@XnyndbXOvVJ~-QT@MLRfoWxS!ITZAYV1f&(t}K6CyY8#eVVfb7qmCP$@j zdQ169xih$(#LlnnmkAiT#&###dmCF-GvDqmW#*yDdtH!c(aE)2+?`^Ji#Nz4s6~!) zD2VcrLtVhDNkJ@fT|4%>0u9ohIw-HGqn^MahE;wm{`d1=%*B2ni|FhdY*>5Fk*2>j z9ZXheYipZnK3roKCB3n+*gcGo;z0U zzKVBu+q6X>U~g04>x@%ZF8C!v-FV8VYfueCR*Vfh+T@u~f>}j@=jSx&k+nJdS;qRXJ97<5T&Kx7^ zcc_83#?@4(0bV^CiZJfH_cD&*;=-owLlYgfOj4+owMHhK{f;>M)P{Hma->lfi`D7# z7sa1Y%gK{_*$*NqB<8*n3CL`G7w(a{wp_tND}nH!mKd3u`-kkSaOZ4YHk&SREw1*w z5w>mz)f1JZUFRf6J5DW#3!57>_Isp>!Z}YXNKF+mT{(BH`K4F4=I6444dkth{8m~S zni&==Yalu!lff1)QjW3iC*R|CD~w6gj$`9{-1x7p*bDZCZ2)*sZE!m)alpHlRK$!j zR|;^Plvgn=#LkyCe=#92kRrp}VSQ!A@a6tdqJTk(1xd>JiTI?~`>RHEPG*(Pk8l!J zEY&go;$Ln_`bj>`+86B+>C~;?8@wG#+uq;Dp>^YV>pbVv+VfZM5l;J2!^4wd@wTe1 z_uiS_ltfGPFROki-N~{xl;Sb+O|n2E&tB~zJVqW-Cq0k=BQOnV;sU4|qu72pTU3&m z`^w;Q(*3QgBM5BVU(Hl2MTSygbK==TM@PrKrKVPm+T@Dq+!T3q0JVpEfeIso+*E_# z=E`}OX91!jrMhzOWF@g+Cq6qh{?&IWpOxD)%Y)sv%dONLF}_62o65GXax&-6Neh{! z2q~RWCTe%kwimo(_i;+gxsxrI@s+yY(@fx6ZhH6lWigZx~r70?%fG8+M5D=+?A|e9PlnzNKq9O#9Dpe7%P^I_KRgfYoy*H(X znuL_Si|={gbI$K~|G1y4%dj)M?9S}-%*-?2r_7OsD^ke?8k-@}a3HOCD>46cO_<`| zl`Gd0E*??5o~s}(EnPDe&UzqK)py~>K%TMsBgk-5K-BEY6`e*TJc8xE+)A>MlxlT+ zu$ix$fv9ZfAI`^|JBPkpEyBou)vYy%>>*Gv_%vg8YEsD0(crpAXeib1(~gkxy@F9G9hR ze0V5WseQdS?`TXHhKFM*q4Lz$n?dZEYcCI6TeOz9UOe?R;*FRZDt*^6?Cwn4W0`V3 z-WLP?tsD8Az>#SJ&mC#$R$}<$Xwe{PTULWt3K!7Y$D{34-M?_!CFGmE<8I@Bdg?W_ zFX=4%0V5+F`SxZ()_x?<+;gLsgV#dwU|P23vWflq5~sd%fArr^Mc^0iTv+L7_K%*B z#2Ckjt9j5AUc3fx{2KA@3*4ge4lBmyur{WMrqi@j723U9ei4MJUo8e9qy>R#`@4xE{eiP`%VuLCL0t~;e(QL=sG2uBEg{5AGei=4Aa`sDOd zR-`gyg_lxH8= zxKLAvspwqumt$YbU0ymHnuuI-ozJhR0l(?(*2vi{L*|q@7<8yY8_1aI@;Pr6toUJW zDe63LEiXi-^{dXQ1$cZWsfZ|FB89kowl>c{?Qz7`cDU_9c~zi+t!T1u?z>U9OB@f1 z8=5tg`I|ugMymRe=eYWV_5XG{0-OEq;Wg zYu>YPI@PLxOk>+r|F_%P>49e*eq*ZBE31o~d#_~vXrCtr8oY=Jh|3KaSyrZb_rZjkr+Cj2+cAe9gQ{mWQ@TSkl`Rg%t(tb-SBF-j0-A`2OG7@x zmyQ+L9M|M@$^3dPNIHE`@JWXI%o8k$LIp8$`=vvPch=`wiHIghztvuVZi z+c&X2ghBX7n&*IJ68nQU&EH%ujo4wE^a*QS+r#Cw0hoLA03s(!9lu3QJZn!@~H{bt|x9XA`_@*~G zNvr4Tb-Q&}sJ@Wv;>-a>2aj35KW!OiYxB5n7ng5svb6a-(Nop=dC#T%Zz$j2?li3v zeimy^bx+<=j;O_t&w9dEw-~$2tKAc%^5dfKbNV07a8Y6yDAl+kZ#%CFEu1i# zSnWpe+J|d$(K$JV6AEg*OICT?E5*r$&}lFh&}UwS0~{kwGG^7*23j^VCOie~_T zQBcQB|6Dl0sNoj*G&VLaE&|IK7Z)4*G|~eZ1;DO+djY}*t-=A|K{5!S(NOs1RFLix z01T&s@L51E4TPP!0VQ|uLrG`=ltcvWC&B+8ll_|`|0IF?Xa4_7{Pxehpaf+PCGIk5 zAp9)Q3%z?90Mt@JKp(1#8&svhZ~&&?0afy=X%qlgaS4r$gon9mgac5MF8X8RvDo-{ zs7dkrC(lBRp(fdmL3htOLrn^K2Es_&7!V5Z0s!Zqf$+U;VmL@=0RUt1ARURcLkS1r z%YYmfM9@e?;%+1eLpsEP^fV%IZ-)fsyuD&U2IvxLZ-)wHG2V|sW*P`W*GVJ-Aqs?{ zy&r)rWGanD-h*!1-rFzo+ApHfs1zERNZO(ORm4oD&}bl)M%f`e+`s7|NKd7bDIg6^ zh0_S+KV^|1f=VXrQPKN_6bkiEVK~S@-P?cRpJFpKFX;C# zQD_k$6WR-;?2$-&dl)hu^}pB1P`x8SdbAIS-`GTNU^d}+5{RZ^D0I79n|t9P0__b_ zC}=VR~d) zt%FKCFGT?e84GtWugCWgUS1y86#n1XB_TEF|7MrUnt!lMOYG|Z*ahD5q&ngcw?M4Z zn4CHcwGZh4aZX)wZaxvpczeZxi0b4I=`9d>F#CM51+faDHs$^Mw3&U1?HBdLbb(_J zi$Ag=KGSFeWU>$I0SyN;LE& zuSk%6^K0?**jRLcmy5%B&8ELNg>$JrH}%bj7Z1by?m63ERkv*2f6F~I$TQQBotpdM zeQ{QJ@O?KYTQd#I2OlFrMzkN;{T3UShRHhcCKDa#<9fr&RQqCpZR%DycnBQ?);4x_ zwBj1;YpWX`dqA(UynOz6bVcIaK2LZ;ouTu_U1xg>qx0NP|FjS)AwP7pvobf(k<|Uu zz$YMcsh>Ae&k%X~K*wJ!!93{`|4Lg?=PVHNrz8es3Qhn&D~X)tKC@r2&m;9+AULYd zECuiU!z1w^0&f5Sfq&QoVgd)?2z2Tx_5y_a0mc8}4T$jW4u7#m0thVq|L2UfH-8Nz z&})}L@PA{;P0xQYM=vLxc!eg?hA{TL(TZZ93DcddfQOu4|CiWzIX%!eU(4V zF|z}LYj;KU^`t-j`E(H7p9;JLKLBQzPF?*kCzJqy<~iW3`QgOBN`MIrfS^anT%7)k zHRyIq-!Vi0z{S7#f`0ae87Dv=2>=iO;t7Ut7!7e%efEa{5W4>+cQnX^^E!E0{i5C# z8E8m_0iF;$p+k1!kjxB+Pe4vbXOBSLhYkQVeuaaO3-Fp>=rio2@X!EXuLs;w0G;k_ z-QIordprh#mr(!^^r!xhLD=3w=(Pv;b6!tCxGTU2)vMtTg`a?Qp8ydrXh^>OCm#dS z!Ii)&40QW`9wIn>^cxWD;fH#1%YO;}`xF4U|CiubfP?=fxI0krKZ3j3{{JAjtJ6tE z06y6M*z~eKJIf&!007u8T|93F00`(50WdK@zfdA4py~rKUugCOih6{9Lz(l=R+nxY z8w1Cob0z>5?fT~rU{LN5^aB8N*)Rb5ZU7AW4`jptdldm>)BSzEf8)UTlE{BIItYNR zWDNTX4+id<^s?P9DQ-LGMTZN`zj(#&$TRNTp(MErPh{0))VAAhz_rcoy;dP&hS=FOl zoG>mcO_=A7SpTu}+KB%gnek{aGHbB&f;QrPx^}^rUWa@I_+jz?^SG*`ZCU@mx?An@ zsUz8w*9EWhiacj}g#L5jYPsVXTWe>2^jvTZgl_^?na}k8y7ZqL{*!9A^TZ$gIHU0D z@{|mhbn>J@jc})VOHnZwY`i%`& zXwDUX#@pQfaz^)Yrh>tSrt4(;_IGlEHupNq=BB>?=Xp>%WD1|Zt>dshYrRhO{MG(F zIR#Xu@f||LdXJh~w$#f{24*um?m|#LvC!@&u|}I`LFurzXchJaTO@Syk49 z@4vOR(uHHm>y@GR*g2f9*4ZqtD-fvA_SOtBxFF7p1)Y~GOt?5PXO3|mY|B|Sb0AiO zoG<+XZ@nQqpxE;k9qi6@*L!HMGgA@{-lT?0an zH$(}c^V$lRgb>#q>h8i#f{K&67FWf-#A;>E%i~^%PWq4s{kW`5;I*j17i$aSRhn7K z>w-(&?=iTb$xgQh@YuLRE~@d++NBJqRIYeN?NobCk<0BoR+sT5tCmFzk%m;sYwwZu z>xoZGH-yP5oi16ZF`qM?#Oldcy@eu}*jf`y9|k{gDbt2oF7_lmca6U;%iXRf!LNQk zC}h6nogLPxp(t&fzrBa--Keyeil^m_woF>zwIyx|H+}P-4*ehxKa58p45+^{9h3Lo zGHLK(Ive<}k!ya$RlTrYU2K_c1&5-@HS74ZWcl5w&fyfZ+|bLp|79*TlRE;|Sfx0s zZba1Vi0iDhO>@4V9y;*_KXmg!u=4TBLaWKUougWoe;&AgMFzfnSz8oXjbX}ODm{VS!&gz)ugm9+>#8DhlA0>*cy zi;SvauX;ybX<6{op0Ri6RSx@&cKDT+g~03@(gdA4m2h^pUE{)U-v;?uR{^l z?Nlr$9z~@c-wQ6v3pQS?)xbXtoq_#hZ*pLNGNy)qdC;OG1@S#`hrS6Ugwa$L-#|-MemX_MxE-hEgvq*aBpE9!Kh5fEjdh4<`Vkw2fJ0t!QOC zei)%;9?|<9`WO z-a9{A2?%g-@g9TNHY{ta`g4LRyH0Vs;4J6h>5UP5ePH2Jop%aTLq@-9^*ZHhXi-#W zT@4TQE<9l*tgzgvbomrE^j3V0W(+DXz>}VQA@#OcCH-LRQ7rbT`74p{iwg^eqMVzFkXv|da-+8p+@_(q4zi(fIbx)ewD4m13sXEk4HcwEIWKNC^9 zuxIP^tJu(P3LCjPc6e{d^K(x|?rQ7q*Kd{4om*m;Zj(jH2ZUNr?QzHuM3~&9tzDk1 zsZZJtqgK-c;%;%?{#*%>t8DJ%*2|F{nNFwgCm(B{;Ze-Jpo-KF2wk!6oMlHCBovfo z1u7lm*)z6o^*b#{SC`rG_Pfe;&$u(~;Xgc(vK~*F$!8yuE1jlQcFVA-WT&)LrxXuL z$SaWq&R>f%JG0}?aV#(kiLTxa6NXR>H{etvQ~c(f$Yz*S-yzdWIB%lSz1z1R8bplE z&D~n#*hX$}z>D#kD)r)mbZ0-ISG}@! z$}G4s?`U$-ZyjT0X|Ls6`Ugm^LrDzmM+AJlDV%1h-jPmTr?|JUX(H&*>0tv>f&X zjx@^_z@0tL2&ab`h*mK>$+oVRczq75EL0ddKuF8(X}t3hrQ+eRTVpm$)ZDeV)a!gW zdN#8Yr`F_Ic1+#ngff}5MA@Gp#f@;Zj0%)5Np@`IGtHySx6-e4YeAq3d#JP5r!KZ4 zR6lS;Ajz_-mv_00>ILR8m29||HTIb_*NaaLw0MT2rkZhKw^-IKI2BEtx`j^}9_P3{ zg!SRugY*6tl!h-zO!aCHWeEuhrA6V9jJ;?X_cR)$bCg0ts-zXjV;8Ofm*#|H;X%xb zPGTAhUZ?nW*ILf@lCJ!|R5jX|Jc^Ai^Qo9!^*w&Uu^l0;BK=tVC{IarZAL^z4hP{* z@Mk(c%aGdDf#)X68uo*9H-yyL3wAgcTpwen#S&G@e|l5u=5(e^gjKx6y_def+iPrW ztX&yFJaz{q&HG$ZSt{t7oBHz3q>ma&>z^TZK3Tl6 z*n;{LAnL9ZRb}lE)-`k1?E~+Brglv15l8U$#^kBoO>xI{Uc-rJUU%GW9m?6_gx8gu zDPd>vjkB#li+7%M_9C$C`)T`7%DFrfq~WeH|HyzT!i&ttOE;z!OJx}CN3!am;4ElJ zIZC>XU`R+rvc;L|>GbsVm3Vk~tle|W!c|i`(7i6I45L18w}>t4 z&`yhCZcbM5EA@qiW{BfS+S?07Lp=Q$PXWx23Ei$(g^C7?ri_65!POo%?ny=*nr$3n zS}Q&2sxO9Wd|jwN3vGq)9M|MzcQClPkD})^gbTi=QjURyt=?>zklZ)_1dyyNr*q`g~?{MsqyMf{-)un`wBCXhzt0gmc!`g3~7*y!w4# zv2r})&z-fkwYK3h7dQFq^+Vq$CnphxVJD)(0^sG2!iC$it{EIv@7V4f-}V)X@>@`$ zJ!9F$p1NEdx@(QZzUw>CkzI7;Z$bEn5iXCX&&H%#HF_{NN~=7g27IMu&erWHq)9Ku zIxk=l#Pjs@GFx73*w)2(&*q)VkFlaoDiy9$Z%9+L#NM5SF^) zd$G$ zvwWk*b7^Vm^?Z}y7dQ*e_*edvCm*Qy-8DBK=Sg)>o1Yll4zwG3AU?-FsrsDih1MOVtKc zZr{C3*x505e5pMpgZ97BA(HaO1y)ZlW!fo=`OR!}B8Ao}MpGn=PSVcSBP9H);#X3J zZ>;CC3W;5r_Et*Vd+O1PwV?=!INTkZIcC9w;YPdxq+xpFCK=k>&6Rd(TtugoG_eSv zSCwpcPQl7A?rJ4hRMT#(^2FPQ`@hYE# zA6r{nS-XU9vSHJltVUEXnliHGZXR}2b_odD%hT|x@Y%pwV$S60d=sWVtKU2 zQ1VR4+TdXplx8^L#>+6doRxtV2M&IkjWnap$^0g+=DkWsTUMWAg*4&{-z}T1(Rdl6 zIkTfYC9gj=NkfZ;)<1hb`JWBb7UY~#KRn5wD)Y8XglQ#8YdN2Qra$}!?kG$Wjih)p zQFTA%JmT>Jp^$dwkIpC_c!kQGfJqD5qEFK2p+NGa2^I2uayv8uC*Fx)5jkmRGv1M4 z#+0z+u;yDi{$+mGY1YE>BrFiH*l3^3Hm_oQmFOqXUm3xWEsZ57PSv{sJSeZ|TX zaw^raEsP0dhb*%0Zb9C4>Qn4}a1-ukr3tJF#<9$&(YO38?MiW{{L5!D z+vbAV|LB5;OH`Tgp{E`-L_VKLJ8|hnfc_gVNMYrSFIVUxA-I)Ao6i6p>}SDGao zsE+v!=TK8uUq8tyLB~3?Wwfn5b?T80MmtjVIOCM@l;Q-!H+ZsQ*C5Ws>Aa&c^N?|M zp8AiTrrO2mLs0C1xIAH5W|(x5?#V}yA8gJJx8IrJt-2Mg+44!&rd@v#eUjJ z>H1OQ)EQTqnVIQf%6DJ;WQj=D^7*xMd1#YsVaIFWRiPTOZg|H=;_ z$^6n=Hx6JJL#0{p{f^GCBy14l!migx|5-1w<=j0nf4gnpyPh}U(?VW6S$UT|=n&t}*%zP2`Zk2v#@?Be`*hSUq&BX(v8o$`t*xF8B6FU{s z{i?XAurSte^FeFNB!(uEGCN6swAoL?ee_w~hBXW6{(f1g}%N%O%;~03#!ce7(s+U zw?w7(0S~bWx`{&DDtvzw!Lm_OpMH0Kgc721p)Zd&;%FgG_b_!5P(5qEGOWn+hu!ts+2r3*b2_dHu$ z@3V@QsP|7s8S$ffmR&5l|BF5B;~N+sahxlH@Jc{HuaW)&FiStCeOtTPwqzH3PD1hN zJ78e2$UY6t?YOXS6Wp{wRFOg3AIZ|RS>Lko2k%)6E&DkrXuHjOR1*L^X*h>NT+ z4!En9%LH-818DdRgTASQlSfhrQy}j)S9P!M{V`Ue~PA8Pbg0B*r%BxzpT6yrb9^{J{v4L85B zvC+Km3a|#rw+l4LMEi0mjkLH$Sf9*_VsvLP2$$7hsD6*m_|>9*R*g@MRVWuwG&r7o zRJ{4F_4$M9jx}z!cZ18DEJpVVk4S5UgkOALAbBTC-FM-su42p6y=rjF_5?*kD`e1j5n>dzom{)YtF+IUb6`4_-pAe|jpY_&9{01VfP3 zQ$&GibiWR*xg4FwNsCszI>nGc#}T$akkfXnnw*%*|+{i9XHcA_9 zgnGg?#qDZv*z_q{Q`R0dffYZm7@@`I}~2 zr33QZk1YWbnR)KNE`vpS&{o7l3HWg&@+5B>8>SHGtb2MH;c7FtdmJZw(P=NmZv^6l}zrP+M}AWsTMaOwDTQ#HEV3f9aEOSq<#+HK## zq#c6hVxs!v4`}Yv$m<-m(I)Ds^q%pr&b}$l+M%Uu(TE`B|aKzqXI~TUu62_@jj;M(Suu zj@F#z9aZ%!XJ5UEK`B*w-}~20fo8Ih#CXLc548#Wsy!H}K9THy3RJ#!2(K6=9&<|R%$dXsvar)%PXamo`QPM^O)*C7j%}>0}eC3!3(9O5Zpj z7YLpa6t*w`vJx^0_?X(*OFF+L77}9zlq1$$=ASZ@Mr?y%4lQ6LBVH z6c1E0-$32HeS1N4^OqP6AI;pxf@dv-6DRI{a2~GHtQGyZoovQdP?<%xe6I+X8oN4l zW7$gw>O9x(*6rvUM%2C$E24-d&BaIrr%Z}P>`a_|0wO7`$kX85G2}3V0$P49ETo!s zbT8g|?R+q+K`rUTziNhN(qMpDk&cPuIc6I64%K`8=JH}CY2Bo^!|Z?y`=<31ltt*5 zYX=L?N-R`02;um<`DRP~jmR%N$YMWw&iFHxaCx&iPGfEC{bUQK^PRS7xztas zq0=?I%^C5Zs9C!|X$#%MeV5nG>vRze3qc!VqDK9v9HR%*R{6G)dcf|nlle#t zi7IFJg#$wi!lQqq+fn=sp6#u_#6>jrng5S|F~Wsgt{g;V6n4xNTe*UI{{(GMd9U`H zMSXa_=*s=za*zBjM@h=FXvrv_mFF9rcwZ)!nf39yK@qKx>Ko9UB^P}_TqXpOvVF2>b={PzO^0S|gkyw^;!N3k%u(ou75R4vOBz zE{(`*+FSZyT_7G$?sA}oe>Jq6c+KYcjLw+L(FapO63n}!K3PZfuUUsjTBSo8tsj%2ite7X{%yeEMeD6V3Wu<7#?l>n6t4(zA zYO2IvzRLg4$r;8K@E&m|(rHaT#7%6BhWfR>zK%J$&Qd^|#4Uk93pgGZ7so6>l44|J zER&R!9RB^=HHZ%HB*nw)_v-Z_rlIusyDEbQs`@m}R@I=fX^-jJSSK+aIqLLkK{UBr z65X%2$W?>%h1?K_peQ6cXK%HUMo~A(yQ>N}YnmW`0*#n=usR8fXZui6OW2ivcTY4^ z0t{ng#C+#mUi8{ofwjsRkw*TSqWt_$UAAK8`q5r(nfRK(Eh#y$JAuPU^t2${p7rxB zWx9pv}=7RC#5OUyLh!DR;Y@zE$swL zw|!$sAVVgg+QEc7PAAYPeXQhFc_6baQ)C)}_ryZCfqje_)$e8{^-8WsPBDjW`0Z(y zxz-s6j%%Pi;(*{C$fHpw0i*_KyGQ@X;)uO|%Z4KO<6qKiwgD6GSSx=IA0&-ncNN&A zEevAIXprbOmRA!`_db+t0=4119=1)1xi^7?rK;X{W57N?0l(a~6Q#Zvzu9Kt165v=^J{Bs?{ZElY>c=S zd!QgpfXszoKN9Dvya}80(?F=qij#sg@}S4GV2!_+(^k?EISxy&>f=L?2su^87n9 z=Arh2@3WI^o%TzI&O`gU6e8_D_H>KMo$*txCM{mh(z1^h3s#b)jh^Ix%MYn|1t|WG zG*IX1@I#{*l-#K()IS9!%yDr?cw@%#QA|IQlU}plbf$tEOgnvN_VrN*E&Cp=Wre5M zAmIFHKlN>cJYu1A&~+}Yn{yZ0c^dt}>dcfIf~}sg@AJLa1d^M)3-}y=hAAOz#uP;@ zw)w1zzV<3!=$sGU@z>o~*y)xa`;!@ZEmx+mIG3>NXy1e&Z)ODbqOhvZn+3>U&Rcnm z7JP$>j58*eVyP)x194-qXOnkk$0Yt;<6|X`s|4QzFWMxAT+*|QbrT|>ZPNIh)jmaw z-f9Dd@&I}e$#`r;Z|~Da$Z~-FjG8s zW^U3nQ~`gOsh$}~;Lfq86&CRIIQwOK<2$2#s!erp+LyWRgol_$2;A6#h7Vttp7f1r zIgOZVXv-`A_1lM8fGez`^m}=Ax{uTwlyydVM$k|zT18tx6-s@*rG^m zcV;&j;$E+3e|8HcuU1vnLw-bzeS=tGCTalZdNT(KY8%INXZ@+Ylz*u94#V@9vhQ~W z^<|3r(s&URvV%4Z|KK{aqVmJ|Z`)G(29-JqZD!lHajJvOjiJ9Hj08IizJ;e)8Q8FC z6(fao&=1ddFf!dl^a%-U0JV;a^-+`yY8kY(2oA04@ah{J+>hIaIFOWhAyLsheQjE% zRlVD)CV*)2n~e1;+K356&7M*4&%r(L?Gbv@UTZ({P`&MqNbbqQFd7`(Hh1>Jv&Y=A^A5JF^ACPky}x<@AujoSRwX4hXqu~!uJxu;_#;$ZFk$T{ z1#tw3(Aki)Gm}g#M5Z!As{zm8Z+{opzt(T|2QWTdp-w z6xFFuCQ5eUG&@n#QT#Vk)+aH6H1(7Ii`Ep!-g77M@Fa=~TI@k_B&xO8>~D19{R?fG zF62>An7vLBF>pJ}X{zb*a!(x@X88EJ z)j660DsQ^6d0~(Kc#Pzlo#NB$3Wku26B!6(WG*&;>_w5GxMgvYpC&JLPuBp08A`-{pB|L@$JgW+ zum6ef;dBvjuFM6L)dSzM^ewC--XD2?Vil?8NmS_Ra=eGaOR@B0CT3V$kZN4gioYV@ zIOvc#keC&@)5PbU$FtL;Yl>?*7v4;G+1LARi9;k_?d(gS{A?VirE2<6#X07_Z^Ofa zt*2*I>SG3=)h^b=$Y{cWjLnH9HA-RIK;{fhVLugsX1cY>6u%coQ7SJ>WI>n0r*(5ZR6;PGU zc8eH3k4)LZlJ-=q31p{1crrLNj->acHEbW5I43iwH0tJdGDVTe_Z{w~UI2ijwc*g8 zEf-IUJ1SP8i%Z6$8otS|(as%1>1Vc%F9*xGEEBSf!?Uh$anELF`Qq184{PVGv3|3BFD-Mq@=5E_1X3s<1DpAvh zd&7P)Pu;My>X;U^N_(&`?S5!7iAD1QZqXwMqFM0MiIty~`R^*MKlbifn|(OTF+CC8 zj@*D`<&WfceuuH(1FnvaQ^Mumi+Er>;$+6Bk9&0C|D=?5CU6jta%b#$Q%=#%?zN@$ zzsQK52ZOC>$onU2X-+KKQ@b4gw5i1JZwUIZ+;|fXpc-6U3bro_s^>Zq6sjk9foO$Zd(PzKeaoID4v9YnnOl(8VR=3E6^{n>FQYdnh3zu;G z7R)Gf+B?cQ-D`BIGQ-1g<-|{D7}SEn-fk!SOoeo16_tt8#V!sijH6TE#Pa7s;>N5T z5+wDGPH&37STLT9rl`L~+qur{2xTCVioDsHp)B3MpyN=2fAKGnR! zz5)U!+x3d4Jb1&AITXh5z|w1$qi*GGRv~c)020=Pv}B!n0`JcSjJY_ed1d2MwUHJVSn* zHLTW_DD8hp43MqY5l1*Oc#{QCNjz8GD-kbt&3kL0tS1_`-n;~@ohQ?3BDBMxg<$a; z3%G3kbNRKhfUmsloIA_Gc9qUqT@~AlbU?@RA;T~hK#tmN)E~4#eP6}KY--u8hAo2C z(2IUyk2f6QOs{7sh22bfufaU*yxSbX=z5tIC-B0p;QZhd9^{rvmhA?=#jLgrAPT-u zu7w(QZ|LSKzS2uG;M)x5SFYJRm9UG<6!hKwaL*#(wh4Hj*O%sivrAL*DpZYa6~!sm zQo3ShH;P|r$^1>Fv^Z@G{37$hK|oq{QtW0bQfY;<;g+%mnUtgEO1o0FIM!DM(haVi zp!i0Y?{+TRRhCXV+uX=$;RWPjzjRVL>sMw>EPlD9eg2aD3Yn;l=8u~IzE&5H#8({_ zwceU;jdt^29XZ26YLCVvqj~d>0k@K;XeZLGXs>5KMqf_Y@lr3p^rJ!w8qJp;C)MiY zP=8jYsgB8CUF^TL!MWX=g~<(qhqueYycK z2+A&k%In_4KSO&wf5|aX0zb!n)WXWV48-{r6r8xq3$s&Gh%)j7x=CJNA#r&F3a6lw z#GXE0<>|m63Ri-HQA8a8l&?=)N~hmADfrka#mMqY72jxo*l3Z@LBuW1>+}W31P(P? z$Nb!w#aAauEey1AUCa^vNz;=CcEw9NV0XUv%uI)J26|32?joXJW1sv_Jq%fG>A?eU zAW^pqY;R*Zmc#lo8yCmsVzr5cwNOMCNC^CZ3co%cVjP-|pa<-zW$!L0zgzaMd3l>@ z=ZvZPt&*}5BZ3O~r^}agKr=;9phT>O{dzY$BZuf1iwRmP02UH+m9FTf8tyw3okGjd z6OcWGON779za@eVrqd(j?@B_8hAA$u!)Yzy!2#y)!qQZnM_Z2~Jw4*KUVOf_hQrX6 zCSMPdp`S)AL+W9FT`n)t{xeyfyDvB?RTAc9dH-Ika&TokMiJVxv+fP@Hip{JN)sF$ zNm*H5_Yhs={#8&koc480caEl7p9t-d7*-HTqJ}Y?L&bERcK07%Xy_@{ef0jNUj52K z4!D(K;2f4KvgH)opk*PC2$=mbWAjs@N~iMDO*LQcj<2bZ!a6X3!AN5MVRUq$(@Wu7 zM|&kuv+_wlU8wH1EU2D6i=ue624Kl__h75R_?xi{#M}07TaBgqCm}rS18NkCDEW=v zACx4P3b(B<2#ZcIPK)$4K3N|${maVokM7|3Vb03843@O;oh&AJ7mDu*U_3?5iB`nSRfQUFMm zrI&f^98CgMWI^ld#oky|!c-R}9c4pvS$8_-)r&gZg>>+nt}({atsFD2`uep>7|nomiZJ#sw@??rF7 zwVl5m5;As6GV{Kb-$xl3L&T_i-A<|O4>8f4ph##g{bQkX~CBS z^~0qK7QW>gYOdFB^)y02h!%D?kYd#{qhBU8*{qHFH|kd+3p)-sQsw+Ei1&mhnk(mt zVifabDFiThslWJaMfy22X-18aw6GP=764eKE$yb+ z`7Tcj$=fVeM`>w{;f0?DR+HS~XZJ(87EMwXl=T(ts_~~fL=?ISi>D6l(oHQU{>#cZ zTN;D=*3`Di@k%&P3U!zB9ysaP1Cr&>Zboh8-J53Tu|#$M=*>4fW!YaW)6dL7x1#i7 zBz)|#3h;n)>E!88oOo;Y8d~zu<631TY%Cyd;_K+t>e$nH*r+(A4nqGvR3q<6@M-Tt z`z#FivB2sdw7AOM`-!K$ua)OOM=LaGR*FtMUw`Fw&*}A1eXqJ$=D`}dG6>eJ;lCd6 zirJUO=txD;ph!@Q)7-v%qkDL|I~N2Srb+)X^ZrYfg*kqdvw{+RQnr+$`<7*aqBJ#$ zcPXKuR&KW9fs}}-GmM2e8!H-rqlOq28Iz6LiVe1_4b0kd8_l?8&cOi`XyRl5PTGwv z2)Hb#L?^-)m~rE!4z2?{*>=1EblL9nEHF7axs%cesnR*p%GlW0Hlz@h{uMocBI4sW zp*AhIEOYBfXt;W!Ez^InVFR*jA$c#)#`Z+NWRy#0oJKxo0=*f?>L?l|6|z}OE(sJ9 zU8+-zL^AyowSmCYBQSHOl%1@Ih&!O5)m;9XHW56IT+A}08Rx_X?#W+q7+SOuFyHcd zxz6ncdiwpYy`EgSjOjvsX;+j(Z)#AkA00w&9=BZ8V^Hyg4Co)I`>ouGmN@2h)8-eC&5dL6ondr_&WU3lI|yy!F4ZRxoG>mQjR2A zq#*(W^2vcWIDobA;`;vjTZ4Bk=wM$AzF$1k!h_c7pEYIbc89iU5^VwJAkbrKme%8z z>ec0FXLb4G*)B5{Kqx}O;0gpwKH?6n7HOPzcPsB5F*IP=DWM!w?9E++!e_Z^%7Xeq z!NI*#3yo;Ty?ZN9n`v)E&b&YVPaAv#ZpA2|D@x7XxH%pCJjz6juAxP&*9zp&Omqb~ zqvw&=uMIiKSihSaOdP^Zp&Gl|pUcOng4W$2!91n?3kj4rZoqNFko7z~l-AJq*W_SD zetLnA27r;v=_*&sAe6u)n-kB)>$Ly{SV+lv&N>YXC{8hB85!`a?^VpBpg>WMCf!f>QKhBL zjNAHu!vj!%H>y_9JFIX0hy|JexmG7ldey~Rnv}O)ZduXvp($RhRiKCD;MRq_9=0+5 zl$O<+5PsjID$R3b@guu>hG9kXUY0MjEDT4Y-X`Vu^`0&JVQnMt7q|4`5Io_+vbVzN zW@zX-foLmL!^wuz_2g(h_Mi<7rSwigCOA^QrGjfp^x6S+v8CQo_HUsT^u|JIokY+J ztI>OJ^%F5ZfbvN>urx;>dlrO(Dy@+q;eVqW+L*dmr|tnP?Z9lzNc>TXkayzW>q~LS zN-pIb+S!!jOZryX9qc4}UhE#|KM^r6b_H~Kh);SvXe8SkeTj6GK&lqfxW+`gHV`+3 zs^g+SKm_~;X^X6*%gUo6OriieBiY?+<2-i| zV>eadHSj117@BwkC~{wQ=C;6%gK(>9 z<(sDjA_#c1>a9I)a>yr4M`y0r&eC&m0F{D;t!1JT1t|9ltZJ z_4Dge@2Yh*wNt^qHsL(3$-|{LQ}c-s0ltSlOpq`nG9vyt?qU*o@S)Xvv&KAr{)?@( zYrU7x5t}e1S_y>%Y!7srR8?sG{Vl1bxaemU!%+^n{&Z`dxKOcw>KvamjHMZ@FNoL> zYeD*YAJw+v;w&m|e&))b_6R`GaGm^qv!pmoRZB~YogP?(c}1PMEHo8+ z@3FE=snBGHm%4d*#(Lq$rXOzst2OS?ST4~{t*#a2W~4w@G(;c$IAK@JC`wrt%=c=| zjHpaXLh0=(UzJ6E__y%Ris=64Df07xENI0Z`>~3n3mN`eU3nwI*I$A%88weu;v1vs zZzX|eu)Ci6PDdj^iQ~ZqKXc9PL@WkJhiS9=V4R?`0UYtBKR-_*m2`Hw~uqPq8;!1;#^c zwH;p6CH6uX7>~TNax5A(Xt%N!4Nd4vH)l&I`T2ORJM=1(C=oa<3fmbm{i7>)V`g+^ z;n3b#$QEpI(BFxMOaKB5<9unzJa}8_Da=<=)pPO<&4MFL>$VTLq|asZ5e(_v3wA!0 z6#ned5mbzsY#;jZ;hK^u-0Lp-^KFWX^BHr761HP6ARiT|YrmJChm{1R21=fPF)mzR zlj3gFhh-F8Gc5S+|BG{x;t$!&jOKHe&jgO8EcT7ZZlrg;{x@wnxE`_4rv2ngCY7cKXgIL)yKDZ5GHO$-#>t3C4zw}GP~ZAT;6ro~RMx2dSYJUapi z7p@}S?nCoDCpX`a5ma*Xy6HWB!k_cb`kTL5n0zF__5qBWq+T^twh z93>PUfp>AfZKi$$T2Iiy^Rj^yD9G7OS@cFH9`PtF@pEuL&3L?sk6xR2cpP) z5IJ^$mA1k$VwH6G=jfFOLYn7p)Om=)Ej+g$kuNgs!-rF3#K7G|HeBI0W;HhsZRjseaYc6nn0 znAadb*cbB)^zLXr&O|GvZ_a{;o!;sj;+KzjNPC3aL~s+0PaoE$d2VJxL3(B9iatXq zUN6Ui13lBTQe~+c{1Z;4jriU7A3Sf<0}6hntfH$i6NrUh->0Y*izg@dFGo8)({(fFoL=a&qMU=wtAieXzrG%t|8F4ohY0BdgC(MMQb z1PGi9b=5c?z}eWzY4&syb9#s8ot2Raw;Jw~uxkJRhpab`hVqTy$DbL4u@gecSSl^{ ziewq0RESctFDY8ADNAC;7Llb5Wf@Xb$eNw8gfiCbJ7r(TZkU-eMN zoI1}ubKkG!dR^D`Y6QeV0rR?7KXG+M&UwT4A`w+=2lPFb^?QrtyO(S~V?*x1&0x#J zCCNcJN{ekB>0I8?dxhD#>E5K!?azh(&B8)8Lh&s0l&|IAFb9;6F@8cPPhc6uFbKH3 z+S8T-S9#}e+6DxqoXDXL%uPN}(BCpoDoAoKF=@Pg)!ZVjkgXlw&+RV9IdSf*%}hhe zo1AUzjMChyxDCoRO1^m8nHqUBj!AAEu!A-^mwW78fJN{U@HzIcXD>ZQk2Dky!HFL3 zaNBR>WnP&cMt45X1@U(4TAnXMG?ltI?FfU2_3Jg_`36R(05+3a@4-zry#*o1T3fr( z!S%%AvBBt%l}5C`3z6%WtN0+PqjJnhY+Ulh6I2`9;JkxQ!hTAc4FzVCg0UJ~1dj8J zFX%nW{cvq8`fMe^t?yQRe8!UdT`#D(pHmyo_GD@0Du?bY6n%!Skgx+W0q%uQFY$P( zA}0~ns(R`oOb?6Gy^bbWpBj?#7C{9{m< z<-xM#v6p{poYYf#BV&pQs-EQ0>dDUg6)r7Z6 zNgKar*7iMVo*WFOa63KCKfbP=OLzU5E;KMnxBc>yESNDRI^6*Bc03iBfc|12!L}%> zN?@ycpwt+K`}N;Ftg#l}pMEw5*PBG`vqi%vrK5U zWcV{{9FL*TJt(=hKa=(|;M=^dE%7y($jO{;X{_Y0IC!7M3(^xW1B07pG0v(Rn~Ov7 zm2Q8SCfiUCL?)D9%{-6!iE|t%bR9|EcEa#mIv?hO%JA)MH)&%p*Igscs96V|*aNN` z2Y?i^3#-=Q(?M{4@EzEv({iNrR z%NIUBa|_=r7LgeGE4AR4clw9mxS&>`dA6T``{4H|MJnkPoK`_Rhr>4ila#Hj_ z*Bve?xG3eosKV5Rge9U_4Yo4Ija6h_Fnr7kNNVrTyt z1KNda)1`6S{v9&s9ozTtCcesE6}xsWno9Y z`;BWSc0hRVz{R=POC(^d(xKw-A#;gQ$$uH_ZU}_vg{mu2p{A zG-B;-qXThd!UOs8qpNM?%j~r8zxnWWtOM-%&nztv;)lkna!Ul1D6WC~I{g;YZh4i10hPgBDQq)9_ zWc)ub00V=wsub237+cy)i%L{ddg?1WikYG^d#6t9c`W97x29OPXT6jHmZf)ePL=PI zq6uXClesowui^EPOGc21(BAFZbw-mfK+v)$Sye}Nf$1v~z;B-=s(4=3Lddy+nZ^>B z(Xg}MSxNSFUkfpI^m+K)x9}#ZS)EbzN%i|jh5D!N4hTx!6k)}00EGPR<}ST#ikXS2 zxN}5v%|)}&?O$?IXjLk@ZN|qmd4e6$=qW zpH9Q4q+Q{qhwATPpMv>S!@%-sx&gxatY4o+`8{>+!KcH9v&?me`~=L~L?Hw#hZ*C1PDwMr zr%b~oqT4v$AXsrqGM*ZAcJI=F#CtTxAWK`9yz>Hmq6-*(2Kg1~JM=hWrOl z7(#kOrH_s)szr?0s9z~OQ9UwV{-zK_LsR2Cq>b{ZhnRB9tW>IUTq^Kqe=}6(>B4YQ z+tQVW^`8crqU}uNa;VpD#S@YVNq@&fAWJg2M@bK;BAhRP+p{g%V{k4gU3#tPk z+mr?|#&$U0e;xbk7MXZiZ!3gsa2yNQ#uu<`*P*C4eeXA1_u1pm&y!qU#Jl<15r>1x zyPS)+2?+_5SR5tx%9_^PB_fmJ>cOk~qx(L&j4|6WGuB}47Dgqp=-8ipnTY5lSOLj5+rPxT)Ek?y$T(z5|M`b%*;n zTWLy%@NW#if*d zKu4M9rM%qt<_m;A5ovYs{s7}mA%1G0BIa5s-;Bhl^)C6kIc^n)nhCD2uNPQ090+dh zk{F=ZjC?Nrs~E$hwb6W1FgmHBt05O%vMT8!)(->dlsH%3zB^qsfcA;3rakN=&0ObQ zgbnq){JKBhFDfmGk&qdB09C{LM9C+%FjikaLZKG!r%11%i3+~ghMLaz?!EK(_hfA> zeF2;sx6qtFdR-37#>^beY_+}q5}Dk|n3taBRP^$D7%M&4k2%875pc3ZVkq}_xq_ZG zY@^C+ZY4wsK_iDhhX3G;p&A;aw&B=_&^1)@1mV#4>9yyp4(CCorOHjWt0gGQMo=2~ zs3hlMoa-8ex9T+t<6UVR8}Fnxo7Y_CR_qq5v4&-Z>!jc`KDlsQ0sH856xxv;@z}jb z;=hF7AL*Lbm~mDX5- z;LQXj576e`rG$9k-RYlECecb^OKx_L$8x!KOD)RVo0S$hGvSi$EXE#Oxi%=;`BuVj zixlxe``y>qvd*!{#h9xt4)F!S2l)^QNIWF$?B(aDt}ZWci#;FXtuJycUio?+QuImg zrLLpj-OUSbS%1yW&Rz!V#%8tKh_8U{xiVL9)zP&RzpZx|Fds0De4p#uR&b-DVLMiFN8lNY3sR*gU;SEMUeTMHWjQ zW2sqS^a3%uo+o+!M))9fsEXZ~shFz-NP7_#0RNnj+h3*i98x(G8F6@ne=aIABXq+) z!r4XOr_8nD1=~nsNGN;?^rQ2qy;sJE!5>hA3)k@vgq54Vz4o2sbKrmIlYgU_1_^69 zsXT=-hSw5S8*C{!{2kbH1XL%^A_$20b2&2kxq%d#9;?eN0=+HGk})Exh0-yBWXy5f zg(%i-dy4Fzj?R?pl8DBDh#xBEW@eERd#iqQc6J_Ag(@*X2L1$S((EYF5JEWelmXsV zt+!Z+el36*&$3is1_Upr=cVc0lZwp#SV{+hUa$<79}RNJ;$NXz-I)3t{ZtG1)>@DJ zKlSzh0A^^kYX6G0D@-6fpm$nME&A>Qn3c#A1PN9hzGQ2DjHC?f$~q@Q0Cf;_UuoOg5jPWZQ4-^`GKl&Bb&Z&&#s+W^}i#$2@yLny!F-btCOH7#OfYl%tP z(qqa*Y^yCx)zqt><2-|?g<$z3|5V)CHZL?xShza_ZM<`+Cw}4f>Cz&6xyAswF~o*~ zfm^)Y(Ga@&G#Fj%6Vb;MZw^$qv@_pCSaj#$_NT~oHRv! zcu<_1yDDp@OT5U2RfE%NEOkqIM60E0zm1>0eZ5w-KQ*^MO5B3WzMkAzOIWvkeh#GjK zoqQH;qaHaI(9noLp~`&$_O6NYC$cm42v;avJAxgxBNaPVSCozCnl= zIrX}k&o@wwPc=l3pB)`}Mn$sM8UZF>2~c=>jAQA4uxYNZ@7|(&=~tdiAv#_jy~y=J zn4rg0)>+cG;d=KG?|2`lgH^Ew4u>P{5_to62fZ`e;+kW?-zWBy^{|zb zA37s1fAZw`ubGqSNXN$grF-}we{Sny=;LfTesHf$)}q9;^@6!eMc2m0fD2}3anWxt z0uyN`6%6mY^)L8_p4{LKG~F?sytBf!Ju1~&g>(PYqCbf5g6#y#HeZBCSXaM>*@w?A zn?0L=j$hoemUI3sea5n^t66Emy)Vr#;Zjz(d%gpOdFjQ%i#Q*9lUyYbUNAXvw}Cz{`+H^Ga1jV9ks> z@6Ots8*N9u%PGMi5R!4bOR-b{%Ac5+lq3=&sp0715pxMj%Nf8X2Q`j) z)dr|UN%nJMQk_m@JqLV1+3Aq|I^{$nHj=H6MHX)tw~5I7EJaxck8%~kDO> z&fkd6+?7z0-e>Y%Ka`@tA9$Z;{1`nxIu<|)U9-k*ugyFKbPJI|u!6|V1m?2g?moq` zQM>&AOW>MEa{!WKNET{Z!jTUl>Ari5={`n9;CEGIlr;QCIrX8~Hu1(Eg&caik!76l zKwK0ZLt;E3bowJ!YA|FDRbTiL?TAF46!8?t?3&{*03MPbvKnd_!2wuQjy<4)WoPWy<$M!@lM#5gm+(ls@pt6uUn3(}4-lTmfVDw30LKHB z)%}t9^xG?kF`}8~X4@LM!wS+QF|>`Ki2QDorE4V|Ggi8uGC+Aq!va;{@7;wD!vGCZ z$z zfx31Sk-s)DV;(=ThlFK90Rx6gjv%-2f)l1h5G<13;@VrQ(?Cc@(xM7sAEcFy*$*Y zT(-RB`m<}Wv>`P5NGJsk6qo~+Uk_T1bYzfG=kOwb25b!{`Bq-|?rcP8D0>O{K4;YE z>rA0YcCYn%?k{y~4y^j0s;tiSNQ%?9g*|Jw`$4}oxjz?Q6#!m?Hl9jexZ)~pb7ZZ%<#;9H0 zI04Fwcmv_W@Hdon9+B3#jP{jXED65@12tRAZ^SnS!dOTDM(~%vK?03a+{t*%2)@;xiAra|7l1P>{&Vs5{^dqt^_6d5ro7vF#9qz1u5$Rw44uTcIb_LL z88MGx(!;T!fjSDk55Nvw63@BFVpy-IF-@omgLvc2)LAJCC(fKXqoS_9Xzw6@=+50d zOyC>cqL?cg!q?vh*&E#NmgbG`s{I%^L1dDFzk#UT>jvQU+E7MUK|7xpq-Cm?$Uh-? zzXrYr7j1iE#de~lxm8(-!IrQWcYX(Rz7sCtiHjiz5CGIV`skOHzS1bZXYKgv)RI4?!B*a@s1J|P-@~5bTh`{Ic5IK(EqmeWFPP@S6QN^5Es({;`*j?A@2Rin0g;X!ozc zVvI6{g}t$ZaBFu@4>lyE!+E^4ZR*Ou@+3th-$pGfgvpLo)~?zF{BJ^Oe9<>u&<3%KPl_eElq4X#f+JlvjS>p#=JDKZQN0^d8&j+uv?M$qI7wa)NFxrwekeS;1LQC9JOPOUsAFao$U z>F^*f^;$@H!1ST77_RqDKhp9hJpOsd$3$%cDigo3z?3~P5|1GpyGWPUajUHwxZG+0 z1uR#rPBxI!SP%k>WXg@pC;Iz_kClHfVSrv^F2-IgEOY#FU=NPtJ$-8B1uRibBdc3> z@>XphPk72{y=$6;@XlwBfqg+=vBilgXT9Cq1k;z`Nx+BRN|t+jsfJIm}!;(q4vr zegTQIQGcOaRg;Hpkhp?z)BGsq9BRHDQw#(aHIC4@73%cP$Bd4CWlb`jvyA3%MpF6mlWQ9AV(={vDG^? zrlg^c9DdcW$Uabfjgu9B)xiac%YE5O?gK(tzW4N{^Jn}w5UPWBY1v1=X|0FFG9<24O3i^`eW?FeO7@kc`0Z;0n{aZr}4s zhNd5~OsfTq;tcUYjJS*`Yz7e&tfEyR+B*9B&4_Ulz*j1s0HjzdEyZA@*sWIo^5s1* ze`aOI2IsUgJWESYfkN+L-#dvI3C46`uCJU>Mp5rqG2COGeMno%7|Rp@)fTAwW`(J+-wB&1P9K`X*5YZu;9e! zefpUhJT`H|@dL7I)a2qBV+T_ycfG=*qM~INc*DhWcWH14!jJjn%k^UJw2Nbc|3m}* zOI1>|_Lu4V*V8wR6ZZXKAv^zo{W9RH|?x%t4U*UuTM zl%Z>oi9$(tzZB`WZT<^ZyxjAgoL0K4ipA7R+-lCY5)iJf{3vu9NUG~as7}WlUiJNl zT?GEyl}4z^J;aruwc(JPInoJaLrX(DKfLW?#i*^n`Gr$HAW7JfF4Aw`CyCj6`5|Q# zoS`+2I}eXc-h5^zAS(q6>|M#KY+?Q|6b@_hK{AG2*or{=(d*E0edYh-H|n6*wtete;4#zR+;vJQFpQS;L!{n%&NSi(C8PF>P)d zVHNg8Ar1z9nj^Bnb&aRa2risQDf0R=CFsc-e;nAjfm^>J4dlX~t5@((a!kS+i@IBX z6`ERuR(S5J^J``ed0Vw7zm2&rY2R4mULFC(frvY7ZUy+6bU+fmy5#_A$o%}riwV3< zWH2%wzrN z=(EX;ITpc1k(W(TNkNcWo2M26;M`LLA`al^FSyjVAZMNGYtX**w?{}ZiAq&K!J=2J zbY#qs{tLaMii}51|A#AF@5~^byS%9?G?ANbK)7yR-km8_3@;ORit! z^cd#FI{#DEA@TV%@P9DensaXq}|Mm zj6?t3cyaP;7T06YIZF8icCKL+ppit^;ly293Aa0)=+$i60YTN*(m$O9UNsuOU6vq-j$r~8JIw(C;v9YoVZ z@F9KILP*^;-ik@AhT~cE@J0CWmcVhsw*MU4x#T>w>(Om1FQns8zJtMm@$1ZoG`85^ z=Q#tk!ND%8Lgr($fe9&bwW{{B$p9ahasSUeC!tnR?alB8UlZzm`J(qM6rnpetdOHx zf)4kKf{410{-UV*>+9ifsygI!FhCi-DmeRI<)+n5CV0Gj2j`KyoY8VSrxU|0*K2*f zG`n`Yb(JaL;gF(I&x5wx?>tnp)2e|BH&Sj=Y|0X@U4*^ss;(|U!?%lfw1n%X4q^fs^FlePXbGNi@;8{L<4@>QK%xiAC8XgP)O96%c zE3l!nYRVcN#2u4y#8Aus4FX~s8R|y43dCSmyj1zla-^D@gzHX}+h<})yQ+U&U-6ga zM=!p@p&<~HpZJ8rPvh8(yHDe;GHa?w3f#GzaKxF`T3f5@as8P7{QUK>sxK^^E`V-6 z0Jw{sLqr_B*nq)3SpY%Hs5ks5b8#&-_5Nq}`@R|U8c9l3$2BM@>Xm_AQjXdi)ARZF z@7)W-oOyVJg#>pqfWmBXdir#b^4@Du@6`Xvu7jxJ1WT)j&9a*zEKtX0;(i#MOzwFu zFbVx_hCpP|uR9+Pc<_Dm9=K+p04Q5+2Z_ryRHF@Be$J>eJsQ*O!IeAmTDChK2*Z<) zAk-b-fw$=)VX!n%w)jb>J(yEm#$Q_oNDFC1j0SL$36aBkZGVx^X@>yMdNq`sx=owfm-nM{=R;{ScCC z;-B6^J+GJ&>F|&ASse8brpRuF_{ufI3xVM0d{59=m}znQrxS~Ri8rN-ZE5AK=S~u^ zk9ta8xX4YxY64~OQ7O2`))&fhk8*>guCVL|bf9RW8{YYFIj!R^>W~{&8Oy7 z4r8d-sKn%_Itld}FtD9Uy_RqG00&b-^&o8IWw@S9Xvj?G`5Tq4vKJ-i)L~uFsq*os zm}sQ2L;bByfRHR~LbuzzLuq(9;OZH2FuX|1r(%#@TVzvsrC@7D?;hx7rnSgK^3Q(xXdX&GF#?lc+pzS_7w(FYD3NF>C? zxq|*i`>c>6>}vknflz8u7Gne%`y_hj)#Yi85>HpvwI-_cwDOca?1<#$8CYtHg1VsQR{di7ZVNhXQ!46;#;_E-$@KS#VPc+dgYXV!5TVDUSZo zGuO@5n{-@ZA@eF+R4f<+r;-VtaC$QF$h__k>jSnCdx0zJ7WBpC&Yj+25cQG7j55Fh zrU0YA=YUgr<`|;!P*yNfbh{v;(EICrzF&sGapi8{1g;CTPvPGH^lzpFUO!`&tCB*J zX(1b@(La6`w~)v4sI?U%1VViRyktvpsKOT0TBEey)!okwg4-r!wc&xz7NB`;KRtT( zZ_GJ9LZfhlTixdA1L9T$E;=&_$EgcF zu3o{t72U>K!p#!^m(I{aY1>Gn3v4BKc$(;k=X?DX@O%)P5(WYZmiU^+YYRFvR2c!$PVeoispIU zzE6C956lxAUNU^*vpD=XS-J0=7ydl)S%hkL#LW*&{Qv7q1^jxzC|D2l{aVq@A8jcF z{72lhT@wYTBuh0IK6|U|=<~duda{o@zo^;R(Mdqcw! zwV>-YzKmBmUQT~yE=J;<2VqntpkHaJFJBTNyP4;8NA1~lwa3VIMfu#;?eMNFSwXGX zgDo$n7Z)#|QdBI|B&V}6_FTXA&zW=GJ#!A=kq(?Iz?slP)LnC#3AHOxf{G@ORvzc(U-M9gJ-*%5_yNqo0XUNejBlgUuj_gIjMdm{d zdAQHJdYg*1U%D!C)&Z;Zl6h;(+{8}?e>eLp=%6={<^gw#@3>71&ZD35Cv*{0Od~Gc zOtn^VVU>q&a?^#DaX*jWnn>K)7Iqs|L2!i?ucjRQd2<+C>w$@TDghJpn<9I!1dSSK z?f)NFCI59v{D|4{v~L)HJ)iv@{gS!+sz9sn>&Z0Y$O?&|aM6dy^J&+9Jw5_?iElj2 z-F|S$Kr!U*o^RY>Ou945*cOiCdxwZJ@cE~aVm$n{@62eBX5k$nGzY z;M-Hp>@^EOMN)rZ3)gur9VyCo=+d6A@KD?ik>8~?qV4VXF}lGV&d(Ify4mjN^Jdg# z_bK1;*s!ZGF${84<5VW$q7NMjBt9?5u#$s~nwg!^7Dbc&&~OC`;)+oTD|DI~^XtaE z@vb3L8y~z4;vCO{x`JOW!mM-$?d$*1%QYBzOt?4hF6i8he=8fztq%kvdi^CcWhTFu zbf<;_CkW24kYHoZ6HD%z%JB^Q9MTuCUrt00P=ELA4zg7O&%8leJ>S2YJo}==npVo0^Q^0%0?H^lT zUq5BT2%V>m_%}iLck|a1693wcll&eXM>bf-3YgHx3e}kddwZ`>-EM5aq+N$EjHo(0^B+r@1f+J zIMdH{I;>Ob&AkUD!YYNYPA9gEe_u8os(AcyM_`R>+Iq{+kGNKp->v*sSS9iRS1w6Q zwd=^|OZgX&QF zS_k`1GjHdz*rFsZSxcEVbN1@*>+vEGEjB^7jjAgOZwPcO z_-z^)hu|;Ulddt3eH&v#)9Jy<^FhzysP~TzA+HVGW2j*NC)6md9V~5O?VA)G{ty{{iZ@=~d1DJVOuVW?ZsR!Unt@ZvUd^L#mzF4X19Gku!T6J9% zKO&&;wx2_9>9?;JZwI5EQck1@0Az}r2F}!_tu_CAYs*<{40+X+b-fUn70_kWIPi?e z-uf|E3BNR4v18!+qB!D_A)NFp)aK1Uk9<)yniUS!PoKcZ(Bxmz7)fyb2%tS-T)wCn#Cvw$7AcVN}}vK)Hrdqi^+T*Z=s3sPm38FfgfCF=O> zo>vVh@-)wF^Mg}4Wzjx8(d=ZECJA>3w0FA2lN9IEv?GvN@J{#b&WbFiz@2ZAm9nyh zSF(F_FQ6{;;10ufvQVag?VbO17zTe4G(z&N$(#`sNuSZ-|xGQEAhZYCLOk8&@@6r06w`x+(bq3qoT^APu?0~juyLDc61goA}}nlJ4|hbEw*;OZf@W< z@(Hwkm++Y1y;t+u^-lhM@t^NU6s`GGJW;++iIO;ZVm0(CR^w|%TNefeOBzCszMMUe zOz5lJRCn6Rb2P^e^>g!B_v3OD%*x?Td+VHj>hZm;!%QvZ{8g`!e*2KzrXq6|EYX$* zVPDbYnSxhc>)};s7UAEtVuotC3`p@XCr8K8+k#AuKZPy!&yv*ji#W%Y z&UryOzl4vjF;^30#XV@7jmNW_Dk+ok`9w;yOHv>?N?lh^-3Fhm`Cm10I6~tXRmlzj z#ga`MxSV)1I;N60k2d8|si^W~@5?Ts!LF!*(pMheVoj}oFkfV-!79M9##zQC5mr!) zRAcQnAzc1_bp%%3%3lAGGkDn&$R}f#WqveZbXL``tQE zOkIHrI?fhHw{924w~FvquVZWKbbu}YtZ==#aN`89dF1%-Ac!LEE>%g>tki&?2IeSi zTN!X2V>&IpLSMZ&U3befjHZ8=7WISYBJcj`jch~@ z{J~I@LAZHgwBKM8*OK;@uA=X4Y)ap;%dR+Q10fly!-BJZynhY|es6aQQLCP=K%lgg zV=QAPw_mXPy??k}Gh_>0ph+O^pqvw!4Bq!}A2V z@Rubw*41y_@43+X9CJ2VX{6F1SkuLkz1#c#xWm{sagPFQ4i*~2f-qtB z#^4Hpf16n?BN7oIF^_=`pKM{n?g{QZ(uaw$fyvx(b{~exU)z8=; zKQg8T+urfc&+9okMj#m^K*!Thp(-tK#|c266|9N=5U;3V-tfyY3Tw`?XmZvmtq`ORn*>?)6COn zjA@|hEIx=lSrr>r_gj4B_fP_XK#V*}gI^q44|0sac$iGS{?qosvG_q9`DDTDa0}K6S7Bzvo6~)dRpX9{uv(6f z^CTmak=a}O<0_v&@!BMt`v!SGhAcvLsNQ_gXQV>ch2$jLAFMlxlN_vg>LwAUDU`zI z9|jmsVxH5m1_$1ycWM6@#+3LH1kY)V|0n{l z6)Qjdv}W;4DZ{O&*N#DVW~MwivlKkL*?{FwY4=1y5GRg?I-tnq`RL=-qg4zxlM}Jl zR)NUTLkFQJA_5Uja{pZG`WG7aC^~a|`pt1QIH%U%S+inj?EullW(E>-EwwAZ<-fPVP-+FMc*LS8RA2UV0o} zaOJ-@cwSfZ8#!Hu-bY!>Y+mO+HMHUqHKLnO>sYb&dAIoV>onggHelzwcG$d=STTG< z`e=)-HcHytXq4-Hb?%esbtJi;oK$GOG;nJ7@VO%O0*ENasueEWR_#i2yplP;*Ur#*;ZJ|$A?6=O z>(iDdw2{2QKc3QOg2*GMF9f&SP^NhHJ-rOE;!ocwd`vm>8|FFlToo#@P%nnlm*ECw z=-@P0VkIk|{}t}!0r+=gW8=47Tw;Pw+u`>jkMFvZ7aL~?`IrlJwS^-`O+I>Au=QMU zjc6sDib(No5}UDR>4r`1)xYQR(FfkNJ~;JH;S&u>*9zwuxx~4#^+-P4aS*{Xpm#28 z#rlwS9S8G{%E(tViL3YL{BY(Z`{{@z1T?{nG> zRmInk)UnAiA!}MSmtW4x_FQ)M{QSJIql?Q@R(7^dNJvP;m9DP>j8&pjlfl77d+c8B z6%f!B6tJaPYkD%TRysxVP6MNd|KO%E9@jEnJ36lkY_GWMMaDUR`I^i=v&g zrE`ILJyHiu(9+#d$@JGJ@4+&naDhkW99%=1P3patIvx= zVP)S6bgjF)Tl`?7L$%Ct%+F4fo?~S@irE+D^0Kk=2ZEXLgt!j5s^0{n&!+S8E~WAp zSPXd<#9fnmwSTi60}^108N3q1*uDY$05*?00;f)N!%w|nHOEgWLSgm^H|esYUqNkf z6W$+en$enRYH@x$^S4xQk0{GQ&3(zS(hZs9CH_|x%@^++L)u-0utS4LK1fzdTDk&a ztYQ#s;vh+6&3p4hUwvK0;MZ-0tW$eneotBN14^b3dHxVgI{WJ{T>E*PhGI7% z{kOt?w`yL|1Qn-Wbu8aWLy{M^n8#qToAjc}dmgJH3)L%_NLHQc)=+fYHYN`i0MJn3 zW0o51inKP*iS0iL)Q;+u!s|k!=c+;%Uxe}dSEEPMg;I36%ma(4{lL?NQKDyAprtxp z#O_Tg>f^vxPY))0#&)rs74Lj5ksi8v4toCTX&oi3 z>r1Ny9hS+1Z`iK8h;Cqt-ruEc9=*+k**O#80rmhF>mi%MJq4WMRxSIakf|p@7Tz*C zQ6H=Vk3be}4s}l|hfY?X8-FpHj08BP#ULvm6z-+T@nG>qm0`+%^|dQMOM(+6-CZ&W z*O*Wib(I7MVoeKHIf8J9Q)@iX37_jsYv6OL5*LVfcxt5g1etdpzq^Smq3VHBCh_5D z4bI~+&w8ga_?%4QhSlxdv24e4=vvogbgs>w3Yj+;nqu}tM4d%%HhR~6hK_*7=jQ(I z&`quwTs^f& zaapFg#^}+R!eySP{;uKY@3OGs&G$+$YvgR4*ucm@&XmoWYh&$oVO3pX8nItggWx$5 ziKH9-mK6PFGdEJ!zdKeYR_601;oA-LB2*K56N$b%|eMkF}3NUEPEqrah(0!9=WeTv@)9-O~&cLPSX zYF!LT)7~}$^|8bzDZs}z9D5^K-9n%AFrC$)X5`8Usy9t{u7EVxcv*< zm`J!L}maV&0YM&)Gi1*f4_Wgzl`5y|< z;W&`Yip<~v7P{5TH1K4vG$GDaz%cD`27>touo_Wq5WuVh!^4V47@qneOf?hEmfh#d zlU!L(u>Z!|x8CP15^s5#lZ$H%6&;@=gYM5` zP~K{v?@6#4Ty6t(C(gPYs7@M*^f{t&yN?xu7121GwNhk#!FYJ%k@~t*<&&H5u0sjE za?cqL?vScy2@SzbqKHxCYiPRo8mQ_5vl{=(6MpEn;i!TKp%k4w;`!#A-*+VEFy`7M znBn1iNF00z(+B6Onb1;SDDv)n-oCcDU%)=g*qgHtc9C#5{&<%bVwHAi2d8rS0nJ6{ z+?=*eCd+G46>FmR>g0ko@XgZQop-UUtX{CHp*@9)6;p;@^EZ7}vX>9queBV4rP?yG zaM-5=e;o}z`I1d&Zs2p{e;Z?}7`dlKRxzf?SUT!6{m-_4-^Pu-YEPJ*VVC#?wX+hO z&T#e6NW8m%p>5*tgNUN_G4+EbLihOuq&3$ZU&}HPA__kHu0&^cjZ7IVrtAW~Zjw-) z6%Q-^kYMYLXf_*XH@Do-9B9_bcQpKMpaIS4#n**DOP~N93TyR~-}8{BGe)F>Oe~xI z^{dRE)RW-?M(>=`%#Zf}HE|M`<3l#c!|W`lfjW4A4mf;6^pV`@zKXQbs18Pzh$7jL z2aoxG2_V+$@h0%Wcm8wmsr#?985yA_IvGk{hkF^Sf_*RV9%wyPe+4xNtj>!VhSURr zE|5&Q%mQtt66F}7pDRHN_1#V^rPSk<^k?5Vd|kLo7)n*0GJW*R{HJqofYNG_2X; zvbEIXZSQ+m(-=)-V0o{@t_^2bhXhadfaUI0;(@jB^+-I&kGHBBX1Smw*pnid$gfU_Adsg8$NbxN)4AQ4hjy+MmH@t4nuz*!XK081ExHOLGhy8ebR~z9Cx{}}=Go`MZD9UX ze&+K*a2rXY5Tyi~!wGd#9tpPH{UUzs`yel6ieIUozodZj7sVmE{mTOWYeF6 zRTZCWhmT2i0+;}7S^l4&vXnWyJNq@5!_!P-K#_4{Ctm#3%iExz;!_V( z3!RO9nwf56WhF;UG)(I|5ivBCvR3b9@dLw8Qb8`qzgG!=7ou ze9--z;B&9^SZ)g(CfQ!A;+PK%{PY%p1~JM)@DvoWIy~Pj$oON%Kny>?;tdydZrQ!x zn-9BzMqr1v9Fmkgy`ut+xrd)*J!vyb>qHae5KlDE98%w|wsJ<&W@$T$63B_a|a zo7j!xp-KEzRaM`OQw|i(!6Ab@^YZ`grB5i(LK9_ZH4QucQx8sJ5?U8oDyWAVamx!l z>RY8cvkT&r!Wq!C9<^s4t~k?nhZAu)d-;$)rJQ3F79S{;e&%~pupdn=_>A|d z`)&Nhg5-3CIPz*|!%cBB5Vdq(n|WEN`3io9F2gZMd^-LBU1|=~j$VwrE_g#(4rwh! zaYb2K8E^qBQULcMVlvV*GhLK|Xc%@Zj4fCpcTP+C!sS&BT-SFI3a|0VHv*-F(AscQ zvmPgRQQ^Ou0?Uhh=?@3cE0$YQMJ4N(SZ8rG4Dg!J;{sf2C8Y>%d)jBJOJ2_%@Ckgh zj}UL8-^i{-Wvfl_$d7Wu0jh)?d^+ z_29#Hi%^P0s5qWGliKDxK1^SOJXfJCF)YByh{=*f3HI)g)Pg023cKff$L9jQmP4_PmmYe39hwV3U z{ZHFi6<#f%))(29i*n7P=Qi4O*{I@vz4!;cbvqbEg|Tr3i>rRtJ+>y9<>Ty@2BS! z40uKMdbl279S5Hv255*z!PI;H&;HAVXBc+d#xnTQ^<^`cR+yKKI&9=f&3xK|*$;t= zYtqKkWBn{c{;jGrXexP9|C&<;tYndMt&{)I6;tdICST`DO$`a-lk$=g9HJEi{6Syv zII&!&#OHFxQ2YRmh}9|6tjwfO`~6Jp2ap3i&gUGuE%gzJlCJ~*SG|P2lTDL6w@-e2Qo7hF{=y4^_cdSY$z9Tw=w6+cR|=Mugt{=LG+u zqLkU){9t_w`F;A^4k3P66}0(-6A2n87L*WnH}=PuszKGnLrkCNu(VjjA|sPA(%3i5 zzAO=?TpH*6xASiwyMCg;UG3OSVDjs?d;^MGoOEHMj;yrd~pZd`$aE$TC8HGQ31>zOp{0zp8u(QclG&;YamtRh!H)lo%dQK z{In2)ES?k7R#goU9feRv*2M#)*%yJ>8@WvmmhxZhKQk`B9`8T!`Y--0_c1Z;A&x)5 ze&tlhj<5CWG>@Hzr!foWK(oBEVhfWZk2j-Sq|Zf3%wnc5GCkHyVS&H*8q7oFrD zNBHMnAc@ru?R=?)*gsEwRV$_}fsEhITgB1Y5G(2NE#EcfduK8WIzdU^JJ$at=V@R7 z)ao#X)HQ?32F>LDUL1Q(hFjEcZn3O+iRLkH1C}#-#do!znC*e55vx2c@cTZzR%jZ^ zyJ$>J4Fb@@Hk?kP4$ExgOxZ~nCx5r4W{<#qD%=6z&DczF59zUXB9`0`RmG1@>Di5t(qmA0B$2(N$!T5m1juU?P%oy}WxSShtdu{C=q^2ao9#+wm+I^G50N9x<( z=0-9>yWGV)eUu7yU9zC24_`i;{laa=Jv^K~d*7XJuRcC^YMBD<5ANn`0!He-f7`19 z5cyOYj1k6{uZ8e+$@nhMkMs@YTmR}0(qLf{@*^{P^V3zpyvpY{Qjl5ACprJOR}t*4 zdic}O-T2J}PBirne0lQItf@r1{7#do;6(LN?3I;}2pSv3p z2Rm=DFy0s$BuLcGb;@5XydoHKBEcx@Ile^f^0TnpTdmJ%L-Tk0>VN*cB^fFbaa*Gz zD-BES2Q=@?M2qlMZh>x~0RuFJ-SE89<6deSr@Qn#q4P(_qpzG<<@6kCjpv$YiYeXB zg$=c4VZ?;XxcE)IQ4BBjX8PUQZ^w6Yge34-vaz(VcnKT@328US?i`ghFfhnq%Cbqe z)|gWHazh|`kz4gRB9aPF1et;NzIoOKrhB)GlrHM6^!@vG$^|HEQ7En0ZSzxEsQu#5 zJIQ^*Km`{7?#C;YHm4p9V>lu7o?2DoZ29x-lK;`H@s~ZKqtw0IULP%54$a~kmxc{D zGRNgi2f@DlqJzH{ToP_L)mKx-O$MG;dXS{9yceX6(PuNAo4A`4kE z&0I-Sdj8|bkNN~4Zsr)}n#^VSMGqdQk_^&80lnuME;Zlv^hWPf;vr)hP7~UFI z2#Sovv68k3H-|xi;tpKb;TP&RF1|d|;IH|;T@&1vWtDSHTpGGo0q!-%w|HHI&d{*i zH!$?b1T+3C)B*qUWAn{V}Cq|>Vv$g2jPC5V)Gu<1;Lmj5Y zb78VEV}DiT#1HIQiS2cHy-a8=3@z?M$S2iU9DTdIW-IO&f`jT2oXQ9vU{){YdM%SI zdG!5q8CB|>5F@@f5mHuEh%OWmmq4AIhGj+w7xxmKGz^}&gR%m2vy?Zby!gG$bBx~m zV-T|&KFvYBzJ!&C`-Y`T40Z`NcVj}ipig>lTNj-oKj5PIqChDSZfjmJH#MS&Sn%o|5adOPKr69yP!7 zkg;#a@vY{P*@ok?;yoBq4tQd34&IG6Ik~UzmYeMVjwqm%tUKBbZ4z_%gd=gz+cCXI zd#!+jE@#V|*O>j={Wo3D0rA+thfe2IFiS=5P+rDyX(NoKMYdta#v{@+uh_Ph`QET7 z%nD@Czspm-ZbG+F>c?F%z1xdca%8ope>#yJuZ-UtuS1~@(%|W@RpBJ8HCQwEdd?|( zV`g)qY43rbKZ5sa9@3=60ybOurRlk5L#Iqd?3I7pzLTWe98Iz`m(1b&eV(z~`(LP>$%q#hbnm+s1evZ8QzTxwHSQ2WPYd z6;2OvL1mP7t+GOrjn6}Rh&I@a@p8-Y1H%c4Uy!QKF~#wx571*#N_gZLXKDdki_1l2 ztGko`DT!v=(mm;JWIOl^p1pe{m7kNox;uSxR2ylqUCWysWLWwoHF}_Fq8q84iRjA{?_n z8A?3`BB%JT;jX0V1O`~B7WkD$TR39;w^Jr?_dLB4{68LIy9aXv-=j*ZoRY;JRiUMG zNLKud0`joqNFT5#Ce3hUDI1l;vW*~oIV(R88;siVwF^8dI(P)F(U$R{J4!|!0*-9q zI3Xb@-ozevM81E$Md-ic2>|sR01&2>%A7UoKE(K6!EUASoILKc*jTh9%-BVPvhZ&{FkTXro8Er+ z@VV1}89LP*>0(9oRqiZazX1-|V@%~%3%JMVXU+F{;lcW}OH`>f>bmXXu>kzx+f0o~ zgC|OS&Lp$4xN1Bd6qqcXxb}Eg)%8*eOAC#`HN1Fvwps~_PTk9vsooI7Hr7#u_XR#X zW40|D1eO(QlxBWDmvi40bfNzPO&U|NT}#4SAw~0b^SJ)G#qHR2m<9~@zC{N@@)}ny zsWpQtjl9oavFMAq+^Lr@frn47!LuMN;}dgNVRHoWo!@K|r*Hc2x7d#_bck1nTJ2BM zY!kIj_468uAst_W`Zul{o)dm15jn|m8ZQtDbLa&^%)wq4{>8?LsqE9Pn=vC%x2Uc^ zrZkGTElalffI={0LfB?UeOmy~I^SNaCN~APDxUwbHxY7#-ELo*#7VbW)YSii3&l5w znfbrCEn(iJ4=yF-`dQHu@!VfWz<0iHgxA8<%>HD+_VyQ0dN=1TRz4A`)lb_=SOYNn zUDLH=V^J}KqLh6o+@87ItnlQB2ZN5>Wsm>sIII=J>^Jj>^mW6RJ_L8aQ&0`KoeHlf z?gDWB0nm5$h4wv&pCU4^e@zS(GpU})pdFaiy$cE_>;}Q@RN#@Gg=@x8@zJ9Ej)jZv zynhJd+pe%xcWm$N>(+&gZvZwTx-ot;xK&^e$c5;0FHCYnipvNGT{~nj_?DJ2HH?~ zonYU);|rSR#=ykWXNI5VVYAb4<3v~85yp`y9R*2W$o|bv4ZI42{)|~c33NR798~E1on`=^5;fC8Qd#Ni6WQFZEcy} zfc6OPT*bt=)G2H$uDIllH#q(7#ycdiuW^XsGzyifVWv4KKvydrtah*Eaet*D-6BK| zZ@BfC5g*P4-PJMq-w_TwB}EFytsQ^CWPb$^bPe+`DNSOF)=GjW=DFUP2OozvBWbHv@8-SF4_5ii?X29Pe*A z!f&jslKgEd+t*Y8(ZY-jEtj!9?|>&~#)xG_hN!NcSGm56QU335>=gcvyl_Mh(5+P~ zJ4yt^?OivTg}=}MvBYUdYB?c%j#Z9Dp6JeaXG&erqu{)@HBuC#X*j35`RJqQrrlm6 zgBkU3U0*#~sQfox62=@R64&0=#%&9Hf4>3WTE;_%4m~I>HN~ZL?JG zQsJcbLWt=+bnM32f79XqWbBFA&!<{2DBR^OqqVL!p&dz}4^q*npU@(=XLsi&zW#Zk z>dJYa7engocznAtn=`DpL^zIupH*KvBFB z#BBGrJO3K2G6QytU*_lM1EsOf77jDgL+9@Nj`ucz9 zPneGwi4ii4I0x>i=<`;eB>31jcO3!pFI^qvgcDbfr%*B0kMV9TlJVv`MlWn zlo3VSQm4KzmWPtC=!;gg>Z~RixoXJA^8SslDQkkxYovWp#q?>g+H?|ZLH$-XHt7~t zRyjzLcj6N0ROdgBn&tbi>;#8&T&UkNqQxpXZ7n|fZ-j!_!=|r5RV12Zff)OXQn%FJ z`s=N_K}N{eG78-LG~J7|novj$?feH1ZD7Q>-LAgF zbyne|`qQ{_`_Y=>zL}F_dUzv7E*$`?M+IJ{5*!v=ABj5MIJ9ZE-UBaI3H{Iq5cL_f z@h{+Z(c9a5`mLpc_M|foZ$XQ_axpMoj@GigH!y0IlM&*lj@(WhYa01(QKt2GZp4Ej zl}oRH*hO+|N4piL{+5E-sTbQ%$wAt$YcSUWfsa|KOT5=C?L~zbx6UiEqv1Q>N;d#Z+q~j<)zx1uX$?m08D@w? z1sTmKF<0^10zVlN2VeZPDtus*_PZ^z1$^kFF{SC|A|Y8$2hZ!7fib^>?QS5nRq^-OY`R~Ipkq4 zZE$r3j5tgK?$>y;?;Cu~?$OM3O_bIeF8UT%9Oy>cW@2F@#vg~bG4fj$2DrRUrdO{F z!R4;Xfv9lG*=%9m8;vlpYUX=p&xPitg->NB(8jxryccKobio{>93_ej>cT~W|3;IO zBr%3EORC9hTwnC@cNC0DKUKwl6St9*1l2dZ0sgxK&78@_yc9iezRQNoSIN+ z^RQUuQPsg)&sCCjjnN<9mq5*1CpFQ;& zj~fLxncv;Dy@}HZvG|=oy^$N9Bi!toYwd?dLJ`ZsHRK$>Le|bKAxKTe&iVbNH|C>F zeLlOz<^QB?e7wj)w0+321;#Zn7Mm zf4Gc;SW2^y$UjO2Oej<0R?-gU_JL@XrKFDGpl1(vH&+%tlCt3~k4@6|y4jBCXvm(w z@zV@J;%<7#qXxaWL&Bf-5&jFO_jW^-ATe@vPUYvG#BSbbfi(uG-58)VHQK$`tEH}@ zKIcc7C@o6?Y8nC2VlSL5$DLirnZvzYxgRr4G<@fEAC9*>UU_K=G)rt@%!p7t>CA@= z$T#rrllH4qS50-Nf|b9O&-s@16e02S8C#4`IaW@2r$n0cCw$4>``@Y%q< zx_X@N=cjp_=6~x^v-TmXrCvZ;B%@i(#Cn*mKmjA(mT4?hW9j3=oK@k|P{OI{>nwlk z9K=OQ^&wUD3BWYJufy$J?50aRe4iDN1VE0lU{waAVoJ=QJvAzE-)dHG1fj7Ws1{6y z=;duMuDvk9{lGnFGV7R@9fwC$Xjw`^ml3Os4QN=2%IL!iu%g%U*!Uu>F&xAX<2OU~ zY!TpXx@h_pgax1U>Ssoh?&1AIOIn@V{z_&aIlZIsRQ=v2D@Fm{C!F^XW*qNpKoJVKLw5oATA1p~KvP`dsTV=25wC)o1H;8VnT&&nGoTG_Ht{*%*u?wmlnDtGVTaL)6^o=EJh6o7Q&Rf;HKG>xnTM_;WyObouQ|BOeinBW~IY~7%H-cJ#Tn2IRaQkvcFC!6835ps&)K& zpI}~g>jN&v=xd)(Sms&YOfR#iUAOR@L|>#CETOdq*9Z6Q00HLI*Vm{LgDn5MGSz2~ zm7E&z94~!2S+cwr=Wf{s>XZs+_kM0o288U~Bn^yJZF^-tp?LIy1+T&w;Iu(uMffW)Y{?wdHp5MCDVc?@+C7A`iJ6bIL@K1-d*>z zdHi{*Klz2fnD-fxrxO|N<`+(O0)ZB z`cO;H+W?PUBsgphWsP79LQFq}NTDvFr08sj#QR`1iypG!{9D*%%wSAx-=j#$Gih=v zqezue9E;|?z)%neRed8urythmq)y!S&d5I;cg(`{opoCr_9il*))n6(x{YIRh7&h2 zigrMGUI~jI#>0Kmh`yBPZ+H91j-v?1wFhqp$EX9sCANSxKINKT(xv7zO^dgIRJfr5 zqrXT9<~!KeNIb2H6!Czw>GcXbsqJ?8-mSiCtV7`wFsO$xr7sLy2<7*CPA+a{Upz}| zL}q!)(!IjMUzV?=yh+JD z{0j(&OWgftAoGV@P|B+QboKv02T4>oUjl}KS@Zy^D8P&6AzUQCp7;=qBlm56d)lbs zT0zY8C^^F*VKdo*CNY$vPv@cr;UBW)`O!VN>pS#$_rEUKpfU zZnBC{7M>mn-@j+{ZD$=fqD|-Q$t*7<`EavY{vKLv%{9)1Zf5=(u)o7Y4c2hH)Y5R= z_1XoKS!j11^(U?dLB>PB{9U&fmz5lgqRRSU)RVI#zU@8=u^j5KKD7{B5{57((f>?Eykt>8Jn6SycOS9fp|}w@w!9Q=Gkrb{}p?w2ayFl@R*at zc8+}l>@&vZI0%Y8HY)7;Ue61Z86V<3;kiV8aFfYRcU}MY@jEf23_}t=+3_2&Q(PLQ z$o%6Wx)wk^QBuw!H>$f|>{8f&LcIoqG5Llh*0gG{yn5&?qQfPb28=PjKPv85RH>E(uxAWdNq~95! zoxJmXhj51shVE1sPUrs|$(7sHZ6Oe$J&NiKS$4dHcln7|B!g@I0s}fY5xn;djUGS5 zJ-GKhX+ATY+NpH#A$;e;ZkHu}_!~DuJ>BxeEvyx?jJl5-0)lguh921JArO&U*0{~# zZq5>JA}Yj)Dg7BIe^cREN0FLCjoYXqVOO5cI?Q$J$?2B1wt1_B3g^99zYYuZmQ?e?rAu@7XG1d|-4Vm+N3X}c5-t7PHW+Hyz zIOefv#KL#DHaZn&Z2@BT`(cyH9a!i9ykPEEoW=;(EoFLqIU~<_F_@VF{KzP(uIe2) zp@Z9=e;X%1SJlz}lC?L`F7G$d!JI^V@3cP0yS!2G!=;UUZ;T`gO)2KJce>yBH&Dpw z0l$HS^*j$@WDivvOv*n3+B-~%>$-+Y);3|NTChk!)TTp+&3=gh%P z!mEvj`fBt*BTv!!er5`sm{d#T_r&$_$xKl{cU*Z7t5{i#)=Naw6aCVEp*XRQB(j1b^&iksxqKa`}3LP&(jvdAn%de&4&8Cha5Y$B|vp2=udNn1A#35k{t1n6QVI z_*4gUaN-DT6N2cb$lI8Y6gkoEV%;`|@Qm04KG!iNM5w?HO)oe$L*f2U{&zmX@aZk$ zn+Z&ASOk27eVMR$Yog;vrbn>r*P)yh>!JL;-_kC|qc4NCw0n^C_>>>qja`Fve?F4@ zxS0sLqD$yisX;g}pNVR_C&i|DVs;m9+bxMIjECEKi|1>5+3<*&h=juttAC{-AV3?k zJ*Mu|iaCj^gn`GyOE6;s-)I?x39*~F?)*1QGE85iMMsN09_O}Lygh~562;DQa-EM| zFKXB!oU_z<`1*5F;zE7s^_l0}#}!?sLaKhB32#Frg?wNnv`PE6TT%VdgcENTI=BE_ z9>Xa`PW~IlazmbN!Hg9|Afc8MtdHtpVfj8vPkb*N(VOf6`Znd$$g7P{YvQLAzL+IZ zSbJfY!t7p_b-1|l<{TlCdTwZ6vI5fNEOB|>XQtu(_^*6q)@CEqBJw-elOr1%8tPYY z9{*PRsppY-3RJhMs6CN-Kr0LeTVof8fq+vO=H8dIlPSp3yo7mf^hL*3MM&3@x|lC{ zZto(zYz&DY?A_SkP-#;KFG(Z5_276{tnzp*tkMktIQ0r`Jo#lTUHj|?cIk#GLK&@T zDt2Pe`G7{kd@prRJ**eI34#KrIkj7q(m4;RIyv}Q{6|`l zodYJrky(+2uydEZCNKV+5Ch!tjpeTNhIZW_?SQoiqSkMK$v%tMScws6dInQ#Y^&)b z+(Yf}oP1~epMvF#O4u);ZA6e+7pcu7Dv@x4!n)ukY9?@jl(@QiUe<@jc`o%T{?*P$ zc07gk6D}@^Qgn9?j^9ZzFyP^4hrRA_)`Pe^uUjPl50Wg(=}im8ecU&zue;t^(fY+h zFa}f?f~;SzlA5I{28hJ4rxyR7Ra0caLpaEN(+*J0)CGkg#um74za^K>VUOq^XWR-R z9_nOqA_8(mHtlk%A2m{WU$Lz$YaZw@B(3|)pVh)iy_d^2h{r%>Ps0#?=1L_O93JA5MEt3X~7&Ur1!m|>}matcDl^OKt#8m5VUD& zj8ukC?irF6<)Ag)5pWLn8^OqJxJ>2oWGPyMPngfZ{0bt+HEb(x9B&?Oz6EBw{&_~? z?rlGguhZs1z2Wb-TE6;ruL8_U?YXp>r>+@+ww6Gwr|Q_=rsV&SE6+do{#FkT0O0R# z?@@$nsbW`N`R?Xkq6jMbDdbv9p|q*$hxq0H@3a$9oYQSfge%QL1C(w|WIqfPdNA}5 zrrWa2Oq#%jFYJt)3Z6B;t{3KK>H}C*u~B#g!6wdNUkkB9spTcTaKDX@NM5>%F#+^IE9|*hdELi#9m>K448=gu)R`=DW3`fTd#cX z#)(@CW1URS*`5E^7~qK}S{T^|e?4(a_EUF&#NF9Q18uW2(J_%JT2(3dkzzN=Jw0Gz z0JXbC7D|tSs~p&?0*2SJ%vF)hQ>ZiKT-VH-K3wH^>Al9P^a!2pt3K+%*!!ll+xD(hogFp znMv-)G*ILRS_r($VOcAWN!8aEf0>_8WtlvpQfgD|byP6(weeZ7j)lj<#A%_zL$9If z?UIcIa(8ZDq@3$?xUjA}v345I3e>tw$v|Pr0OeTkm5~GS#>h1Vg%72xDSr~V z8#2YkhzXKTHx~R^l?sJdX_(q+aY-X!IhO{pPW2p~ncDHoP z`M;P=Ib@TBbv0e?m? z&bk*=nVt3s9B|<7H}5vMD=^>*NSPoZM97FI_RLUlRfy z6{?CddyZxI*paRx2X|X6@37kYx}tS0NkA*0wtr;q&=uC-u`ukGSVv#e>IB(`m}x&! zB&^kxLt4-7rQ5pxDYYLb5V;-s@a;!41q(0?^(~>*xvTZ`^4T=uJM$#fj-MvJ@r=Wd z$7tJZj)moH4_)Z;-fUWGuWE7;HK!8ZO@FNdi4#Z-veWRMKQ2pEkgak#uZyrn#c(r1 zAGSea>25h1eoZzZ5`XS)J*FNa4{W6>L@$Wqc%7z7w|9>i76sj8#)w==IeZnh(nIx?SU10E%eNzD7Z7XNr~ z!v%=>xmJXA{67hnPXkfD5!7tG=3j@`ZBeWYC~Y`fy6XZl0lU0kpdKApTUi()#)g)u zp4{%>^up1+*YIi{8?NIdWy;qs5=h*TByq+l8-*RKvJN}4ce}*?aJ|XMxAuY18Pke2 ztGCz9QFj+qG3(Vw+GM7FD!29fSKRrvQ(HEWbHje;)5gl70lk6sZ^*T$=_2ZMhxkvD z?lEjEGfD2RKR^2I_QxhfV$8kUZ{Q11$5Lhp0k9P|H=22~I{{{Qh8Gd4ue#?jvk5}k zSjVsU&z|1k^v+HQR~;pUALD)Wbvr?XEZVT$4dYV#ct)w&yy#3BLser|wg#szU=hwzEKQ^XmQc~H)m%CrXC-{#o@8R&Uh4-c&t5=@icL4oUkE#^1W{O&ql+3Zw8&V7AYH-QND}-ncC>zlo8YXCa zG6U~E!=6}4`%LO1`yidgROQ#7xW~iGb4fo-p^!b92>sIs)UfvoytLoJz`9}!xz2i2 zfZ<2Dgk%ejCv#HiF_dhMwsI#f4NJ?5QH2@x#`Bu8XFm&EO00B(Zzw?oRE^g^F?T;3 z7ZfmM96A+TOn5T&1njP2vEL8|NCn`Yn9!@_Ei)-Fso=dFgB0n*Vit@D$E}XeXDUR~ zdp~P|N7P&9MJ+@)==SfsA+M>3u-XW1Vz-}G6?r)nt_NLe^10f?j%~jGHjC$}>I>0d z61o_VZ}g$#p+t54>m!H~YIzn^obCmL7Y0>ZEhhaDBhwn2>L+Twe(u?lL-Oj0Tvj~g z-eh%-ISsxN3xnb}>66%P{t>}X>$egLj&xS#CdcklAd0b&I@G9#z^8~l_M@qiux3+B z|056r(+vY#Ee)J#GQ+@DPJ=?ck!Z)539%<6l*PJn*=;SDa*2GX@xWC*$EsS7%{GF? z(i|r+^~HB2D84V;VH`73sHN_EaFbUR$@V&KNBb_GhZg&8W3HNi)`Gtw%_tKQdk&y< zbU~p#A+GF|lok(d1nN1S+hvit_|CWL&FW#j_PVdF-m*F8Pm-)rS=CzAKr61gKd_OS z$7oo4sPc|l`jFgIcwq$CQ*`3^6$y4dr3q`{?+$@bfXNp@wVLz)vl{c`$yj234d4 z@7EfoKl4bP_RwVC($$~GS>IeDkbl-GZ zS=V#f1szY5^tTo&%~I|(7(?XQJL?Y1vv)TYr#kol6JbTM4hh=VAEoEL5Ofs2s~U{t zunZn#l~+G3FuZ7VT{u+rm{8yzB9eagTA4rVuL--l8nsn)Y!SgB`oQ}|ISIzQj$_dJoN^6sTi^;)Q;m-uQxiA- zBz{x&VImh>SC^wCRyqlHI2PEzD6a{(9~d@c4-$}(C$8cS1murrvFTUAEm3pu5Di32 z?eh7Md|`37DDFsthV**7Og`;YdhkUf@e?;o+b(VmetGHfr)1_lgAcdo^I@SdeoX8e z%SkK~wc-21E^+4a!vv1_Dl7ei>rpy4XL&F?1NYikzg{7(w?3R^hjg&qr>YY>;<_ft zqKuh(=-2Xjs>SR@4$8<+rx8Opqah;Av%A|3k$1_+*l>F2i{`{xiOeL5 z&;yh)QsktF%;B5#=ylq4nXwx7yI+Ob`4|w@yjk(?9b3S{Wg9-N59u%CIxGEZ~a zy=k>tSkQgi?s2?jnnhKP%er!?Q}ca{Hi8@y=S5LEG>+CU+z}8$c#kP4(d8{?iR6(p z&q032?q3Q#5$0CdK7=bgok=4LNtfm^LMH~^4b<&#WXb<{c6mGH@MDywD71j*v!NBc zAfby?*>ftXo%vG^O@(CyIzAd3AVsp_;Vw95?al~KzeK)=zK!EP)f40p!86>W%L_w@ zTEpM0Y^nruM;6-uv+si0pB=}}cFYu2p{#$SFE{RnuD$TgOBoLp`}a9lR29B#lhN4L zz%n4d*wTBbeA0eIa)qBvW6*I0-&QZ4g}0?4C!hGjE|P$E7`VSe)s{hhG>(ObsdU-= zcB8gxZ_xGXQLovSg~e!ququ}n^*H8c?6ag5d*;u3&-i4f#w)aO5?3pX_)pqjMu7y6 zK3!9Nn|(+-fGQU7f}G~(Kp6b~y5aY1>#pzwv|{%6Tj|Y)w@d!P*35u)7DY2gVQV@`JaW?C+7c*KcP zJ{=u8X%0Pru8`5GH-#D}oQn|h3g~QGKC?36??g=V#|8K+*JJHp^mK^g^_YTog-_)8 zJ|0iT(u1RPZ!3&Aa><4DH?z-K zzN;wX%ILP{vJw)7JbM?OLFCntCl{)ANls!9JKqIFVvPtK@6zq|yYf0oI?aJ~1#yI-Y=-}ja_#ctobiM@7rJ<&P*K`dD!K@ij7{Ep@^!qa_q2?`d$v^8|q z{PoCtGyVpjy;q+Hf8MSeVl>w;*7BttH?~+i&z450Cd@}iuBQ&d^O$#(P9p_YN$dqZ zF=GA?!eChKo^{2NkW!j~Ga7o5(zL0(_|wmf=@#y&Ap}x#8$|Ffw{7K2%YuCBW|FPC zQs3_h`N2GF+jCM0-^l<64=TH79o#K@?a`s9MpZ0(D zTN2x`5{SMI-r#!4fp>r=*cjRNj#kMWTbk|ga2*_~ocr|7s$GeNa7?RQYF3eXEIl`~{QhjNQ!_X8X+5Ky zo7}q(Qdj0%C#vCV-@z%OiYE(4h781sWr&a8*Y}cNXzN|i zTYg`rgL(pG98vQ+P;HW06uAh`Z7InpjQX_Z4Z;p))GjMMC5K1DG+(g09mpFIV#3vO z*7>w#foP=26O@v!^Ww;hKT}iojOb@i_tHQjxg(s3E)>tXM`;&4zb$W^CpOfVI%aHl5jWhXln6M{8 z;hs{OOPC-?WK+0CF%?n{lRQG(r&kqeDcXN8xV9=oMYS2F%VyYIBfkI9*j}wA; zOpr0g0T$YcVm{X_Q&?|Y_yCGK2n(G$sd+)v{?fo;@p!LGszw>=!0Z~A5Q1qqLXY^G zOlPjm8-ArOT<|~)A|{I-eb2Kpo}h>lC`heO6S>XF6nXtRqDdKwQ@unT__bBxZ~>`& zK*U$oJ|i8)x8-KU*d(W^gXljtpcjFDk^+KGs|m*?7}y`o!A;vKGuf5W(3hLX1%GoV zW2fywH8YvA8O$H+Lz@%y2So9cBBtPEQ{QmkVS~)Cat1)kx@uQ**iwFRt<70!j4#ed z+jcEi3&^w|T~82srfZCpn0xn&p_1iE4T}-}s640+;t6N8X+EQwT!r|n5xG6$LHqa*+2rTt<&C4ML>KUabTMRbg@lyFWvYNssrBi$;ey zq9Qb}2Bd6zfzCQ(x~$~N=wc|EZcfBGWZ9OCjy;Mg4Hy$I-CVFJiC06cpkLIBLqaU) zYB$rE529>_5@4T%wZDh_1x z;d9IB)DY5HQ9!mO((V#BBH1(45W-ica-1s5=IRW)+~uf#JUXh@NGttdqpER1xZP?G zZeXchZtWN@^LW(jwW_t*Z$M69zlCN7_f@?Z`Pj7oAA{a7HwiE_FnY!9h_C@Geoj3* z@svYG*Q9m;4N*>{oIU~XvBHm!Uuzyqkhg{T2I*@fGiVaU?VVKvP<#iYt+F>?GL1}k z&agxHm0Wu-CO#8ZyvTbO8CDge=Sc3uZ_`EQ=)u6RI>MV(?Xrk8B0&5|ELLh48u`RH ze(yy}p;gG_LrI_^MayYov4`l1K9jhIVs!*ggI$45g)A!QB1CTaHTLq#ru<{4Is|ztaVM1q8iWqg6D=|$d=h)jT|(a~pWTrBaM*p$s_gCnWJKa7PkTt9Dd#{# z)nbgy-{BHM-pKCHBH=@J_=Ad1j%~+^?{~2e8FLPX-DWWXw64V+-K<1radjH+Gv=5F zE#qyjciD#c_7E?79Ao-I!wT(x#9YHtydIYQ#5f8dTEQwW^-o_r#76bHRE?0jCl>x- zrg&?N8&4nCe)GB?*L>He%5Nz&C`wjdLDLibKU4Dl3Hp6#V{^y+U@~OiwZ^a|kTv6w zCDMz(xNZOGTJdqIo6|=ib-GAfn#o`F;-m%VR@UP1H)VJ-B*8A%KJrLZhivW_$LoBM z5y8l2=1cTHq7LQP#Ty z%r~uZ^p9t+)@Nf&oPo3QTN$^^){pjo*4gz#={y4tBNXbtc~-M$in$zmFus@7d-@Sh&B{ZKOND?82b?=_srNZ;Z`DwO)H4)L(CwveIQ?; zoyZ3re`%NECmkok(8|?(}B$zXN_mgOoBeFoL=AoMTs71T0VDpvo%-z96FDYoIf)5YN9A`^J+F$#X?EafLaMUKfSY)n~4=3pu zScQMEbYQOUVS9D_l11T_#RtkVtqmQ)PsAacA&<~Y@8^q@cd8^y%SYJBa;3AF^6{>H z4_k*BwwIRz17b0I>M=cjKIepQe8k^GJ?j*?J@!f@@(>j>iy+1cHM6_Dr2eoESGVw4Y?3EziQ3R=- zBU5e?MGV0ngFMka;ciKc(m_c36MBKjW5qHV=MfOAki`Ciiy2Idu;~*6PWT)-h6&!kl5Vp%sl=Bqho-TgA3d~;bKg{|SEOA5IN->DAo z8VhC1Co8@eFS(WVlf8HcWs9(@6DPgt9ZOIc+CYJZ>_HIf0q+PqK7ahVDtf=)rB7I= z|6}XR!=Zemzn>X1jC~EsE^BsC))^!fLiTKfY}tlnU&fXSQPxt77F4oCb{S+TYm_}k z_J|4D2J=3n@9+1=`@a7?*F2Z&s`H%tKIeSS=bZc80GXHeU50BD#`jdE(Ceb%9r|9# zz!z);@DV&45Z8`Gzg($_k%4K2LaP)Tesz0pG@nlGA-9XZ?VbFz?mhPWry+PTawXaQ z1mxSA`vyyj z@*nRxP~}LZ@k0#cbUd#y2uxwuA8A7S>iZ?N@OK`??lEi7pfDeH!t>SwW1=ByG=vE1 zU!+=iKMn?5T6l@DhqbZ``V_{8IilMG-xvt8Y;l&64;PYPu^O#+r|IT;sMA zn(gM&bp7z)P8tlu<-ptpLB+iFBej@b*3I#Rx@+cevzWQT(M^wpa~25C*t|K!HKp%h zoKGlZ!C0X9H8T3p&)ipA(#ojvaP}ekpqYLr`!JlxAn;AbaS;mi{ZhV_vfzDaV9(`c z>~o<6d29Q&uDu?NP5>`Da$(@3n{D6p`;hwLt6(Q>bUmz-wNOYONV|}zo)vxo(SWYm zY|ZJ;A+W-P4mliRH%7E3DuoCHx@Loehe*N$S|8jB#eWC=a-vuKtpTZ(r~V8cyD34a46N0v z3oc(o#gSdVOIrue#GrSVV((PvAf#_Hp#8-ct?*UvB3Mf?Rf;3ll)_Z_Id z7`SCxBstY-EVE)2CzXK8HqHZ5y&eOkc%5*a0B5=5UptfBg2PU4!BBh^99ePVsCf4w zO^D7jGk=AiU;QTp@oSgB4lu+_^cauQh>UC*9uhxB_B`yos|7UC09*%U_=FWU3LAlw zgI)u+5)9PAuegifVk1&-zV?(a6{1(?8KM1IF_Z`3?rZd3%1HxKQvR*dak zB?Vv4*HlrT?moH!p;8uom?i>Ln%Y%PF1VXe3rb^$Y)(rz{8ihaI%s_~0dhzB*V;?; zQP|Jvw~eo6BQ&PM(g&^dqheQNVmA!*m2toe_hEy zu~L1!OF%7#Jw(BY=y}UDomLb-7hO9PLjKfs)DOcdXaFUEC{JE5!e6=R6M3^vpkv)# zN9fHsXcuNWV0f0S`&w^Ei4oi~kS8O8Gp+mi@l${u-KpO;;-!JkGpM>sh!Bqx#Pq$( z#Z)YmjoLTT>$6%0#JJfooY6W)AC&k>`dslk#Jci{u3@Ht`<%x5c}gdsn(9bG1hnf zHrL*LAovA5bXa~gn>fo4P~{mW9xuQJcF-iA`{hf4EgTf$0WVX0*M?baP58z;#dsaD z$`^$B34N3PsHC-EGOPJs@g*r}#N3r0Gwf%dC?-)nl>t~o|J=%#DtClLRuUd!EVpO5BHJFteVqIFF-8g~?r@hF>&6g{=PdkCcs+4T0kB=}P|*Vp9;_ zf<_G4!Ec#VV@|1D%NE zseq9o5nQ#)=SqDdY?nI^VnRJ2f}T}Ul7Ky$UvCpZpJ<{M)CWp(vl8|3rVxqKB0Uc- zq!nbI*vTA@2J=sY@G!W`?uaHtkXt4E3{Jj_n1FkaPCXIfMk}vT7-rc?6x%ixEq=LC zY3Z^}etc@z$NWhJ`SpCW1!O?KW!!?|drCP#iA%rz{?>jBO552ko%-&p>;?LX*b@Pe z3*~IO+c&Qicb-@|?SA`ubi`ap@89dwmD`)Yd*#E#-ilWuF0TfxrA-74`lRjJa8tjtR9v9==IT@ z5S2@O86AHwtb9dBO!h((l~`bNj{L=^r^a@if#G}OqK=7Ir(;lI(`=LOcb=c6t3*Jo z+rc)(o}+#yq41ic;Pdw^k2g`Kupk_tS^un_`xqNtfEvPRX7cY1JBL8#zVe+iEX%eo zpw&=@TYx-zqKaT6uQ#aWQ~VGjY;;$HkvRl(qsBOH>!{C%h;r(8LtQATPG633LZG^lR?n8SZ1}zJ?=cLg4(6X2Uk9FIZ=Qmb)pP z21vqGRIotvffIoBn2a&-c7Ec=M)aFE9M3&W6Il2_D_!!H`=)fD`hgVk4#gLD4!C(j z1A@aN9?w+p7Bq*{Cb>|P6;w8PlC2Ica;ss*OV1T)zI2|q())=Fxs6VyQ>x7jv21&B z@+iKoa$PomC*YMJWuho(D7T^Dbv>nO^!EAxO4y;a<*)d{AQI1o9;~epASea%HY`k{ z0rT>G0Tb8up*vV@7zx@!j2=MwA&xfhcQt#WeXI9%4J>C^fsyUndT-N*{1C&AyDkL` zXe$qWI!K9HHeUBF@*Q~#iq^v3tM6oDtgBr@I1ppC5Ga zcW4`B!?xbx*9YeUJCpsM*Cg%{j`EcPD<8*QXS1i=@x--X*&h`Y$>7E}lJlkHc`e-)xVyby4 zlw?2sE{};Pbmf5tG)-E5hufY;XV*9{;^{UIhMgbcg?v9(2VzAur!uaH`qP%+x1X>r zghyYny1m!;P-}z~c0iz>{DKQ;7JU$5gvFE^rlcf?E&HoHX29Y!Ynhk z-{C#~{hJ7`5u39l8Un-jYNql+3W^06ocoHL=EtH55SI7_!Sg%pLztkiTs8VvfJev; z2(E~30fvJDE{JF>={))}Eyn-c4T4fTG3d3$x^>gO9fqur0x}#TM1`19ZasN-TbqxM zXyjZ3!?)qA{fIKf^1&{3364;g$3y9PfcJ$VwjL;W-O%G?dY3K;a5*#JyUp)add2rl zzt1|PIcCeTYc~`OZC_oP$ZWYib{Og_1-+YNCS5tv4n}de1{3O%=$oGpZgEbB{di=H ztejIR)Gkj@4;=F8Kvd%TW-RB0M2uf#v|&8k|#Ma z_)Adsj)TfvJe7lxUB?U2z=|#tz_(Lv9wu0*a4N*nL{zJz)>t9zmWMnH7tu>s;AN;$ z6f$Tla{!LeQfQE{&_A~Rcq|9N6>B3-X^f9~dlhJ9(*#e4oN|6W50T$LwH6R;c9pS- zn)mq#g|jOU6{rKIzzi<{Rx({Vw~Xw`a<~A3-YXclufk!lIsYO2EUM;3vVDe`w z2h>MaXbTF|go3`l2?!A#Usd0JYaM*$A@@(7jxZL9A=iUft?~BP3*+T|)=mWtb-XGdw<8t!Z}x8t zy$FGEIq*I+1a|R3T2?uD-`-tSfbO;HUhBqUp^@A{wq`s7Xdf%KQ>yqiWf z_v9lDlGE`v&$f*vEJmfqzijL_!SSIq5uUW(==3=y|9Swsi|d$oA&UldFuf=N#ta}D z)@akNN*)c8s50M*90|A-ORR_2?nI7+7&4&`?c-u?9IQ4tR;`=#5E&79b$l+D!bVqm zdDFWa-h9Vdv90Ozwrn`sb=1b%ej1G~VP1cc&b78)JS@3$W!heRXXN-IXFFFYcvhoS zk<0$ynK*nXq8xeqI(eCPfJ3I=Ect;dO^kU|;)OUD$s!d3b!0ibAc&qHGHr8BuND8! z?`r}BD|FY|9Zvob+j-N=BCjLaCY5L6+^I6PS8ZwyG|R@vk#iKmNk1(-OIsb-$njy zl`mCbrNHc{CE^>Z#v>Ixa=qK}C~^IHHWsA$dL5_+A_*zc)i;>zi!IWcg%%>)G~*L8 zIiue|TagZO>A-XPrhydxCWzShe(H)U4}zXb^-saPGXD{Bdn*2N&}mh6`Z?2)x4~Pg zKZZ2b+dP?4MceHi46dC?@3|qi>~0`d`YucO!=$Kcn=0vJQNy$ac&Wz6en|fp9aj#l z^bIk^m82b$7{qxEVJ$(b8Ge5L{>_resyua?9%+aN|G<2r-}k9y~8 zu2IV$M#K8a)67F{>n+dP!G3qlVQ}vzQU*9p^jo<6+FVEwR(}ul1V18V-((((dWI#Z zx1^x@Y36L0XWu7RJ1G97*@N#c0oQ&+WOsYp2T@tm9aT82%Mv_V~s$@9tR7!r^`VTG>SOm)>cLA_rLf0A*!Q1N9ocfHa z+zW`LT5YCtTKPWE$(b6X^XCSa48Us|YaZXqhV|<9{DYTapJ&Inj9o}xL@h>_Up?9O zM_`0p6mCqsx~{w1$;QPa*!vEgZp3I&NYO2B1#t;7@K^lhJ}pHuwRmj*lf9nti0_8p z&!PAT0L{2pKaw~h{W~H>sxNo2bM$tKaY^3hp6qO&4Qz`rDM#AQ7SbS}K0SRTwk6QS zF6MW1Ij3xRQ=e zK2QZMkF%7;3*B6J{}&bb2J-Z=ZtGtAiu9G z?p{E}y=FM+5e!hdzKgzQ4e;KfbtBguAsLtyNXDDd?+zVTTuhvFPzY}saGkw>zc6c0 zpoq7khgEW0VDKp&eLJR%xKORa)p{+plKfOi1|~t5C~NS?fs0eKf9O_3*|Uz)&W*Ak z8rgThc5W>CHU*7m9F6yS8J>Mzgp`tHCbXRGnI`qm2oSa=(i(R)wvc2$3`0LwX# z;HZh>($wk95_$um=gk9SmV6Y1Xu<7F-x8Q#`Hm|sR6#@wi_w_dy!bc7WJXsHRmwOj zq=!|$&)A(1asI-mfLrVrWRkJ~>-4;u+$s*U;4Ad4Zb5Q!%xdfZ<>bbG?eqO35&c`J`uqq3C;pR9^wSh__*hBSB1f?Q_ax>kwi_QTOO z%=6S!hO{Och&8@0!okM3?IUFt!=ZzTcLP=@J=qKl8U6q%jc%cApx`Chi?d!B^?rk&c2XJUH@6p@oijAap#rn?Jo)X33KCR^p`^ zJO`B7jNZG*)?Cr)t(@oV!18l-j4=F;OGfXQb~gA%lm zkss_Sn_xf%szi^aVi=G_e6Yvv`Y^BegPTs(~=qvz})s@Y6ADjI9gR6WawViYimDLT&Hz>f149VSN zkJ0DC#gG$0`HZp&d#-`Nsmw6srz=iKT$qDy5|roQ=)X_CXt?_X4b-|htuK78YMe4 zC7V-Z(Jeos!fOvud)3q+2~)jb`uh2?Y`%hoxYhT@fKp5$s*?{mPs%3}+^PEp={A=V zWIPPSZYK4&UMUr<^o(=?_n>tq<*627$8^!#JEwXcVh-i_f`z^Q>cSX0NB_|6=H+w1!(ZlxIwVD42LZlgE7mTyl;r(>{M>NuM zSJ)cm?=&4MOii6r*v3cQpP=en+*58pmXUN9G?<+~uiy3_zh(;IPdcmt_`l@jKaU^l zNW@afCGhDJt}J{xb;Ss43p1fbIZa2vOeBFBaE$(iC3)f#J-`qC!-ww0)9}ut=Y7@Z zgvV9+v}fR**h!|e4X+S{0k97fL}_p%9_VPo2Gh2gytktRb~&dW&rXt}a|qurdmzwI zt%QhU=Zs}3rg-O@$rprR$Fc7=3y$H_<8xuCA~+Bqt+uB4Fma>r$&LKs3vd6KE_b2P zvQ@8mN3&FZe=f~LTih35m4{_X9>d_|0|-E>5V(ARUr7(}eILF{Q*d|VLLzyb)Qj{u zl?^fM1B@B!s3YM!FEF?g$Y>8)0Y}70Qk*8B@WZPrJs&c5EHrUtpf>%a~h|! zbKYG%CGW>*fEDq6cyC_8P8g5=y&UmkqrUXFToai}PQpx)ck)Q?M>HQNP=>#KL7)sy zeE!^3n;7NUBI#1f zA|wdMPJvH~YK!k-ncsI$kweuJf2eF1nxr!-cqGD60xQqzM1Zoo@*ricMW3X&p{%lw zjqbp_2O#D-{1`Bq@iBs2Kjia0m@i^i3)NAReZ!3vXz{y{1V})7gaKH%IgIe*`6H|x z&&tJlZQI*+V@l4Eroq?c4P}Yy*mGe|Z&|7{2%zrI`@w#@3L5R4x?y1t-aY0tMNV{5 z3*jxaBc*C3q)x%YKh-Hpl-=7gn$NLH(GnkW{3kU4eGd$H9e)4|R7M#4FmwhcKTQij z`wlKOwLkiFvzryia!x>kJctAmkejqXOU^JPn+5k8fm6o%2zXpWM-_QK3lY&_oxjI) zsGIVGiMl0@_DZc#*Hev^$dGR)76qdJj6wTdXO+u=Mafu9za2rWGkecs} zzc!>ug0H5qy46~$-))a$oGa}7if1J`S!hyPWaMmPkx(euJ0o-cqGP7xM~AE7N#kFF zqvp@IA|Kg*B)NqhT^zq19tO^gh7a0tq8uSxteCq_^zR_GUceA&1D+4kbCumY(Qvu z73@3=K2Gfj(G%IQUF)5mBq2$RQb1u_;;0%c6FUvfQaJhqnnmq_6|QFonYR*|S#;uG z07g+zSQz`U=5)|-1Pa>%Og$JYS)jYm+WkWhC%tHz7c2lV2Z(CV-~p;Y4O`VK&{N}8 z-$5m0`ZguDAi415+fwo2Iknd~R~}X48)cl|?S|pTGp>Tzlt4+eT>L{+>Ur z9{xte4`D(YCxm+n^BH)hN4?3KmcQV&nzWg6K`)L@2-$KCD<5+UB>@cZu!n5EQZg(! z+UXKULA?+^A2RNg|D6WUWvr98XwkO!SQ?VAu<8b4Bi4Y2m)ISc+=e0NpMxyc;)dapfM0?@9OvY z^hVooSyJCF8ZZFyAnlUt-r$prEMSXPz7mH1J4zt2pdkZDI+u{6{3knP-IBwiOqftN zJgNq;j;HqI__uh1l$G@N4%GXXn(&CAZ;`o++wO5~|6WjYnAnV9&Ck(b?{@qY7izTZ z5@Gplx+?E@4<1pTk5jwNo~Er`k+|W`zSI=u%^b{7{)5WIW?C7mH*MHj6isQ)m~J*$P`TpXdb?WJ^=%7~lSh}DM$(GQ|7KKG4n=T-DdJ?nhF z_HPzEJ3pkc+h>m#1_N+03+P-RcQnHVpMxj@R(lJea(`C$6uaYd8U!5mn8MsFU`XlP z;|5>Bx*cx1BoRB=U!C>7rO)4L)A(E=;s>X+bMVX4a|A{S=C5uNT1$udk)0)}l39?9 zAqRzpGsjtH5H}R%3ayKMv z__4}kD>Y@oi=PPy1<(t}0om};L11!G1HlzqqTF-hssVO+bhxRA<$+Hy_NY-5fBj7L zomRoQwmnC+$(j%3*%tyR?OS#|`=p-c&V)fX#t+vhT0_LxUjPB1eZ-ra>Bs&r0kPY2 zDk%rqpVSixV17hXi@VjGKq;W})BQ><%3kA6yeRu3=O|aybj@d8y*Yq)*0JzyuJ4!r z<-^dB@!5d7+ndh>Zqy|d$mS=U>v!$g?Rl6ZXsnifBDC-1(Jcvxtf{FQW1t=Y`k@hu zF)^qwFNurSozYQekL2}z)gwI9ZPciqetr&U_wVV ze3B+4qHZr*>uvv?#TL@Dz0opBPKx>_MPQ|B9n>jVP#nZs_`eE zkvpMu6zxKUOj1CL{?2_*=buGOvDEUU#ict9yRo~c~N01eG=l`68^9&(ODqFlJPS$Scw?+@Ew{AzLwgwU< z9Lat<$Z>PTwpFCz#}l}sn#%8QJ{)g?TOgTNuDWXR{`f7J6-SIc**JhatA}4xF_)R( zfq^aT;JDt7O)V(#%M(33>z#|{hyl=cs5U&84jiV|o#qwK(QR&^X<5+1#;)-o_FPoS z6)H$KqFyL%)UmwQ5N)!^KnF4&UE9h8WZl-5i6yENj{q^*vS*1tLnr6jsax4E+a?6Yp z^AuTfqJbD~+jBpZ{4Gqh-Gm}-xeG;$F3je=$EkfF6tWNCvmD&u*jE6Z4(=Ahq}oU#IMF@Fv7$6*}j^*@LXTE ze__rGTv-ewljy&ojgy7WkJU|{L#@5+0hw+-IXK%UG3E9byLB&}hxFGSObktKK3P8i z^=ACIZ^&r*@T0X|w&Mx=y)ae2Gt-;Tre*^^7QOxX^GGqb1G>&gZ2`Bk^ZO!q5t;AU zH94#z%X~f#ifu*8K$lLZF;VS2EKCLV8Mp~(oXOQBY^cLtW&`<^k;d*szeIv4ekrt% z{cqPD<^n+!U&zbikza;vYokox1P-;wPsN{&p+c3A^VgcPM)Ie~5MEMRfPhl|HeDAT z{-McnL@!PR-PKsl6QV7%V>KM76^`tL z3q=7C8wuk@A)VY;O=(fDz}EzRv@0h_sNm8*RVzFN9s8s_RunjdTBG&q_Z#9`p$74V zZC0Cq$t2q<;|d=`)` zXSkl`FAvKiJ z6riuW_%8wsFhR`$4o+aN{zg8VPhwLoBIbh#;R?WM7?Y>?7bc$8)N2gzK?fDFmVn6I zkQLCs_v@Cnx-RR77YIOUHW7-ZO*8B>0WulvY*VpgTW1Uawjcvqyj0=gi->Ijbzs1` zn3+s{2-iV+c54@sT`y!Dhr@5Wpz91ffA7ja1qvf-J=eZtd1Eg+LDK&2&nBz*!h^hXYpW!WRIwRina5B%D8$_ukqmHx}oP+`bD93 zOn8m!R3<0!5&SHHG8_--J3`&ko9Fbxq_}XfoTnnaS9Bn#c6?eEKm*qu2n07lCr&a8 z@p!YjZ9QR?aQmA-mUCb)znXN0KTG)7e_o-SJP<9v|F7;D%u0lWt^Gv~U!@b>`pFm* zM@nxf*RA^$e*zp9!{NM_aJ_7V(^~}q&KR3< zL`%S=Hh(_YiEX{qu!gM`_3*g=f$X_1_%be$ctA$bWPm1w^F3WxahSiOnylHAAD;Ig zSM`69eFlPQ%-@CPFkArtP?Biv5~ol(98qicB`5ZS0LPKO2^7TZ?uY$DgsfFLQ+jvZqPTwXvb;41gzxLr5URt&K(^F$<6e&gQ;{p`P`S$Wtp$ zpm1YTx=V<};_tA(jlK}<6{%y3jz@KaCO)8ua~6kzjQcF5C^lUYE`$+aAq*t7xG=RX$Uwn$rh`ZUvI@K}Qh_`( zRxFwGz(I_YX*S?}ZnVEhLgduhI@Af4erX85FuA-o;jDq@$@`@2q`?;d9Nt5qvmxg& zafd7~Gbs!nFGI@h_UFr4)vq1Lqe(x|-_%a`JHF$hh5z-;B~1M3Etzn)1^tO6t>4zAh+f@Gg3BgpB4(@kZ->+(RpJQkbyd8ydjED5M2 z(L_r@d)NqPYhafuC&huN?1lU`jP(aLAi-L-3el>7-2wX#i!etciJQoMIJ)`k%2&U; zJ3=F~dKjr=+ZTjA0f7qYR!?B!e;7~)5Q$O)J~>Q-1>Vi;JNGUjRwbYu3nwKQHVHv7 z8BMQ&(KdfeYna9-V)7M0jiJgF0&hCgXP9%*!2-vIKZ~e!3Oo6T^(RNGO2Bf29Ezns z4pi=@h2CTq2I!1VE&nSpOr9-QJMHpzrjgKGOx;-eA3YFEfu9X75=_T_Jv;^fJf?y1 zyOSikG7kI&Y7WGz2)9Qxd&m|s61{H*kiy~RjVq(z{`$g}?H zcB6^;tt0-h@!7rY^gDYQ4WWI(LCMH8vQHBLYxsT9?=KZCZRBlM-aA-{$% zJ;&1&YJa*!?5q+;(kswqFOL#-A@Kyd;xB4>isu|R?!KST1~ ztpYZ5d=3RY<_i~|z>DyH)WBY$T9X(!J-VvOfsj7Ur%g*_D{5Z@!lg&S?r3=*og_sQ zep2k87ImlO59BJXC0$AUn|4?fEy+lp^BraVaQt9i{;ln@`G3(60a@EIa)jh~#*h4w z9#itddPz$Jf1|y<{EK*<#%O52gJQ@kpTH;M-dR_6m*$FtY95pJqF?n?D7EZa%|c9n z#MMtjPPla*49E`ApC8cZC{FXttAHvqtS1jbIZn0urO8Am$Z zxMW+Hv*t%1zAn0NKKie7^e)@ZGPhG@1BT%Grvd^n%?w@p4j($8x%zI|#(&UG6%_t# zr(y7a9?KrqLxXaHVE42r<&y=L9Ip4TVG?4?MiA6{1w;qS(Q5?ZZ~A4#7Bhwx@+=Et z$3M^s=V#EnvAEeN6E||%#N*^(g%7I-6ZAC(!7PMB=DesdbnpA93zYw25VtRrJ*i=s~SNSgyF4q86DV_RkjpHAN zmV%)ns3B)x(kpx54Sw*pkcl8cQO$*m5PGj0dNDx{j6BOC1R)M!(g=GMT9+W02{gLJ zs;>z#^XGNEcFj=+6qT%@hUEfIDhi5hZl872q#M7km68(=>bA++IShH|L-K?Ppm9e5 z&p*0oOYY6MBjI<{7v1bhJe~m}P@?2=q#+Jcn#qR>mF`+V4>J&- zE;jQ7e{Hq{3^>RRMKA&K`yzg^8B8q4LFMMQR=%<8yoY3=HeP(48@*Vznb#VNH1wYd zWK)!-!McL?4S>}m>f+m#1`Vtx>QUL@R>U=u5cA>=UVVBn}-I&#TnhpE9+ z)c^}Sg0rn^q%jc=1@g#6)};KFRve8}KFw{0so+V@$}j(a*92ypED!{*5o-z)&4>9?k*r8lpc?Q=I* z@17?Y9yo9Db*EY^cH9c&b@tCNUA=Svp#I>^(wC9$<@+~#FcQ;NSF`sr%Cd)C_xGyk z|0MsZbmmj^6}luI!_}qHz9*Ccwgd9U0#Q&lDMX0;%i0)Dn5EcbK@(Q|Sk!f>iG1fe z*XuOK8Fs9eMow#Tlt25=dWZuMMkDkiJeF#K+*BY5^nkPbb*v&gGKJAvWxkTnkGZ%> zcG&%^;d{eZAmtiC^=AJiA$r(BxSL?b&bb}3iU82_(|@sl7yZ1+@azgP7w zAlk}~3G)Cf7L!<(`dMzN;$0Ya9)7G_BB#=tCQa*=kW3k^f?LR7{gavfrmWWd8W70o}6~Z)pa_O-; z|9!8V8TzIOE^LXu=c~}#cNq(lJd>stnD4jc-hg>e{pMJ8t!Km2DOW?|aJ!mA*RaLT z&nsdDJw>0J&fuCpsCkRfa&Mw-Uo%|tWCiE5iSqtw!uvgJpvKq$!A!Uz6y5d#UwYoo zDdvTl2sOITORwzv&u{u=0VZ>gMX~H6brROoV22ou6CDk9=x{`yM80psetK&+Rd_U| zhyG~(mix+K%Kua<@IOEdP4L}a_N5?dEX!R%>>tgGyQ6SiDjyIs0GiB2Uz2JuY;=p@ zr#WwXKkW*R$!nmp6E+fnY*7&b1wOb|i$8pWYQfU#H?Y zpxc9R(}T;{|JY7Scw;ukNk+^W-BclEjyf|fAOk`v%@d!-D7Gm&Jxs2+tks>-)T5bu zGq_|Dtd{xwZ{Y&`@z;?{fc&FE$1VPiKt!lnkKB{{JG~VZfZa9Y#511FD<6KI}iJQ$$R!%_18Q@JLxf6Zu<3H?J z6$fhTH$g)7c#VfyFc7tl@?T-AA5$dgYS#pmQUa;7{@6MFMO2BJlzuFfa;MLYnK#q?;6y@`eOCtsRk6*wR# zhmVXEW|1+({IzDM6>>NRdeeZ4po`DEQ@ea|^b+#+3(hacTW?hs%9HYYt=rZd+2$4{wjfakrI##X%KW@!S3_G~fEb#=e@Ws4r@}==@ed22cz;)~9I%n8@D&hk3H8XDcAJQc^@Vy^eKeMpMhZl1>!-dLyVNdAxS4yYFx?Of! z;<*3ReiB&Y#>a6&woahnc=m&!y4!+>Fov1-=FWHUi-FAO*f8o_v0=zO8*-k3R*dB1iRV8A>~LhPGU_}YA}Zi}6%CgMJ1oA& zP1DZKPAh>5;+1{vBYcmUx5*wK%v!iFzweVODCU-r60{(TwYP&_4Y4}j%_*j zY$>H*o+X-kXwq0`dqb(GD>6n~m3ng2QcfK|e4Tl!{ZHXzf*5XILMyJ$2OC!^AAv5c zQF*?&b;@lftAfeeQi$;TrA7-MU|r^o{oCv&)}v7bGK*O#Ec9(_07AO;L9>1!YYn$>{nW?&d$@Gihp0ThX}}crUemw&XsbmtIj7O&qI}lmRd)O24`9=DOnJ)^$yRGck!s z#270FoF-hUE?2J)N<(@IJ=+Ya3naugkBkgehGSYanzizg>T=bGKbZhYUPvJkK45HW zETw84(^!0RuQgrj$(t4W$G+NbLqV!dNNY*}{!FRVCi{U1D8F>x3Zy5)er#8@7x{)J zEghV@`8Lf&NLK&3GQdmYHlQRXo->BzO;|o9zZX59g4tVYk{>5)*GBA;gftJdGHA=W zPS~0 zFuUTt#in$`vXOr%9ABgn#s8>#QEXTIWre3If;5_~elkDtM%W!u2zOc$u}iNVYp)-F zyXIuga@dwj$loI;L>ZZtH|!9xxQ;GlqKku6&%dyWs-eT3^^FxFkJA2}h^v_ml5)^% zD`&t<0|ahqU3>On_AxqJEVh}c;ixgFDbmP6S?gAyQV zyz-_pYu^REyJu|MUbVgZ#8LuGCsHlW{+CotzdCqsTrO4d$^AMt(SN3(&muoHN68D##hRq~)P1Sjv+HRTI{+>qqdauE|6Td`qrS`1$-+)z*>Mccjkh(XXu)r3T^ji>vlw<|0%+FU|T%^O=sF$)ze3gP4 z!G|pAxhkJsz@OfI?i$g2fZA!3m9Tr7&~nawMv&B*rc;ok5yJM~DvBZLMNJ94)AUTM z=B#z?@9V4l^Z#|dC{b|8o$TV{zdsn>MUA78ZuK(nRiUjrpomm^?iMI#E#-q>cHuzf5in(g}zWzit!72jK1{#xQ*ToEWsQ4Hd$D9bC8Hd^U$~{9 z^|sINdOwAN52hT7@L4?P6HF2XdAj!)SOI`8|^Unu`~=iMB|b3^PodqdLX zt+$gUi4n{P!NEJKT6VyFknQ|I1Ka1r zI~ppNn9fSSE6Hnuw^7Kg~_I-4ip{m@1K?6_|1Q0!+Vz0%*{1_{B`3OaToB+7#b)IKWF1}_IdU-cf{a+%l{~nWHRVQv zWIrA!p&my(q;Zeo_?GS&HJYsD{@uWBFB6@MNqRpijDJdV&EOAj!2ani9J;GG2fNvV zwTbps$l-I|!MdypV~9MwQ9?~L-M~|Kno&<|10#-ykaI>|jL7srx!DHqM&NyY`kLo=&+mU%MLqu@j_U1C#qUUBK#K@<*v=$!6|Ii>Q-isr`T^ zD{+-&0rl&#mh5lw*t8WG}2Y7Jg-XbUR zi)O~pe*}}KV?MARLNr3CB0J+EmeXy-en{g<=9U(8F@?;ATOb$)^V@@!rodaT0Bat# z9}-}@V5BxW%H)em_jbQdAp`*jsMjz&+yo8zflz{0 z351`FSlr^n+rv?DuF%QxerbW)O31Gq0hR-LPq3QrcHYo)#z^93L2(=6TcqWY+VHD& zOuEGfY6LNKbIhzPakRcDDM^0!XVIuI%P%d76XI=6X-$7Rm&Bv)P61bR24}KXB0b_1 z^`!m}U0)s#W&gH)%^17vYxb0oHCb91w5TLhb}}d`L|Mx+V@pLS*_R=qtW(O)jD)f; z*|N;Yo}Iy9miHR>{d=D0eLwH>kAI}k%=Nv#=W?9Kah(4^6h`!!cVExKC3=1kg$^+l zW%Rau(3&a^R-5l^kzv_)h*}bx*spHLa@$wi^t?^!Mm+BJ-M3>xl&=U=H*QaK$kF&h z-@>vB5^>icremVjxljBW@rn#qoPOdMZ;~h?bxkB5!H!+~!@#m`#k2 zcK?Nmk^A4lnzYjUkq1=aL-e0?G(Nq{^SAEc(4Ok|y5v^j`YDl`Do;39(DmQdB91Sx=_sYy#63Z;~=Q8vq5OnKJDGoatd@U!1P11#GEMT$#$R8nh1YU~d-e)( zCaBh*W4}pM8`+_W1-HcYJ|^Z|+^_dc#9-Z2B7TEZQ9U6r{bxs;T=WG8AqW{3lGHEu z9UtAx%_zZeTX;vc1DiThd&@|*)+8!qwiCTLcORm66Wm`WR3#wEIBT7qy_`F3J*#wF zE>nP@vsRcm`GfhVu8*t=92?o$mu#i01SJ!AVHxLh9GAoY$l%J6v?cbSD$!%3>9y^STTlfScf$Xcd1IL;#h!%)?oRY@9mYg`k5 zJM^=B5)VQ?bh7`;;n8cW-+Bur2Q;1E*LZ3{XZ+Kz8+`*tP+Oj(-t5p~;XdlfIA z%%PtZl&b=#cvViwXsw262I4hT~htpd*+( zCy{6A>^_>t5JC$FhhlpX#C0wLXhTGSdOFj7Do?x25!ym84lT)2{!QdI^hC}s%L67i z3_A-6=o@`3^NKxVQtOG}qn59fl<_V(vV-36js|sYUNWnxh<40n|8#Dr#>y-Q_akKD zxB^qNonc(6FW;9>Gg+(?C2}HSi8X4A-@@OJ&8w8pzR%IxQzk0sh)ojk81Wekh9S>d zr=H02#aHtNuWm6*V{}-mmagX@BdA1P$}a|@ZId%mXrAwO$l-4VG_F!dRsowt3IX|@ z6M{r}KNNZ}Ubeto-^fc6|7XG!>c?$0bNOrL;g`_|h|yheb9-eKcqppr`f_=Z4^aMp zmo{Kw@QD3{?#U5ad(bP|%+1lh?z%mPZ%uGx`~o8;%F(@Lg_y55c75RVHCa#o@Kkk0 zOgC4+Kvz_I^Ohf*TPXWFA`^1~MM@!Xp&?0~_jSYUWa69Oako2MXs`R<%PPqtPw=+k z-Z&Oc4HRT=@o zfYSo)kUu9NZI&eHJdI~MM2-Pr4Ra0!974-6mqk=-Kk)t2DSV*Q62Io~=78rj`VyxR ziZ;-FmXeyfB$UuE)A7Ek4lYE7t8-E9M$uj^lHs>Tp`H;+Ywp2t!>`(MLFw^}x#Jqy zP47xpyo$|9;20dRIHgkhN!h|>9DZ>eGzv(uuC>Ydph6lb$z)ZCe(oG}4nMj5rS z?=A3;fHDHNL5Ds50rEp*r3qmTmhJsRPU-8d+5FBo`0_u+!p}yXrbTl}EuAMt3GKsd zNs*gnYKZ3FH2$n&xi8;xGR3=s_&%i$si5+21Y@6CI?RHvxGpS_?BJy+Z87D2kNCSN0TN-mms zL|l=WeeyDv>NPQ-SM-dUCH|A&9<+ZfO7yTQD^jCwi8}8NeJs6Uyim3>)?q!qXVGhJ zUp87(LHecSY42k^N~dJD{^t2FR*`P4NyVXOw;Ut*6o7k-Jv+Kd0y6r&-R~q#y3mmm z!n)Sayf80kEafTCy7egOV4^}sRM?yL%pR4%?xk<=(^nvR{Qtm$1N3b3>a`plj#hXB&RxUv&?|B?JE6b+pT!3HHJodueyF*gOhEKJHPTs z0E4j^gq?AP1$7s=0zCn^UGL2*)oi)6LYk5xo!RoSaSO~8y+AM7T)_c}Uxg^JH!ZE0 zlI>8>wp1RkpCcKpnT*(KXnYJVu2B=14^s{z`zjxdXBUf|7@$nQWtRopU)gj z9Te$CZ5KbtfrOFJ>qiI-4d?Q?Qzh;2-JcvT#q|%jsKk7-$IEw+P1F{_6X+tMgPa5b zJGTe1l(G8~#tYR}iFJpsbI!cA@G(^cwWnN(8JMvg6WJ!@p|}8+Wca zAEu}$rY*H%U{bp)LplBsNu`^L%u)*z4xvncknp+Q+Ae_KQa=f>w3-KNumi}LAK1J% zZ%2Rf(q6`dg81&#rzxo4dm%AQw1xUCEArX}l9;74#%oT@H%L#2<4d zR|oJLPbEEJtd1uU;2#g&<*$O%>7I#I7P|IH<&ze6>wLhE4 zDN714g4udYXe;2f8)e}K*3Bjh%zKXQG=%Dl=_ z`2u13&Aj{ zI>jmm&i@JMxRjcC{{g!IM8Rc+D>RJ_1rfW~_(V|Wt|)@lY_r#wz4`06u&wo6$a&3+ z`Yi73P-=P6Q_rGOPou!aLB7Y>WvJH+J_QI9|Au(+#cSllx1PBy_(F|P*zypS$Suq5 zZ7h5LarpP+VR$waE2CcD&k#?u(YFUEz13mJs#vnie>dkz7jcZiSUi}NyEeS8XrZU|M|q0+!oZf@Hn$=NN4#|e{z4; z>LZYcz3gK=RY3}aTTl$vMmQdvcw0?eFam=3o~l%R zXV-U^}@{sLij+L=SbaSypZI%Y&9ibaUY{khb& z-7ng(6@9x+xwRQc^~mP}HbHNL8*=C0h5s!jJSyi6g+-YAqaJPP5_9SFCz3e zKf`G37fth8Aaav)XuJ6H(($vk3_&!L^Lu{-=eO@eP$xeq#vjugFF10B4hu+w1C+6* zs8U(>P+w^Rv>{o@NF86Q_H6CprnVIxT_2H3^M|wljONM#NPtVW>T1CYENfNsDU~4- zejjC~k}2A^=ZFfwUXlMjs?9O>c`dJ%B-7wWqpi|lP~s#59IsTU zfYrt%dxpukx3P{p63;L@Qtz7>FmI3H&JoWXgxa@sG$7_Vy__iK3^l-2LZ8}Irbd6r zApey0`fV83UEnagNOlMj<4q&UbPZ9E>^Xv`#ul@3TSidvxotJMKL#{B$}>*K=c|L< zHz8pw=PMVOia8282bWwHf-FMD>I%ic$CY#e7}s+R_wQX=GSse;0eO(OU2pGfo_U2! zDq{_5BsP#}+2@`e11dv<_qz@Dew*|NY&$~qo|*Dv>bg`S3;Pkh2WZT1Izf9I!+#u{ z+4DT_Tsx~OhJS={@sW4p=r|b=(1mIB)^17)=BHvQ_b+Erc-_eGi1W4V9oskOE6;lK zA$OI1wKs<`kZ1gbj)z|N9y!uTAe}KcyiuGedE&zjd&s*3q@l2qK3rOS=k~kw0CA25 ze_}!OneuY;M3KW4)AF$N*(S8^qMl)%47g0aM}!cRY-(=Ewpo#QA~+NG60pT?!^zmS z5@AtW8|a;=I55!x?vAX8yUH#KXg~um`kLOP9!Q3~<8B?|g{B+g1R#Q=OYEImYPZkB zswJUtmvuv{_MatWIij}*e2Ce_SAcd>J5xxst+ns)j0gX z)_xpp^av9#@-Ik>CTl+UYXshbcH+cRitJ*@+ zEqnh4--V2j{zw0E9k&w~D92-0D$L|I@B3`>elIRK%kZ8T@jNEgsnX?cF)jN>O7H~G z-rR7A5=Zp}i9^Q$epVM&FXGk9JCaT!dJ0CUV-g7uLEr%4PoIYQqf2aLVS~@WrcRQf zJVt%{?Q#GjDA^IY=e5qSPAy1TZxsy5*h22gyF84K@(C*;cl5&}^*NWMzNZ-?-5`Bz zUwM9L3rmPOpnwT!1a`Y%hI4W zLV5nImWf03>8Utt*UhF55v2BmwyH$@CYKt)ne4Vn5bMHz_D$ba)X?UP%_#YEms?dj zij5z^$*8BP6QPd#hJ=>+I@Y=Q-kGvWeP>X9ZWgch<>z9o`A6Tte;@GG{|%!7g$`%7 z@|*%9;K^RU4Bb$940}8Z8T(&gsGo5DPKpW5yWuQA=~$ACS|WAEOPu3m?W;Bc1pUgd z?ZT|~r040Nas>yNfGd_lKh_u^_*kk?t9Ju`JF#V)!hhFR%)8baI?i~FywHetBb(@k z=gM~MVM*HPnF4}|CykE;jzwd3`s~ERD^pG98RZ{7Ls^>=o)G6bxGjMC1Wu(uC0K}C z?^ty`LuZ=&UvWd6LtOgF-&@Zt?XlNOZV7R(;m__X;18j?fNCl_w418jJ)j67@DYlT zP_+DT?D;(k7Ia{fjJm^;CnvzDDB9&(qHR+wtu%=z^hna0OGdl z3C-_Ihxt!b2r>-q25BBP)ny(lX67o}uwVQF7CS-h^i*3}l(GF^t-a;i$Eu+6FZo*E z!EC!)7VPd3)W0`&LALwF`iovmP%|Nvt1_3|KlAi$8Az-?8LViZzw-so)kXk$g%*II z_tUJ_lU=~a)1c`NLgd%XW)E$N)?5ttPYpeSSd)qX7h4e<`KI*=1-w$c?>U|Wx$fY% z^`m=;_|2LXN*f>&S$bYelG1^nBC{t_Pp0E?;Y_xZ{G1fw{&bp%7`gs?3|wc|I~X1e zT$?1sg`esorpE!QpBA#r2lpG+E23al>oI$vKl5v+xDbF~^?FpL=eN^T%9J?fj4FMg zm8}8$bJD}@;+K}^zIg`E%4u`Apakvjm5l;`ztX+OkeRu=mm8>aJ#(7n{boNVC`IuN zlvRVz{xRL$f|AG1%MVU~RwW0fIXdZm zWoafcw0A+&rFv@2Cn~&r8JJ{8jY4cHQSi!+9u=p+#HhfLR((iXBdo2;fO=n)7wphM!PX^7n(FF%KLl9mevq0#aayyi2c$R{yH*u*4#vE=pw3H zSp)|%Isr=X52{dAzu~xVYB7p);4@*J?IpL7H0Bgkob*D`e#fKkbwJ$u9JKWq=k=Cy z&wJ%aTn7?**Jq=%`+VGJZ=VY8ERyf@D$SaOnd`h}1laPiOyhO;pxKFU4;YzndhY215vxozc_*J-1x7Ahb)yN)|U!8Vp3ZD0b=Gq)X+n3HjoQ1Qc2;UpQy|N`S z`YJJv%hF62pl|>r3Yan-9aE_tc)cZlcrKh=7#c!_PUK|APW=92e<1E3q5nKEm;gt^ z4#f@jQ+!2p`5TLWn(+1g-&B7lLA+RjN+u%tN!r~}bx&5+dX`{!o|GP=Wf*Ar#FA1^ z<+Fm-Io2P+2H*19d3rlEJ+kcxK~|P7XF;6h>5&UQi%x%_1hdg6q~YQkZ>)5pp>Sx6 z^8yS?W0BZbTSS|!!S~M`wHsYkrwQ5Z&^W?1#~M@lo^BQpeo7}=bAP#Etad*JKr?4S zz?_^7Wb@*JRHe}6h_smpG4mGV2sojnaQ$&&Ui=R)hu`Uye*V<7__!!TI8ea>tUIo& zF54Ix-*sSt1FS*4NAcv7#N&3nj5}Y~tP|?@g+L584+Fzhgf2-wGEM@N991;I#O=ci zUgtBrR=4D(dz9%}#1hORYAb&-u<{Tooa>Z#ac9J7_|OhISm4{u6w}AA-~te^^@*dh zKJ5D)67^L^P4X!7Cl=F|=`LWB8FjtvUY_HSs?RR2q|`CqZzMWZsXyxN`TGx;A{(1TDeJp z?&d1q$V5y2_80I=vVqW7 zBD93=^N;tQG*sa0$W2RVPTJ-3lRPdnno}mO-nB5tvJnF9QmAycmH*rKO}Q7>c=)QH+r8gcqK!?ZXJDWtj3iWogOdBCw#^c{-Tqy{FOK`{1I=1qDG6 zA2S@j;2Z9-E}y)(DzCJ$z!7f*k=4F;m@w1^+NgDoL-vICToQU{E0#U#MAM^+5X?1& zzFQJt5H-w(mq4cc&NA2Sq0}wygejI)pdog3Z@{WXwY|3r`+h$0|-~MuV=58h; z2~6#$r%cLeJjD>q!;?FI;;d6g4%6-~=I#&1qLdhL1VLNqGkKQ=jDX-J>_rU=jkeMU zch`@Uy1#WWZzvUoQV+9mN@K3TND_UJY+FbV7w)QIfvGA+^1TVF01LJeLF3s!I0ijN zxTt3$rdA_;xNKPrM5NI`dXU;JI#s&J0Fh_ERH&fT0G`4$%Xb%&IC|{qn~7J|HQ1`- zdF5~xgpkSkZRj^@CA{?-d~gd(Ry}IBX~Kt84x5RAcao#h*8R^_DpW*ukDNN^R*KA1 z*HdPmcWiz3HrHNE7ECJ|nw{;=OLG_3%agy{67N>I+x>W-^7rS;^ zzYpCvyJv&GcrHa~iVw7jplg^Nx>O3q~sadN+ zcqLF2=M|%eF+3txXOV9>m>Iqc3xG}BpNB_&6;*`fo3gwI$pjO-T+*X~qjvnmm3%YZ ztDFQ~fV{uBaCYbl2bdp02TwX6r~xT)iohv=CIQcz`BzROK5yZ7km?3GVG> z9>w>?Mm9~kq2l@|@w{()++KCNFC38<7;z%}-L22p@iokTJlBVwcABbo(3-%q7sPIK zLTCn()?TP|s_~ClJm-S$+kDLRAMUJTh2K|;{z)F~^yJYlnO%s)a(n6HZI{70Jd=?o zzB}bAz)}2}KfLfJ3$+{0F;j7tv{Kmthf!;W+5>xt^+0FXqp84j1 z47F%E|2nU9E*G%G6t9|}c!MhwmdLQA^1HA$aTIU=d-isAdy@bmg1hi?## zM!0CsKeq8o)=*OY2a6nzwbinMGC3bvdX+LS3zm~Uo7EpI3@`f4?pOiQ=9%d$&imvcSOOdoj9Wj z{<%Kl2tW0X*S)unQhbdB;WBX>6^Q*+3!O=j`NDt|%e|F$&puCuw{l+;)-4=6vcg;MsTWRmW7j zja_^bQBoIzbKdi$9w)&9xG1tWMfR@unBF&qp?7yyKNnDH4wSxnLtrhH?PhXeiwCNQ zW9H?2R-lw`4Uaq>6YYLE!uo~J%dgSIG5EKT7N2?lSZieQvPsvc3K~pph!W?35?^h) zh7H`TY)q!CzvEvOg9aFB<7Un}pM`)+-Cx;Dy2z|%x?v6<1#zy5BdAqt?I>APD|fJ< zg>s3~u;#}xaRT(}rU`--6~c>e_krd;eQED4QP1~n^3l9LPy8w;s{ISjnf6ku5$R!a zl@SCFKztX(W@S({_AFmO%eSNF{3f!xoKvK4kSgKN)h_?M*B1vd(hh$?>vxEdIJY-i z{mMwyO=Qc(gadSzY}W(SB+oL z)fzhkV45&)HC|jKP6&W*H8sof{b%9V-)gen)iqvOKIvgzTUZ)6S~y==dKRtR8suNa z_UhZIOi0$0_P5vitg4H-7Gpq?@eD}xM7wkW_gR5Wi+gb!jZ3no zlPLV)&IWAjL}As7!Vh%cH_aGa9TWxbva%}OzW4CCjSrvO$76X<_j*GefHNJ-Q-SFl zXE`qFy*%bKk}DZOoaa%5u%UtZRx2H*koIGwIji|HFrJ<`kE_kdV^3MMPoB*Y1#jKG z=X%xzY^v;ePGzr@JKsYY`Jo*R0gxP8KX(>|DNNUx@+p`nbHBG&l0kgmYz>cmQ{Z|& z;mF7NtRwO4BNag~3xHJ#k}o{{INL3ZbO!NBE2XBS?pl%?b6?#pyHfjve4=?wCK_p@ zWAE#*`*gSAagB2DK(NN{g^>#?Z-s~QPK*m0Yt9S_f;5`^4QHVF??H-*cDSi~_o+$X zIR{VbtoBIv6{HPdhhUNzT^)G{ysusKd~@zElMS@z>VwtLU=u!f^yvN`nqbRp#DJk9 z_i||h*CEy3z~2|wqs`MD*i5NeMj(#rEpS!fsTMUmUwdNw&gw>%`n|xUBBkwe8(m8OEIg z?ro|79m2hyPsttiVtSr@FU#rGoTmGwC;rsfl22WE@5oxVZ5B6J+%=%-L1osOvNR77 z9OK&r=b(P3c^S<<<2BK%$K;hD4L_71n6r9Jt~K(>jCC8JY3eyvotwXIiePdc*! zD?#xBQU$$Lso!_$($y#S#L8Nh;r3I_fsy)3prHK|M|M=BucPJX*{7T0TeBrp6cur{HNU|IfvzkH4pde7{OmO;4Ne6?ILJY`|#@OPKjKs#c?p?y*>zeExIS8 zOTRX|@~qZ8@nO1b1W26vxjKc>EmjWKoHu2*fpSy@ajH|S*n0MtyA3qMj!0aGl;bIQ z1nU~?5*yiZP8Tw(1ZmR%@oN#DJn+>V<_GVWJKK}QKouU)Y|Kf$_8G}MMbFzk{8;4d zPqYL@{ppIN{tx6XPpkqW&l54xfRae_O07ft~(a*)5z!$Vivwx>rg%-lClp0S;m zU90TJ25>UeLK=oZ>x3wjWr$ec)KIA+WKAs@gMGoAcaomHqQSHAea)N6eGgoLRtI>+;;F&6whEem>*Ff;k>-1@gh~hZ9}3 zN?Z@pKb>oKz<%l9H69fzI)L9F7TbGFm+yzxb#ghkWC9otsno|;L^lH5-yf2Dd(}@d z)2W`@heC7C3Po=netMy#jF+=(hPkVe&PuPHGfO6O+3!TCMjjIO#`q?cm8(j|{q zjzKM<@HDQRRx!-vFF&0r9K=#*B%KgPDaU%ipJN(tUeU=;A*P zwoI1L86L3yIvud5&{a0gmnqEQ<;QS+|D^kr(Cwg?)*)heiXu^tc#}tOGeoHE8Fyc) zao|1GN$nH21wl*MeA6>ON&s1_{s#;e7uUE;KY!TTc@a7$#(CgK!HW;2vVLV{5`CMp(2KqbDP5kk2oZDl8pKxI znbt51>LLZSde)YY6gC z+oPvtMFl#g?Snijy7;P z^S6sODaNZ)gz$~OBxMJWqnqkz>;aoJ;c^lD3@GJ<%@g9n;Ps!qEd~c2S5LY;7@g&j zyEGhtzXyqLtQHWrO_e`U`Q=YwRTm+g;+ypGGrj82gf8WS+A99VmF}M7;snId1x9e8 zbn{c?q3}&?x#wdefS5^KPH?i;+umD^B=*+!cpHpdy?gwW=x5mc_i*r*;Ogo27lAZ3 z7St#=IH20s;U|{eJE;x(HYXm=*ItWD3O==n+&X1w7?Nuas|TVE?)=jU|_;61~@--hoFnX=|x}Fx?tdr|rv^?s% zwdHdex5gcO$JU-QUN(DPPH8#rbYAa_#20brOg~q*`k4x6G@v8f;)|LOqN6H&Z8D|7`Bt-ebsp# zg@}^6b+hIrV0>$Tc%l%QWSa}CLm!wUgc{4}MM_0djXFN}bKzLpu8=EnZkfC8pe?Mx zlqSj*A1M(V@iKIw3IiiG#p~=kUhV~VcSS(He1>5PKET2E3XF&HfF`W&<+3cDV6uG9 zKGuWq8l3h>b>)j?BibA0u#LZ|4hU{kDz(4c;PH!*kTlxnGw`bzQ-a$Pj`_OqH?_%) zoq(;aJj!M(NC0_U!%U^$QE5t+ekCwI+M$3TBk7}#YmLaPzf^oae3_ofpZ!-Vxw-4{ zwa6_D!%- z>AmHLUXT(Zd5h~99@*W~Y4PK+=;J1}Mrt9`cKVCa>XhLwm7D}DPai+kk?Eccbn|Z< zS~OD0)}fx%)csi?0=LIa2z;KLHYi8bZwzk$J`~$jLlMCxx3171r!;iC{$l-lb^T|k zo>SaaBe6_dUV^|S?8{YT+#rfP;anG=KNVlU+d3>wXa!?s6doh|!NmK*MG>!&UNQw$1ghk3FK@= zo?0&e?i#>#sgW^v!;%D!PU6=s>aM`nBz_lN1}7f{X&_5gTtJsSzv|B^0cKDE#8EB@ zvkKo?x>p{PR+mQQKfvfU{sWZJB?JFo5TE|fPD-vmxC}>f)gIY{R()p$fk9~&XdJBL<$1vRF9@56g=6qX1`(v<#!-rj)6FjDMuu4T4Rwi9l#vg*)hm{$I2Dx5vn{Kcz4sMG`awH-jm9)Z9Q9|`)k6X0Y_lCO)-(4-^`_M$fWEdQ_I$| zs9g}B9p!+BSdiA{7WW%lnKf>wIMJCbq-Rr%Gl~MqK#%+}XPc_wFSf1AH7Z?MY|o`{ z&cM(wiD1sVy3F&4PdMbjwc7=MvdUQ-%(%KwKD{7`j^qeKX5WX`?;&@*J4nvk=zLm6 z@DI#I9!A=vnlOrW*D575;2HS&bYP^kKa@`GO|D6F5}ocQxUXMaSd(w#-00n^bocbG z(ow&U^x?Yz5<4L%IX9FD8Zgig#p*2m$^p2L`^WfYiy_zHC*)fj@HAR{7p?Tk;E7w)eG zheYyk86y<0)KyT~;pIwir`02zFqtfRRdb}qh>V~X^k6{8N%fEvlB-pdYZz@os2UTu z9QQaZ;U`ILypxz%*0^?j7oC010RIrt-Rn$oDsi4YF4VhN}A!t?HxjBwyoStpX` zdGM(TzuF)E=5?c`MRf5MMh$k4(JQpy8R)c_jDm2hQJ*Tdcr>)q)?TUb!+o;L~!Cu?_sxFeMzO?%#zimxou#q>!A88aQO1ItD@2X(rO7 zrjL@>sC=_#qykIi8Iro;eQxsUQBQShrns+r)0CO`*>K<(J6U%v#FY+AZL7I7&p{Y| z{W0uMO)ESCKG`vKnB4T{O`}bkH_`kHRCr31LnmlH2mcP5y$RX+j(o^IRvYj#;V4lp z|MG(Kdbm zX~xRU@+%AhM6Nm2_OqeZv~qkz#NwXgAGF<(Ro+punLbW~%5cVT>K;R*i}EYCtU(89 z%oYnlr!qAl=8H6`ABxh2RNWq!pjC{{P5GuT|MC3Eg*8=BePjQw5bfSprUZ(mlQumu zwXe+}<~R4){9d`bI?sTf2Q$eFI?Ioi8XkwFHe{5(Q*qew5s)k>64g2Y3QR!4=bb!01Z<_W(;#DpxZqv&?6jsT(u?J85d7s=u*L~w`sp$CExwgumg|q z;cAC4-4kv(p_~7@2WxL){Z#;JPcPa^;nD-1(om`yF*?hogDbCON#%V=^alVJAU#E$ zwHu->F^FM1T*=)HEUaS0o>N>7V;RSWNUnBM-EkV_B*Sm;*QVeamk%07YgF$fw(B21 z%ZD)Zd)MufIy)wU_tm~Iqq-+XR^1vsix*6k={n}GNB`9^|KH|FKatn7V#kGQCED@) zAPvT2x*KDV`w^CX4De0JUp9QIztel^(}~H(kT?qquy{tPPg0X<_r^;-wCZ-G?vyn! zAH$vZY0b_(28>=tGQXCZ(Sr%!1%o*^T^S^Is;1{6%&uprX68N{nd7-Jsk>hUo?++U z51Eu0CEZ>5vD(a>vZdlez7GMS0bB1@o(pAG^sBSZRhnF8#j?Z?{q<&jd~S&b=&D?k zZ^7$R*=_A@Pd~LhXfwycfZ8Law>`~0pN{W!D`SaN!7QuI&i+#hv-dGDPCJ9VO+va(p z(Tvoh!y7fhT+36>xnu+YVVIX#yfMKsIiKt`+qy-WT<9ir(%d*CFkR?biqBue(5MNr z2LT0dxh6S$BEr`X$xYyj!a_JcbTWfR(tQnsm&Ttj8-`WA!ndAN**Foo0&}(#sO)nC_j@D(Z{jvBu)*?x)?_pdIO*nH-Z5S?HEXp`LsPZVMqr(S%5fcJK9~QJJ{3v9bOy6 zx~bRk*SiHh;fKb?X;3AjrkkTumZP+g3XD}1=yHmfS&AW2RA(&Dsm79Ji4$51Lv6O- z3CjcI-`;icY{$R&XQ;x!Ql#p2E6p7Wt#%-*;oBl-uSkf2C*5TqFr-#w&0Pv z!BB)(LM-NN?+%SW2^dx|O#=L*Y{dQtDBuHu4BZK|f0+L$@+3>cuBP>mn;8Z2Owi$P zDoql#kg$-A4d;$MngV*g;3iy=@ki#KV+GQxZd-G-`_0i`+>DIU2$mF$LrL9hJB><^ zNiG=?AuQSgseo`%_mA<11rjg5GN6Mo&JzFO^8190Z_`sy*=SdOP+H$miQ%Y^@uCR$ z>!FWjJ3P~kpt&AYc(S&89C&)}gE*ntgQFNuE?shV5BqeLmX2=XX4i!xKBgQ3QLxI<;9#H*Z0A==k}YS@upA=ta`P*eb^? zC1U~JyhK|l0Iwk<00O#Y)v0@K9<*TO*I!f{7K9#KyRc|bzM*vE(%b#kV&6cSBe6@A z;Xz1HE>kqPRx1>A|9==ZOCvJka^tAZqlV>TbNoh-`L|V3GeEG_iFb+Mf6SHZPgRVd z9Cth;_70w9F!y>V@#H?XJ^FoMB#v?sF@ahWvbwmEnHw&K+9(7GTy(Xxp%Ww!?M{?-hAJut}n_}td%rrFi-cH<{#sIB*CEIxp9m z!N}ov)nL$&HhG^ETpX-^H~lz`b@2P6RlBsk{tnub5g)nf^hVbtfvX*G$)^SfX`i0* zyvcA@ReN}z@5bZ~JA`^$O2hGz!W51#_9S1|^+&pGi3~gJ++Qugb14Par2?6>UM?JK zY}9;mM-A8RDD|UO^NAK^FSZm!^1F#4c=PaF$M3|xzw4QBu93zQjx|xbB1u3nv31aP z^T6ydLeCg1D?hNl{qb8Lq-xL2g1JBF$+e&O2&BuO(X4OaZd-7&4EDc0FVT+qG=AG% zdjlTTSRVXNDeSTg)X?Y?x0Mi7^Sz?WT+VavW2ohfP>5FNqu*j)8~!U( zL!%+3pWMJEUnkZom~KHzXJmucg&Xa}tZi*ShtpVaglyTHTozdKGOmB%Rr*GBkKyO3 zZ}*p;8PBw?y&O0W?z54cvP^V{VLu6u0NWRtM30 z+GHJly|vVZ>^O1Bglf0n;!Clc>s}^b*X?vA=ZI9E!?(qiC!BL{p|u@-nBZ}1!~k)e zJNwGtwI6l2(tV9J6(W$y!=v|(J^A{x?A4hUbc55(3n+U=Un)Pj8islaoM9NtQ;uM> zSg|-I;^>d+@7bSqP@8@7BF{=h_JVQ_j8p`oe^R6234{095)~niLv=<{RtZEy@RSAU zPDgBd0_`VYb_~m>vs~QK@(*fu8y`de$geY-Z}&g@bBU&i}7N0JWu6|p;gyD8+w(> z>e-19rj$)8%{12OAbc%-c3z8iaCP&9Qm@I)RkBN#9nnc&)-r=S+}9>fwVr5l$Cmh> zjXDo!BX>)Y`-#iPI7^qK49Cbtv2kLNyl1{Wn#?J`{K3fpk6RSdsXH;t zRwf1;<0_wsJkG~r(b+6N`mn4E(n{dU9~KY`^iJbiG@EO2)VRt=SCQ?&=&#hz@Y}xX z_DxGO0l%Fel*ucb=6LK!Z;CNfNIl;>BWQE0^aRLFMv6QI9WO|NFc4MrW%s(E$<9l5 zHJ!h}Qp^OQYDeRI3s^hMIz^`K6sIGwxNKKU2rl=S!!;rqq7 z<N0BCd>@Zo0DS90=?!@FoG-y*G@cg;g3%Id9s_OKFoN4GFR` z1U6JUc|qmN@^C?m{#%X@+E1QGCia*n%M?$yzen$rK6RtB$P3N1POStT>U-~vZXK`B ze_0@(u~^*l^Cq#s%uA!LH)RE*UCmTVIix8X)`TG2?RokWe`}(p}ozm_8 zCG`GqfcIB)D@kqB%62({#`cg)EObUnYHEQbs@N=q;|zkhH!bk<1CKYDLWZaCt}cmk zw#dH2H!fsO9PK;2YU^W^)$G~pJ!3^K%CGcr;B&b7bkuLQ?dOcAZQO~C)B!cVm@vhV z=!efmR3HTl_CK%8C@X|m2Y-w@$JityG0%mnOI}wgjBSs%wT8YOWxjFPf?CMfX!iiE$#8foPRC<9(V48eo;(mTVDEq1Luej+ zZq_V_XV=+LCBfvZ1$JQWM%>@>ZAC|+)Di#7wBDSK=sfLa9xoV3oVo>gy=hMXV!;_$ zlZ~HDANm$ssM~LO4)*;8 z(5ze`>oIB6zUro-X~r`obHVoh>x+?!X(Ll=KjD<|Vcu-Az+1o+=;1`1v*3%L?q*~e z<0U|kUI!ng4zv{9@-6wO^3bp37ZJi=+G_>&!>j*vU;fET+vPdc+iJDmssOhnKgqz? zwz6QG+C>5>k1`yDdm@B?KOLDed8KolO7&gZ?tgqgR?m{fi}2&MY$br`c~OgEeqcuU zDVHve%Mkj$KLeg_tezWe*cIdUr&9@7#bkRuf3dFlkgO%3cKJ6snxfWn&1Wxa-C}is zLGcSBDDqMq6Q=5YIBrxj%4;z={!$LtcA*fSoFB+ezoZXgK`k0u5kogo*NI zrJFW&2(deSKVM9mYUZ0Db06O?YiPL&zkL}4$aN8Z#To9JOFU@)<=|l0@JGdKPtp*f z!-M0p-`>ylyS3e`#Vi034ifbGd-_Uy3FVHqLelwpqv2PI({CCS&VL4PmQt@E_Tv9x z>aD|~YQOK{GebysNu$!OARUs@DBU0;AkwISzzotYE#07WhXO+*At{1_^w84HF!LUK zKHvBH{Rv#xaOT`Q)?Rz8lUW>XV1DsE##Y>G@SE) zVYg@YZL70xc?s#L0L;^Lv+hl9wH_t4yzvODQf}&gw z@LNf)@9)6Onf{y|>O6sTBx4{P*Y?ddR$2n-74Ah=&$k%9)cyX#3I;o4Jm?hHm#_uC zCcv#jVg?yb87apFLH!r+lJTtB%o_nWh7O5jKm^i^Pg~Exs29QB;keO;W=lG*3Dy9u zXFlbv9C3l!J~%g?X$Hj;LHCn4AApXt7z)FgNcQjhjFUYkyuS{c&#Zqy{4rucuJ5|w zfhM}8iG}&PyG+hTkX{p9kWE$uFoujv8*^Ms{))TrBEB>4r)qsfHfA7liX|eG%n-Db zFer0M(3-^EmyY>)WVbr?$`L{%gPd#zPe9a)e(kX2B9&?Sl4q5^Y0IX_?ATzSX3#?D zPjIKE5YO`iGcU#A^L2-!rlR$fSwk1I_J_zgM7P)bFrpa(-5)yG8}X3ihqb?dI{iH# z6R*LBKcyk&w~jDb{Mf-vV_D4xc7ia9bX^p=oGW6BY%~@RSzYj}->_60eIwss1S7f^ z$!0NO&oQ=4C15GeS>luzV-uYwM4cYRRkA3m!R&M=AkV!`#_u~LxGy$xSBfwbmsMS1le;v>zi%(=mv_t+{;Gkg zW(&%dM35bMXk~f1{PZS{nR%71f&QU`+)$0H8c?xto}K>j$y@^bRny=ovT2nsecnK3 z+v7Z|47N8C|5y&ZuYE=Z+QffwB@VT?p!qYBJYdi8`52xeU8twn9Q zcDe2Omk)KM64Jid2){_s9_NP`o<8#JjP2+GCCeRMY?h%qO%_(Bf&`@3pfq{1#(@`~9LN|d8#?L-Aq;%oqI6VCpZ(=X(XMHqJwTHJVZWREDZ zVCB9J?xqMPKjou}b*nO4bZ)R1CV>FZzVz|z%~3r+kbOryimnD1A^?_NxP8fw($4SJ z{X1fRa_ciTIZvL;{mVt+>}sfd7(4*L(%^XU8p{CI^N8!nIh`W6RQ6@S#Z=F9Qb5bG z+RMsJbF`Y;kpEys3Ftx7^RAJ(gCIzen4Xt{>;5HD9QD-!x1v1lk=O zG7Pdyyy*JSmBO~dAV!Da&F^wV+CriI%&_#6qkt=0uZ^=yh#`jMQ5hOr@B?Kl-@YM| zAeRU&LB2RUEeOV_<|lY#%V7b4_axN1auS#cn`}5W~5T=cjU*JfAo8atvM|d zx7FOls&xNjXCu_Xi%+eWp0W!;MRXjed(6-BG535=Gj;!XwONlP-lDOwJN) zKxUa9oYD4*UJ>|sG6sU8+dURum1PEO8u{LbR6w__IF=I2eP)~WW5QJ}SKC6D58nyQ zP+DFU?T3yZX?~U3sv|C$b7GI*N811z5Rwm*62g;f|AbU zWb^VkwFMFxYIu>th+N-`rZktt>Y;%jI0D0*gw)phmKr}B@(XGhn;w~z*>*ECJ%nBD zRquMzgd#3j6kFcPB}p{_q^9SDplf8E=BClj4pFKFe{U8TW_K0e%+e31gi* zcGUYKH%HWm=aw5jf=vMT2=BBdk|SPP5M_2@zfR4l7s>ASGz zHL`2FXwcxn%Mcw3m%YFS|h!T2tE zzUl7cC`TWon5xq37NqIlZS`1ogp;p}KR<|)r>2*iHd;LR(3P9c+q0lE&Fj0atz+lV z=J-$mC?LuH<37olnDbqM5(w+_ORd(zIOHmG7GI+~jT^}fY#(7G;{aFye2_PL;H)xp z>|13?l>8HXYm1{wX;Y7^T`&<0DT3i(sM|M>T}ul!-sw4RdFg}hoS&o6zVeQ?>iqEA zD*Y0H;w(SK0PG!c_YX+13Y|(uJ6p?7k3yDi;+8nHj!Yf{wPIzz2CTuICvhLxlEQZ0 z{x7Si;cf89ePuO;jL`z!O!v+mX#d>5vU`txE25-I0pbMI5Wq=4kuyO8jz_yU+Ny+( z3v__k>kiHli-T{<_lWrX4@vpJkE(<~=h5d)91Vf?!5D}Q8NZ*umuE*7 z3*q;n;%X#PX1{YQz16d-bbKqn7%HBb!3WdPVfBA4?-d&id7WC87`#@|QVXU$}JG_g>%t@F=PJ zW(5`tMmf^!JoOuM??w@iTse%8>In+(!4BfUizPl#!`x@sU!bRkbkaA${%gil-Y;(arv}fBu3HU5ep#Y8*W|W$ zIrHMsf3ca=TOME6+WnI_IA_)uCu8giVy}MKZIwL?J>T5#DOz42TF9>TwhrOP$A_HY z$INKncu8?iM&-WKi9pZit`y8hPs?FkE+a_VpWWuTHeZ6Byyn`N**j@U7Q>{D>xpT# zi7$nv8MU6@9}8?s*~t56KB;USB%ijV-1r=REj$wIiv2X71237vkv)C%8{8vV=zKK7 z#VS??W(|8P?t374W>YGSIDu>ijK`_QRyQ^Uk+9C&~5sW&65 zeRZou*Ko_X(OK0EiBA$$;QP?W`&LLZx)UIN0So)Jjo+v7n+f?wZJOQ~&gL)H7qT9f z_x6~vqG*&Wnp>hBbzarA5wsA=E}yFdj9uyi(QY2_42;#bV5rzGE-T1Sh+cdUEZ^5N zv-tW4u~%Cjh%&{@&@h$Y*$i*)ZgbKkQFvHN3h=e5XyUB893^+;5f%#l6mFniNK zte~13DqjRF1~VBdd*K?7-DYjX3V$HK>3W|kW+%g2=PitOrGfsN?O;xEQ_T8*MSkUl z$A3Vq{iaX>Pe<_Myz#Y4XbQD?a%SbA^RHoHGnW=_xfRCw>Y>hHL?J044&fUiUrGUd zn^R?RM^{e>@yIB#h0apZSF2zaMU!?Ig|am!#J<@Lc3V%>-L;mI|4soPYheeT><|6V z3>$M87PRM9MuEft<_7kwtEFB9y?LsK7t5(j+copMKe^b8FEMOqS90Bva=u%odi}S> zH|B01{1*~%*jTZ?nbA4uLFA+E3bfd1qG|Q{Y5y@OL=dLkv6opTz!+@@{;t1^f2)mg z{YwF$;8~%L27JW1l$=zp3a0dw0H2L@Q`?v$D!#KibN`P0)KVu?pt(a z@{TU&q*h*tYL;bc=o~rCB@}FKQ>^`*Tz1Vb*>p5N*odq=oES^UIc$hAJ51lW{HhOD z{vH(z&VyBlzYm=xJ~K{mM|HDmTT5KXF^9hIhr~)zOJ9n{09RH#9!;*Du0LkSVCO6! zNI=x{T6I=@>!eN42EW>(4x4pf#%p#1Ls@1(aOwI8AT%ndrG_ZRS6S7R9*NqUE} z>&4(%UdIX7gc)H9N@hk+#drV8DV^`$(!8wM%b|q1k9CbO{5CNq{3h=kL%(hSLe{|T z7$6zECZW0ER@(|mc3yN+RFD$WFQa=8Sgp(~^};#9q8@%1E{n%H7JbOicgOXv2jNPA zKgIQZa%;JfyB4>^r;r=#Vo!hhi!ydyE9dNKdwwDjv!_qj1cJv80VGDI0W2;*G z-#qPmxeOE2ao_m#5naPEq0{7E!S;fYntseG@#!gycoH4;sAuxz+0g3)N&$%{YJd3@s00&hvGJG`habG}qzP7q1 zUn13oqVOhp3&)3ZT!n9Qtq`lmR3N7MK3(2?3Lit@OAc0=$Hq+W!I;oJV-*7;iOR&( zbr2JX(L+dL983rJ0e$Eg3wZD5`BXIA6xxxaaj=HdidpdjVzu0pb1H@UGQ_-tbbVfpkr)MW>sAV@wrk|g(pQq9E{L=M#x>`a?OShTINo1fLe+Sle~ z*d@JSMe6>uGD?`+WRDdGDw(2#6GPAx1{y>)1@@R=#2pG60Oyj^1xH@aAl#0ErzfDw z(Tw8DgYmFhGmY5}ZI7RJgw142 zb{SUfckc0kQrD|`l?s73CpANHa>1MK)gC@KTw|FMh`$I`b6jbCkK%09C{1=UDC)o# z9MRAN$^CBs;3>4?&Jpb3mL?j}$&3jb&yZWt^{QqsMsMg!be#Sdzg{cBvHE0j!&=`} zKQARFGBYsZ)T#KGHSiDb(BNg-EMrK9FmK72tq(_SlFYC~u=<60Ij@fK_fNsqjY0v) z_esHf3Ks`feaE2aH2=xMta-I3=u;hc$oJD$GdD_K==GY1PeO=)XFe^9RBj9Q982AUrfW8_GLb@wDrv$QtrOO;M9H4Mj zVd9fXL(ZzQG1)!h%ms}F*T&>n<5v@}!|ZL8!r&}uWx6FVICFnv{yuxPE_6{)?#>A$ zcf~eFbqPHUKDJ>XoEMN(wfORNur`_!Rz9bvHz;#Gqha8|GBu#l8f+=gaDCVC+C6%q z3`T$>b7?yYdlbeq1(+IM3a{I%Zv6+ww&Ua(&)o@uYaq!>U$T%IU{V&=lC0NA?`$8r z`lIg8`upa5@5f{I(&D^6gP|}d(*nhTV)n+~T zh{dpae+`C53DZU`_(i3XeZOY0DPk$c%&c22W*P_|?LDBpXGnu3OJ`UJ^2m&VCn`W& zt~jcUDn}Q(FW#Zh$oB}+Arkw={`+3RJeA|lm3NhiMnjOR8UH`9b#pGf{mWLOGEM%5 z{zmL2WgZo8OpfO~JTJcToJD$6>RX($w}Q)$?cw#nq9dT7^eN6TE7MXDuy&7{eh8*a zybU=FR%nIv{e6+>YUSivh{{)~4dj9O)0OuJ?o+8z5M%0b_j)tvkK7YgRaVl#7FD%M z;2V}7hgevHUxY5Tu7~Yy#zHq_SyHlKIodNB172iwboCIdGJhag{~qIb2#Lw6zA0@* z7AXY=NZe$MYDYZ%0!JPpn>+OW5No)x0z{~1Fyn^eSi~!bLP#3C2|9#bc%U0ZA84n| zXPhslNFb)rSCgDzMHQPJGM|VDd4@x1uDc&wEt88nM)W)h6vqiQ!xG=_hfQra@^-Y` zq;4FL+jf9VBpd51roBj^h8@319}(K!yG1NW;S*=wi;(tb7!)Jjuk{I~#@yQA$_bBv ziTA6^ou1K359)BBh66|Av0mh$O5EPffj0S&1aj(VfB>gO2Lc!If_m8ugRN=ktB(H^ zU9(_oz*}>cPLd<*;xbN<^@cMjajNuiCCLI&& zB!CaXpE2Ms69V{yv&JU&WaT{+i!@YU*YnP{W_3~fdk4|Zl^Y0E7K{Pc-fjqU4NaI) z;yAy}&tw>rs?%IN2xtP4Y>VK%k2ODIBX^EBbb2|yir^y2%FM<>2W4U9=&)|iywz+_ zgcYtPXNazuM!;?5{s^+qqqZ%txd(4p8n9(R4E-4BR)n{%l-ljDiC($|i~t#`zZgI3 z-Tt57F|l>HganE5s5pS3AMnC^Yz3G-mR8M=-jw9o`wg1Y&O$F|hYweELqi97;LUI{PP5b`-set3> z%Mfd~(Ad3o-S$gKDv=Wy7A5Av&WT(AGv_t<-S|JHpAQkFR-IR&xA#PE3eXX9vcC=u z*xWS03>1(9CjP2%(%%Yt5cd8#ct0q0SVT?YZmSw09t92+#0 zeV!}!>Mi5XIeg2smg0I-_}rlErqyaGo7A2Rv&p#q4rk!){+#ME@K#g}r?-j`+m~(# zoU>@f(7M9#+QKl9uaJ@M@Re1oXHp#%pkj*564luo*L8XBh2oC}*>pE-nn*C}QFy;z zu6ka1S~tW~!($Lh$;$<89>r(M%nVWALxUvRscQK-CWvvJbL86kP~8gfaBpDA%400Z ze}5A^K&JA`9o8U6q7!c~Dx-)EuE^2)l!Wdk38H#|Vv7_Pq~{mV#l)e+cy0|j1i-w| zlQSn~Y&c7Q);=F}#`XwQ*{4xAJH1a`2+rPfu5}Iz4rV6qy&!IED8}T@i5{ zXz}@~#g_<1pI*yYN*KxW3vgS^KXY=SfiB+-NdfaYoaqyfihU<54dC>{Xl;ZPgk!RV zSQ8!>wEX=E3!)aY6;_ZKGoI5kv+4#!$fH0KbDxm|fUEREa5d z^sz?*_-ed@Z@v~+04*na=fjMsdoRoA*vrrd<)@xcVQB5lE1ccE^->HWc=6fpyI)6E z`fFP5Fga^G`;EkakY6`Bw>bjO%}Z6;fyFYfX;COrRk23rBBDz3B@|SfHA4OoAIpihm*hImJ;0OR#NVG z-Ptj_g!c**5~@IQDgCGTUYg7CnjEO!GJIA&*mk{>-0W->d)WPi6FD#{-nWmjou^d%+N^T|*Y^hg#CF^#|4_t4bTCuZrKHcOLOegP==wsmG{8tD zcp`3OHC-#SAzCEk$m1pG1E4z;F`#gNCDeNV4<|QtfVuxOV?dL)dtZ$j2pb$T_|WEG z1~n8lvWq2Y~9d$l9TFtZ=B=rnm-aha$=-ymiyQ!q5)zyo4I81@WN{fA5z;RuR z_borCW0Xt$D0(;sSWQShh+1+3P()BDaWd%-nm@bgHIRB`NM3Twn z*1nT0_H*-SVc~i{obngF6pI@Yd=T83Yh~pQ1POBfkI?U;TPmi|#Tj{NpHw-Po$Oig zvlf4I0~7e|Pz6aTy1(-wq)Y|_*VhK4dL)h3%NT;ID~W+HTFf+QZYPQ@{pyIWtWM1M zK&~qo@m>qJmLIpy6rU7qJb(rzjHlmLQNC7JRaEQ6pz?G_PI#4}s(y1U&c>r)A^S_h zhW_vJ@Eew9fR#UWA)(;d+=mA9WxT=P(P8QVa?)D>u~ygBcu3SP?1R#!PU@>TOs+)H z7kkBsg*XNvn>Nz38P*2t&Zh$_{}2gxWXffNBZdLMh|t65a@_%gRk37?w_^#!9C$>8fVxYRr$U;J8Q^Ev+TWoa`zykiB%7^qF&{DuHdmGwmd z&O~_SQwl9ij32?HSMxp;tX{TazNS+5J%U|}wtjrpo6~1?iuZn?H zq4ZJ8>&c_2&)=;)y zp$1OyW#h~Gm7R9vl19;e5mIY6NF{PCLQN@cbh#@M+h%!JEC2FHo>O7lxSSJ1Z-n#kc%*@v9o{U+N8=rF)JtwYZ zFOtd1dC(v1g^R}vhZ+L5N3hMeWLCyYf6H1fGO@|8W&6iwNDMQ(Bo>cgcrwyaI&eYs ztgZsSZn&s`am&fW*b)1#y%Zn=6SGfKP6}nH0-A}`(~d#0iNAy^k>qEe)kuWq4k=3r zMHyE zA%iT$yNkvj`c1nU?D3EDn?m>Re&X}85C1O^hjsMv0A58_iXr#!u0Sg!O=D~yTr z<$%gdw;IG&)_q9XF) zfTOxmi}OViY{~}g41ghS%0=U*efGt`YC@vZ{#!fF&y6L#ksMI3LIMyP0FNanP+NF` z1m34tJxnDICouHg#`!Kez#od*TIix!l>PaK2VtITG!Ir|GM_`tp!eY3KggS*P=+#~ zdX^wAf5*C~0K}l(EsqBxWH`@VVPyRQ;IZW5os$y;mIx^$RfN3I_vv~U^%cJYIyZgA zn;<~|-BJuGfgaaFQ!f&~d4AXXT?qQ%}pBNEeky~PZ9 zvgM&1yK;1-+v-nsS&f|wg%@M)wlnMofLnY?bsr`Pub$l`E}GB|Fy?OYUhmL}jOZ?# z-?_uYBy~k=$}sK(!!Nn(wPj?Dlxw|W&O$jI>$Vx_I0RB#K-4d+bRIte{ z<{fGUA2-4<#o`6)zynwa0u|;-UGRm(ehYy5uZVwNt6_QoF+rCK!`j{JFO`csl=6w7 zhH0Kl9KbF}#~yn0vJ3((V*>?2@z>WA)9=EnjQ^KBm&xR5p~36n{ce_fVs zB@vSw0nY(7d$=^kJ|lj5@xld%iD_}z1)lXNVv*EoZuul=?CKJx;zy@qg^tN2A-j|k z&msq<3KUUc*nM%F{NI`g3&XwV$Q@Ly|55{W>AC8G&4+Qq1DjIrYewLmLtq`hbOC#B z7|)A#+wY$$mfd}ySN6t!Y4fJ<=!TsV1gK8Z9iO<#ih#{GnO9gF?so+?GcC40F~sSO zM*mMA?m3U>kBQK+?BOBsN=t95zhpx$Di5(&S=*9D%V1g&w#!bIgE7~ptGba{Ec zO|WYNtbor+BY~SnL9P_G5bu1n)60obc9<9QPKJ#<)!@oHoAh-Y8|t`87h776`elZrPP* z>p7k#C?}Ps(nJ|@VH_mfaK)LoDnd|8XQkney(|wRbTFwe*(KzE)Vwcb-%3pC2*`<%tYAiuq-s+b?#}haXKd@>pIhGb+f{wTcOJ{%_U;Sux)9BdV zQ^aJzIIl2aR@Yi|fB*D$3SU)YZzxK@M<1(P*U8a0VSl^|a)V?9!B4G?Di1*ao>4G> zetYm0vctmf_?t8lv%iWV>aD|wNhUw5;t$f;5&jRvg32o`u*F5c$M1p#_pzV(5;7o% z0*EBeyT4DdTADL0Z-4&}*3*OlS9DwVzy;@J7+vT$N8szn4=z78yq^I4iUL=@ZJ;tO z0H4tE5*w}~$Q5cg2*Zfkc&$^?y^wzd&YesT@vV3s-2cf4at)82W_vfE!wk8~(B|x2 zs|ddnVk!W`wWe6RrL&hmXEaFC``^E03=~xW6vf_rpHOujpn=!I@8pX2ZD~6js}Av> zE{WiH z{!4WuA1yzvO&)tN_RD}iXi{~n5R9en7bvdbQ>;!`3`Pm zK?$DYxk+|ZVM=s&=keKf;sTdH_P=v7(z805zEH?YF}k(>2HS-M>Qn|a@7x80Zni=< zcP85X1k<~)f=4TUS)fQ>iHiD#v7?Z_>8pcgX25<)wf(f8*0pJ3%LbG~bbgw_wxA~z{B{{K&z zH?M8Wxw!IpZ@v!E zPqQGm=)E^xYa0{=-#J6tR?gFYxkPkCwm7IRnzB{r5x}3K>XWd3FO{IHQE-U1*Ym997|JmYe6?w@$<42NMtDv>;L3*|gPt+5pFr|v?kE>*V zn?0Yb=cD_ORuL)mz``oY-$EbTR(TYZcMt`C?+z_EC| zPmPfJG(T1Rf21s9pbJ^Yvd3aPydJt30hl}g4u9ey_T5U5+Z!Jg8PHr3XkKE0Yw++< z0a+~F1lB@Dly3;(Czq?O4>JPczs)P{oH-M(#f=&JYY6Exf>Hms3m`lSvy-MF{$cq$ zWx;3aB$A*Y_5ThDq_1fqzi@#vf!ONJUuo(<2Qr~OXjF_Z*{(^#|M8i?dRwK_7y}BeV!Mh3$@*qTfc5__w1h(oeLwTwVy^8CvQKy zH?Cy11N(|HUGxu#6E_Iqn^TsawdW0d*x@pr{p+1-u!wiT2XYSgH&a*7m(&xOE%sbeId zPaJt8=PJy`^EI^H$K!q0alXj^OKdOhcDUHX-B%cnHCiv`&e|Ow8V}_{VWuISwDJ*W zL9Lw4&P2*XG>b~ywj;Mwo)`#rlg|iY|NITjjb(?;_^v<@=p&&mmf-O}azXZEsd?T9 zZ}VV>ntYJwVjVwNDVWZiNm=CdmlM68$#ldPr}(_dj@TD2^X9H-w*8RwAbE}a-&45I zLwEYeU!1lWUkknyCn4i(8B5prqW>n%w`8m*R-)+lf%4HTdw)_RQtY5;)3McAX2Q?0 zwIVaAidW+ET;qYn5Q{yF+&!GC$ZUOE#)hp2FTVNd`k?+COn66Ipqz?IjzzN7)h9(O zZ3bO?_0S^OYh@))RzYfrOl&wmfWw3}_>qjwhdNb1w*RXte9W_^id19a@3qkHHcA!a z4c?|xyJV|1EG`4tl$UcOQ{1{p5~B?Fm$>CB-DQ9RMKwScG8}R+6p7{xt?^^g4}0Bc}Fi)+1Mn#NO;IoBcx6#)TDLY zJ4D}&4HzBt)PK{^y4OTUrJ15t>Q}k?^PD^ALO(l6<03cqC=uqTB`KJv{rW{>z3@9N zJNH12ozLp|A0h?K|$ga2_lg3({1OIY52?PE%0V z0fbJOVR*8cW(#riPK~E{ucD!F`t|{)62Is(p&Dibto|oHR;Tf?jSJl){eN@_6WcR`63IkR3*q6!U0fA>Y|Y@CSXImw2;Vo?};-u6+Jx@tnc zY+B;*rOt5cCC!x3(+{i(w~LMRqknv+^x>(=rf28Yk+FMtR){+o)!MK#EUK*AsIjT1 zX;8>fpPl*Pf*Wbkg7TTjnk6^B4V}Q`EhxhTw6hoIk_UnEzdbqk5SItHez!-0h2JWN z1PHO30;||eiueSFD?Z%x9#j5LrdoMC_r~n+x8%ej*W|Abz90-kOJ&sExDpDbLmk30VM@+_X@FnN@dCX$F3o`lG@e3ufCGm)$k@FUn(+jt)o zvxIbZmMrab!`RODcT@A?t})WY^25NK#L8;H0jKIB!Oa<1e{tTp_lXR6!tq%+l7wDW zZD}sWgK$K_O}*ojq`-6I5D&k{><&9zg0!ytQy^>pf8onAA z>oEr6+-1Fnw3p0athxwtb6Ei6w;}I?WRm=otFGUd?JVDDp40DipmF;lp>OFH7?<1o z+wtl{+SO^N2H2BR9I_tXma#Y&p`8CET0T^&)!TtU6itg`0Hs8#!P3=tq`kZl8PQ>mSOie!t8mkM5T={QJRIB_xQ8 z%$Rt|#-h}0wSPT(@lmn&5O^cdQ|2w*F+nWFcE)c(m>QBA^NQ5vyN<)7&kRV0COwR! zf2PGf6|n0&WN%T4JJ&kD_jwuVId_=XLbk>HA(F~Hy2aR~oNhVYa$w?BdX8we|M&dS z{3*}7GBy#toIUO-M83VgqCP9o>!sg!;q&yxIe~_Nj5s#mB2o1vvH5SWsQ!GjE|32; z>K~*olw!UN)NK6%o56p;xI9|nYUJTD)W!pwy?l5eTGUjL!>(%OsJTuK_kw~Ve0^Lu zA&wQMSg9=>E#(jL?V(=xG@f*c^)en!*Xay=4K~^`w4+)=>HW!kW&1jdaHrN+wm4BP z_GNI>h${07fIlU&J?-Km%x1t{Y$fr7Fj0HwXzeGFPGV)3f!aqUb<+uv7V(fTTt4Kr z=Gj0{jr7??+?(C5Rm@wP@OQ_ZIbqfB1dnS%QboCa>v3_V&>Q?na4ZMp;T3L3f=tFE z)yh=#;-mHz-ciiHV5sDPN{+$n1p3lBy7#W7_Bv8#-(m5x{Pr|CjcjYl zBym}+l~EH(O#%%gMNEhHEcCYb;HR|>?Zd)luh?}aR2&}-5002@O!c(Zij&FV-T!6i zE3+Eh=9@=Anv9#gEWfHeFJ9AMm!xRA8btuK=1MrGM4*)BpC_=`^?2ObGY*tLF7rFQ z?(|IReQ(Sh&#t2+-p4K2$F8+yb$~CYTkb|?@_}q6lC+DvMcqCvX;R;%?bVuErTd== z9laxV)XE0+L`iM6h1Rq_ZcqzxT>J^NrA39dR@^28Z?SHj)%{AIv6ZIxfM9!B`5z)t zgjW&GGpf5C#;pK$3>~??sr$xX#-q>Foiin`aWguHpaLKCy6y=a-jmGh9ko+oEEI2F z4Q6Q491~TdO7t+HNyL{Z(x-G=Dri+RfAKrBL&INU+}_v1C7Rbl;RygwjWkc&FOX9W zhzRQYFmm;2!+<^+SJ{=JH_zqjtlJG!pgVtcKj{_%E^sdJ65DBJoZGvDGZLDzeWS7% z4(c%F1?p|;r~vc7h@DcM{WPl;M~4C3c9B2%I_J;&sf@m*f=UP08_?llABH+)4b0dDiioC6ZGshVZN zeE7-k5s`tgysy5Jl3kawY;PD+n~Ic6XDg7O-dnlO(p>|`YPwuw?kAhqVa$+f3wg&( zY^lp@<@b#mv)s$Zp-HK$_W5HbVku^EcTM9oT9OncXIT`V_w>H$_a?d>ai-+LZ}G9z zi#x~hPB>|*`Qqo9Lh%?)mnqC_bFa$`y(DL4 zdwx(>V{+ajsCy-8hNAhC@aq3jK{@?dn6^Nd`*1&lDiK#}c6t^Xo`zeoB+}EL#o>@;JfOfnbvfyF3C{*~-WuE54`5 zUJIEc{!wv$Q|{Enw`%LbjDK=^E`|pKSt*^rQ3R}&P0&?&v&SU5r9|MLg&#gw7!~I{ z{m`p>c)yTQldz-gaE2xB!nm@S*W$MVSv&`1VRzM5ra>V3DE5SUzBF6r8@~CJYFhmo z@$Aex!V>@m*H3;36!kM)a1z2y^$UCHgu0poJ%cVYA5BW%NL(DTAF4n)SQ^ovw)5WL zT?bfAT&zsDVcb0;9Pv5cNgil-JBo7%BQtcD6O|F)`bYMbr(|JY#eREdd*yxl2>T*! zwkEQGV`Hmu*Xo4i<64Gw{7=?HgS5V)d!&!GXMf$})XGT-H&W+ui_FWDz3;wOXvB#k zl6dy$8*NUZB1Cum#lcb*%>@XZ3uTiAf+Jde{qnh3S!N3T_>J&tn8C}AFA_aCkQ)BC zvrOWQStMtZytutnT6z43Z=L$e^c_34y~@_gg$j}oxiea~_!Fwbvu5^=j#`NZwH!<{B0l#-Ma>0zy%*c#zAQMDDc9~+9e9Y+9H$5Gyjh75rY-EFbki<$a!j$(|_({8v^#c?u8=`o0ml-%mp<+#lKtcjmIQoU>|F@W<^8lDCWdujCh|t zbBb9ix#K?uz=LcC4+sA6F>Igc#AH%DuWV9u#A{*_-%8IMS!|O&I;n^K%GHF-h6|0ZQZ@Z3;A(DSaHi=CpLY zV4sZ->v6>7w{KSCzf_*QaWHd=gpeyr`iLM*?`xhvlPMK1=XmD-Svn7xDEsi}-kn18 zKGCed&m>sY{W%XCt|@zOJ>c10qI)od|mI z_BaFGOK-#(0;sg#!dOQ3V2q(}cLTq*w{9H?J&C=h=3JiYF{J{gg3S!ugaiBTOoeM) zT)$MPB*4<1u*;7V3vV?prG7P5s6(Az%m!0PtsS^~UspD}?w96E-_V&1fuO*mS`D>Sr?}XQPrcGwuekVNb2Ux#v0BXWITfaO z^Q8XLlX5{z$Eci-k?+ger0$v)eY{XWqk4MbwAI7Jbu|gf^tCK%?Q{DgZ3o--%`JVR zgRkGd;gNUByxhrCDh9P(Jxx*py zW&u27xs2_Jc4F5s&BI$WfdOwg8BYQjVi&H4+)f9o6iE9uhop4-GQFog?++Uss6)s& z2VOq4()wiA%hV>^U!YI0_??^+JxqFe{#EGqkY%voeXYymZ{+>$$pG$ihomr%QmEIC zxpKVNi#2uBv9jc-LXT+5=vIkeyfQ|c8?S?&njq0H`e@MzKajl%x)E%pm=Zs4djYOw zInfQc(Io&<{L|FI$6>?xkrQ4DRaubP4zIQ}%aYAHvNE~NV9uCnpY2gCzoTL&lMId$ z=eE~op@-Y{rS8s6q3Sx_K9inEZiL0|F`chCdU__{rxC*5yS(>f{(^s_8t$C&6NV)!_|ne`q1F?%4O`4# z0V)9JwdBU{6bviKJ(7kI)H&4_Wb{$xTX`P6ou@cI34=E;H3=Byw5DkFW2O~jXKz=9`DMROtjd0C z{y`4pHo=MhpN5bRjq ze? z7sOp=2ly6_eD>+g)WBTqqsv0Z&l-2aeC!Ubk}0=u+v%(tI%Ad4hb#5s9(=MQk0U?D z%_&lr@yQ2Jty=wyvk__~pe<@1}n1|%(g)AeL*Iv~{=u2U3;6JHsB z5JVv`h|`-;kXD&qd9h{VzpQg{5+Sz&j-5{Ue9ojhLfp{IxPdYHfJ67pBe#x9n>I?; zEcYxthfhAD^&9DxHfFNOY27176l}p|lkR}({=(S~> ziy%Tb&*V4hOQm^Vf%b?fo%={SDVBEromuIF{r#F`<6#ci%3|2j;Aagbt$->$$NSOg zX*Q^N6Yo8mwA~ba zwBj2_eJh;{tR52`eg=&mta(bvieiaCYShcJlVOo@7yV#G6lVUNH|Opo=P{S!N;%!o zrzFU5lvK9I(^Sf9vFP#jExIGEsi^y0acnM)@n`2sB!k_jztI77x{xshWoTPlwb4B3 z_1jTJ%&OK#>K@N+GMOvIXOJ>PVb<-b8xaBf@Bj6swDQ)MtsBbJwDrEQzx{PQ=W7aL z@|STS6LqssMZ)V?P#-uR$pgGkJZF5+cawn8?w^~&h8G6{ot6Q+dZ{kqdD^;9R4xOi zpK)@W)G@q7f-5^79++&ZPwOH#y#sAGO^gO}4n>N15r>Y(C3UYRUQ1WGPb6uZW>sGN z6Mg&LAY!31$KMe`no>eBC3%D6ty-IdReto-x|=*YoAfWg^ksCtUfTP@?2HrzOL^Y* zf2~Q??nV?yySOGSBvo-Eik)V_vEJl3EdJLN50eFtdhy@=RSPv~@b+u{Cil*odMGQ) zkk)jI;&qmIz|R1c?fj*WkBSGQdk+PQdF?4l2F37sO$>r2Q#6<3_wolJuPJN>(*~oC z)sAjgOG3ysp#O%DDkwHCtmD9xnrzuqS{wF?^pT-Nv>0o`uf*}4niXi0Mvi4H_-b>yDQB@gTAdVTSFJF{4J`?ZI6UX{if?ITID$ zdQusOjsa!<=`I6Le2x5^kzNKadOl#fk`aBCkUBJ-vcO}sNngBxRpj&uDH`H@VRqyg zNGnSCxQ3s_OSY79FYTAX!!9*{5qtjl&HENPSr5P8_Ic_vIr)0f_OHFUBa|n5Ek=Tu z=e@{K(hnX?NG&$mTJ&2!99YYxTsCSY{{N%vE2E-n!*=%!0}Le~N~d(gD@aI;Afg~8 z-5@F@DP6OXQczG*rInIax<^ovkd#IkVx&8yIeXCe{mweyI)C<3muu~3o_)u4*L80S zmW+fAk2J%ECL*ThLz8`{90l$5ky>IJ+16d1+Yc*A=-#EibG1 zQA_;=rw$iLF&Q(_;X)H%z z%2Nw%V4WqYajqOr+fcC0BV({%vz_BEVXmA|G9~1ff0IMhCEGE@cVEu;_m}GSZG16M zL=~TcNiu9YrnIPtOsx0gy}Qx*)>6_^K+sTA^ zIQ0(4_Nw{q@dG}zZbQ6Q3r~>X&$r!zhFiH)Z`;I$`Mzr^wfE&on{@Yh^ZN?YF;=*vqpCZo%4@~Y3ZU4fIZWEaiaj< zRLl+Ec{*J2Fhk10h6-iK-3WAPHt%-Nqb=ml&8?v?+!z}hFy5IjaiGzwROfv^==1fh zAkS8gR9j6xM8K?p%USUBT|Q(OdaB?nnVLBvpsXBKynrvJV;mJm8vv;VfR9+fOwA`}K+n1cUVy4$v={~k;?=KXTEf~ZI zRUaXSAG}@;1u%Mj&vl1nYVwLaPTj3jW9T5;T7Va7`_MRo(%vOcAw-|5n6ua@oj!B3 z_RR=MNbv-FVd55l`mJ*EjC7cL4CzDS;czW*EInc?q`SrH_q$TU`zXpmpg!kUq%QTX zXta>u^ZSdvkR{W7?MNLm$v*Ut$i8@$622_+1{%@*GhDSWs&JfXXVy}=qrR_iQS2;~ z&|i7vIp^qLs4F|FN-Kk-^gpdi4-|!V6Iz}y+=gQbfUzX(QwKE|#`|$2-5c7p3ko=` znbAp;g?5)P`^I>vbEQMQA2M_4Nm^T%esbmgVWVUTW&*+8T|?(ZsH^0SNgj&| zjpfjSLCxsPO5yHU8yubtWOne8j{E4~JK=PFt!(`Cs#eDbg%TB01v`0(PA65}kawV_)os($U(@^(I{ zJZjHf>8%crtP6MAheSoHt!hug(u6X~a=|{&{SIW|`x3MugKoZ&?JiMVowd{Fk)0cm z-_z$ok^4O~k`P$29xEFaO*g}*&-GaPQXpyFY=z@0pq`hP62c3)W=T%Fb;w(2Y+FJeRr0WUwr zNH`b-pKgSO-lfQ>fVv!v9w7$r{wV)NUsUT?TP}%N;O5QEJU!oa(^8J&UCU7BaNR{e z|GIT!cvP0d#BlL2ksPRSn*dc>giDMP@mAKphlk|A!FZh8v{^NZ2q*Se?zybHM zUoL`{`+aM1eUd-i`?VpR59d$+I<}b`@Wv8nx&ZyTNE-)X2$yM_+KIyCP4#bOB$)_4 z?_D!IPKTI%y1(acN_KuPIXde_dXA|l1rnaQnT$;3 zseiFJ6MyN+U0;nO`;*Fz@)XbSxjVHEfs#$( zPPlShM}oipNx?72vFL)$>`ASJcT@KlX5UZF-mk~%1k?Lc`ulS%E0MUa+tV`#z-_^` zuoEmo)h%^;9>e0?OgLFX-nXPmCSbriVTHI8*6bPf_WSkS+RDJ*m1*xMj}H3ZmF}!B zi8agDKT-^(tWtKuR5)Bd8bh<}>lME!n+GyYJzHTa*0 zQh=L7opQnkwY^8AKG9z;VObXLZfImnO%>5(N~B+OiM7Q!st+BQRWN^_tdzsmIW!h; z7BEwkn4}l{O0F6&_~l|ciT_oc3GXrouTs2Dn}}C=^DVyWw&JtWMN6n%j35OmCcSrm zzQI5A({Jh&k12hFhsxBzjg!{>@sE-qA?|jhkVRD5mFqJ^P1gp^me{-oK+m``q1hrY zXd=l1U-5zF{!1V}GKGRh!6{>Qc`u!7_%;v(*RcStrC0v;&`{G$d&CS1Atn zzJAx(c-U-tIcGoKIqd!T_)(%+cJ5}v#03k<^mcRo6a3`iSfv(jP8=Zx(u8{fQsG zfedr?(>>qhA@bn+O_;&LeZdk4uXdG zW^SQR10NF8Pf38VXac#WLk;@lqjd3J#g^;orhr{~)KkSGL>`jjnk+!e2>*nnW3wF|3uq_@ThFT?I`3xbwXkcC!cj(0I5-l9cKSG7tG}lnmI_XmsaQ zNFFyRspBjaLP)oVRTWGlew~!0MNE&xKz&6JadY5?)?2k3yB&UI4x?I*!}^|ei9`Ag zX3@|I3l-t!0>EHXg@rOyIOfC>JRS(bXzVQ^e&<&_j7=Bxo;dJGu*5;9l9z{wjh+JU z6rg~(vSofyHQ_Sma2hG*>JL=GzI|qc8O*kycwM+g_j8?$N{b{?h3`jk^h! z$`Axm8xn)i6Do#P-G{S>VE(J^ABb z9GEp^AdLAF1J)Z&4)fk;6?&=gd63hD!>vxo^Mhi)g66-Cp6Bq47Ay*cXH)`02pC&{ zFv39BPGmxM3IduCS>y{oKrG|eU4>&<{8jJf{f5cu6W!q)P82fvAjPw%m4672EBm%`~!zBGm2KW}glF^{$)#GDAOw3NpzF*2S}5kzD3@w7Vn z+FNoEAb^P0V8Qn(;r-X_OmO#yc!kjhW=o&7UF0p3R~D=jiY(7z$z3gvfRxEYbNYs( z2;;Y?8Dyi$$9EQ>X7$a-%vA{BTyhWtO}U0k;t*OBLA&2z<=xykOP&im+7{bRI|2Iv z3&XgeJ-+umr{p7Od$z*k(G=mW<+FEtJjPFy2ls}ZHRP2BAs=t5KP-%os*+0);_ zfk(fg_~PNp4Mm_zktF2j@0ML!W;eH;^f-Ub?fxix!T`8ccC@PZh6iXzQu=K~$>eFL zkMlshWpard#TYGqB2?X3q=`G1)6d3}k-@~^bF59T@CT^BB}JwGFG1ePnSH(-)pQ5A zKww1O;Lj47q~)eahMUSXqVI)2{Zar&spMS(-BxBKzWe4ERL?Bj0GZQQ)J5 zr;=r<@Oaq=d_fh<)edcKET{D1Uhee z;U^-Yx8jNG)WgQ`b58hSlbh5%P_0(dIqWSk?_zxoE&6O%5gBr|i8REtDRk)6+;~8A z_9iMJF|_>L{3i~~peA3{E|*q0Gr&f?Q%~pV$&H2zoTMds&dzlZB1ud9+x+TDR+qn) z57BX~%B4pMwD|C~F*xf00d$e+tYMqm7a~=p`R=pn>M9+~qFFKWc*-6jI7G@Q1lLbm zfKCa0W-&VW;B2~$W6n+nA>aHCdd`A={8#|Wi=L-BFs1jgl#6t{LtTLYvhTpJI|2_W zZl)4z{^K;!FMB)w3Z-Pp2hJW=*wI%X?9ES3Kn!c>^ny1>3iDG!po+dti%Jd9JTZs$ zuo}$aE0{QTXbW{>NLkYKpI7(5VVbK;N!ds$K_L3$0{J>tcf1t9M4sSC!8iB#iSM^X zvMgxxVMM_coJLKVNR&cUk_6QAJJm>dml0=)p1w9$Z9UqXtJjDGQD{mvL-A5AZFk66D@%Em>?2j+0~v^nxAUs#_co zyy%sicuz3A<4y)+rZ~V4ehtwF`vy%j2ifrIU_QKUpi>O%-D;h_P|A$u0;Gkr?eyVx z>0ZxYZs$PL{g`kLi2jJ;5K~`!rg`HCghx+`=8-31QEMDbtTVA6m?y?!FMoj3uQo;` z9L4o8rCp=OP|HHJ4dyp`r5;+Qtk`fJuk^_24{ZkXz(#-(4cZ+7OJK&-e;Pm5RX zK$cz>Z|Rk13<4$ONti~2iK5cJv8n0?J$ICTP{=ykC#;Y#^nY>eCT%p_VBoHc+A8bu z-;ZM^k&f*LCLT|yT0Um-(Iv?UWSA-uyaHhow1h=YWT?nYT+*Z(?6eeFd_`7t}z?JQE)ts3aX$e#*d?jV(S?3&iGL|#U zNO|L6k=eEG4nnLeDh|8ta8=wH$`)yLR7{(ia;XM)Swj5py z@nwKHq-&pxxh^T}70^SPVQF7j`w@*tD_&@~e z16oYqsJ%acJ6VM@pB?01)*4rgZm)g$xY(@#yZ_;kKYAh@P6|=tliRl5g=Gw2KU=OP z@2G4J;dA((u$4yN2fqfm#_?5w7=p{6C$&R~jyZd_@Wrj`uTQsd8cDt0)rC33!)! z)#&xrmghyl_~fKtR?JAu?afTt7b^h$&;CyEJa*%1{EH!vY&Cf5J*#Z7B{kf=`xdZA zfBUnXObp#e6TS5t|D>Sv4Mk4h;_!2EbCqM$ys1r2(OJGwOTekW;xT>rI*Hg@7a)xY z^w5WwoS9JBaN%miJZ<*XDCo-;G6v^N%6KDF)52M+0J#&9&>_W$ z&1FQ;&4{}sn8i9mOupiEQ9OI?BC?tg#X^CGY!Kc<7|FnE@8pC$NL?G7&G+U!OD$?_Xj2o5Fx-e%W$G2`_0c1Dt8W%p zf1>`7GF|)I9fKZ%Qi~?I5;aXjh_7)mGR;&Al4aAKPFybY(XKDEm2?ClrhqQ<_qH`( zP!MBt-B9MZBE}7zmlBYKIFPcwIHHsKMoq^G2A_cenn<#952ZcDns_v1YGHLdG9hA9&R9K%VM8*z(*m5bulAl)Et-5`d zqe#op{Z0);KIu-Cq12)6fP2EQWihu_aaRTEW|!KvP^A14m7D2vC=kjKA3A?|Rss~K zpBJc|k8#*M>OK2xW{6rnz(f3~t*B`W>iRl^OEw4(&xeCqmiFaD*el1Zzvo&Qu=@>` z%CPl1vGFfg0L^jSo8K4padR6M5WVs0a;6X;fgVX|WOqiv(}CJHW7|MM7u!ZWls1i-tJUa1pOTJH18urs8>rs|s zN3W$J&2!(S)qR#=5$g4|9fXDe%$2Sc+L+WUmFctRgj8MY`Mu739>5hq4fRKO(jv4y8h$H}Op*|$!o0+hx#XGw z)gL3`h~IJpRRnsi2nX&Zj(y);L$wkf>gKU|18vO3Y{2xR8pI3NrzmqAYFHMMUOap!r-8J=AUUy{FOCRy~+lxtoz%6=PkFWx&oyn6%r1XkPj(|iVZl~Mc4SDt{8@|^K}MPIvvPaa zF}Bq9#iMyualy^L_}I)wV4#=KA71!?c{`-8&>_JL~~lDBpTWs|r^jpBm`qNWolYKYX%M zlt*`c(wZOMchbf8we3ufJD;QIXaSR_l8h^M3HbIeyuv{(4ta3Y*t-oszAm7K8hz+R zkL3a%LGBfx+2r`>DbY7XY6tBHFFxw$$DS*KQ9(ozqKyp3%a0=;PzMz;z)yTjMuHkee>XiNR! z1T7E|XKQ>%>85eA`@q=ugZ|3hZRu?`MTk9T@|zpT*>#L#^8|WHt#sea?chQ9QUogS z=07e=SKim9RTZV-9T9XsD?;RaR=Ud4R$(czEifJDLYE60KQ)Im@8T}bMoB@g1sOmh z;#mC?gjl}d!!5f60th>nj5tEHO)++?EbEfzr7?ZCgVY7Jv<_ot_|dX2BZfbkAmBiH zn^h4xwO-*Nvnf8^Ekp>||7EihLgeK>^#5SmKSZVcwUv&@N_WHUF}^(lZ^otJ5Fe5u z1#!ngyY;uaAVwf+(K@!PF~pkB6^`22 zl+h%>1p4q9ptuV|_--TsJ5QSw948Ivmb%Z*$9_58X99d1G4B%Y@YIM@8{A}X2sIOThWa|$m!j~gQ*1V0!kFnj=i(G=>? zIYJ6;5=3loS%yALs*y$H-3xuG<3^;y&2#!ChEi!`J3?EDL)#E2EPib95xS6Z4~Wvq zwZ92A5p?ExuTa5K_sSL*%J=|OE+w$h+2lzUcS@Oo*n2q2fc41^x&~-BCW;%tt(YD^ zB*q8@x5FT=0ckCLzIP(L&vQTG4SC)XekVo_M6$W>-Xhp8UiO;g#+SdOThFJz&c>(H zs7>$(rhM}GhLigItPO9}eWBK^7B|9z2s8Z5dm^(&lhEv37`2z%p2#+OPj~)!k9UJm z`z;%lEqJro6!zn=wBxfMl-h#6s5zeDRYco^;qMn#SIJPYN+dy7T(ml1uyHNir5p1v zh3|=_e4@ncf66rq8+)Gua}RC$9EFb}7idsNa4Ua+BDpS0CU5aTLAho)B_JoOS4kHBO3p9&(wXgY{e8n}mybMC56l0X_lE;c?Ic#ptxVN>GJ zKc<*fX$F12wRYsEsl?QXoP5VM@mbfz7cV-teV8{8{Fem~KU{z|bQjuRQfn&wsRy7Y z>AEzP)SczzC5q@;4T>nnM2IJ(Ts) z#K*6XRsdphcZ|NS)AG8FcQbYVAe+L{D> zhgUPl57{Bw1(J6^55>OxjERJJ<(`CFk+cIWx7xv+R* zHWfiI#4>zpRelc+o-?b27v_zo>w-#yoD&EguWFFm?gZ1oGFYsH_W z1}!K+eq&(fCA@7qI52Rp4(gyeNLg9A9Z<}UN9HS?ILmTo^`NuNp}-LI4{2XYev+WS z5*(FJHqt5rI4w$L-`_!U=d^=nXas>s!w&8OzT7ha+(QU=hV>9einRPS>)gosP(@+0 zg}72W(&YwG@3m%9EEyk6fsDHnCN#icWzyzn7ESUw5tQFUU>gXsK|TcLGs)M&TQ}sJ z6!DW3ewV;WXScm87qlA5zGx{%+F;HrD9-Y(K(1~7wQmt~uwyi;Vp$9==*j&c=$6Q* zKktQN?+Ac*FW^*cR`T__AuZ%HFh4_ton1Uw)r{ceQ^a5{?Ab&BFWKq`u5+!PBO-Sa zH6z;T=Qa!Hn3#@40~`+&V4V^zCh?WW_aKFNs-Ir|9^Plw;x8kByYV!72t z8AY;&Bq$xzt+i37K+5@zZ@n&;Z`V>by!iKh`wvh=0$KSCCDdfBA<<`HpqM<>_AdZ4 zqC*ruJq?YP@x-|KLn}un45yA7Cc~yC4u_-E<)tUGWl1bOL!fYi3=NbchIeS-oiW!R zXg$b>IDZRN!4{8Iv1T`L{L~VkH%#hQmX>MUmH-C~#~twoa)=?gO9&{wd~@Q;nT^M@ zT7ooz7IBb`-0UWiEKXx?kR)v>Y7kpqdwLlI#iW^`O6-__GNeL1fs3#N=C<->MKjvj zFS0$Nz|uKe>rCk{`5c-^`b()oAKo|D{!rB4F-gL&9Z@fZV5+W6q@n4F1ln+89G^CG z9>7zUzIJ#2Vl-`dV=W(6HjAw@?1Nj0AseJhl-3xc5dqQt0G5V*dBuh)HjojV&J0Zc z`iCIQ$^tR{&CY`VUpN6pvjm7cgcuLzM{^1WKfIkIsCiC9LbO_}DAmA;E1hoEELNk# zB^lNb*t!m;wu=J7@YztHi*K+XUl7$A<$<_D024^}p}djlLm&vwmBK+z%sQz7FieZh zg+2V*I$z;|UugxU?3~l{s{U~HFg->Ex?8%qr&^#_ttC^p78@TD4kz>jT~PhknwlyD z0HuO!Uk%7Vx(b&MEt5^zeze)7)e7pt^-5Mc^4rTh`o=0B>bw8b@%>(vX}Ta^(xiaz z|5{b#SDX?LkpQyp!8p?<>I|jNuiNuw0DRqAf`kCWdR$QeteOo7ZaKwAGH^UUGyIch z?_aapp$x_aTF5SxC<;CoBD^t!>q>PEI{iJh+%Or@yX&L_6h3DI>{WImG#c1x_fPC)0Va#aUty731Ook$Z8AFFrfHG=o%<$;6$uI0FOQ+0{ zThWoB1C>wor?N8g&uP$ky>Gw>w-WI1B1%7M4CE9VC#j@=Q8$4S_jCCk!j@wNZt7_X z&b@}*tpeWq+ZwIBRVPuOUw1e$yR{76+q6Q!8v@{}TCcG)xeXCWxnjNjnB~P94k(3mK$DN$CxG1khlqhc;gh>+%sptQ@xXBmq z>NZPvWB(#K+9#;MfkJ0$_P8L;G`BDPKn7xdXUYmK^=x+n3SDE|xUdnK=v|&|h(5dH zOXH!#)lcw(F^lrfbL*ZubOwk`VpheCH$K!OJ>5=&*_@_Y!NB>&%2#MtiU5vYcB zv-nv1nUzV*#hQx7yiTlma5t_slY6!rM=nU&iQAAdGP(q*n$e|Ui}*7r7mfN2g$oK46{u34;QgV6E4?bVxzTT1Cx@n6ey+_;c^@h_COA|hzGw#pz_9GzfzAnZgbIcp!ga{7wnF^o2P=i=m6!739Ll+UL z{7~vG8?Z-!Y+W0NXXtvEzk)790*})7v@=MAwa)wobXWd}2by~YE5J@UYatLRyxj2R z3fNl|gC)iWN)yy`D**GauZj#6**`K?G=YoFCW7WBa1;#X2(Z!^4cQoJe3-Y7^v~x@~uY`0zT&Wfs3`RY+f@XyBcUm}nv9z}jJ`tANsp>P1?hk(>SQG#Y<= zQ#?{~=C1q03 zaD!P2Z`keKg;rShNQk($VJ{(pi;Y>jnWaJqYmlxd~8O zv(xxc|NC!zIum<we|xo7W(63K{Q_f+CY!w9>T4{NJt9X^=#cg}ZOr4 z|E1MYIAPVYa@vOCP`Q2acwW_YLa0=XG7tnR04v(;jgdc;J-@DjKeg!S4!B3ep0;S1 zP|(!!_22(5hEKZmLi38gMpVjz`( z^+yUpY*&HoEwLL%XJyKZuoLo)tyz2E*yWTea_vMs^quk^+eq^jKo&8MQLudv_*p~W zNsJP{B>)VEeKP)NmU7hZ7)vSmYybLxH5OZ>YjcUA?0)*^jY~^z2?2`nhisu+V|ws_ z$3?(ZpHEW*mG&WST`YDKz-5~a!cs$i*uASjCGor$KzKv>*UZmdwf+0o!A|~$TNWZ{ z?zPAfk-;3nYiA8CK_7m-jO}n~GnSD5L+G&xRkZ&l^zci0=d#)ZCw4ph{o{Y=Np+^NHd!eFHxNUTC5cf;tKkNdhM8Jb z&(^A{D}gQEi_>BYYc`vcho>X{{a0#Ua%%K|)toL9LbOr$Sn>sK_4nOo>(^Qd)E1^CFQy-)_HvFO>`2gmK1%5BeV?gaFE0GHi8|UVuVdvTpx0{t73W$`Zp^iJvFnx1d)<^MC3@B63f>0oFqc>LrDG0kQ>ET<@K%E=3Qx^D=(> zKG9vY!<+Z2Q&Aq_DhT!?P-Z)oh|;J>J>O~A?^Q9vZ6g3%>^4y;0S9I&_q=={AG`!G zc5LDWP?i6j*bea(v_UVSg$3Ut0S-DyY(~t@5oSd(f3HpVG1xsH(cSjTMv^)FwC{kZ z9%lB^dF5?ZLQYvHg^kqwck)NA4^J`5z^kBI61^Evg7({sHH%)6i210T-zHldliD(D zx?KkCSqGB&DLVU+qsUt75tH_jFDgt~+bK1R%LzpT+is?;Zz;16alaO$y{l3I_Mlzl z8=1pcC1rk<89ty#*`?dkvG&W^k)B0ivJk+`psmM$ANB`3Dj4_)yF{uTCt5V~Dy8pNgLQ_-KN1=nM& z$gC#oVJRf@22VLkG059}L>PFBow?MX@9^ph;@kM;JjSBplgk?2ZAX_syOFl+>vYpw zy}xAa#8L@l5NbEE58R_vaQ4!svOB)0>^(<*tdpbgP6O~_ME?*0y1mEb*I?W1s8Lo4 zHgD~Ywz<&0Ef3!MG$TnBGSc3NKILO_=oytr^H#BBduwqh&rcO6Xfe~rANcas8V6p;2^FiL3D<%?vW>93;Bt1`k1BF%Mhjoo&- zNM7tThI^V8@FSRSrpg%e+IBO~+>YTF{sPGidGHkS6%oeOOlScAH<+?jG?g|CWTU(Y zF*2dZJ5G(?lU@bVQGly*pKu=T9K7ak*Ql*rDU(9TCt=up*%D(s3)g}_a@|m|yLK$- z=M07gl7fhKAvN?UF0?(}qjuLcz04wFkpvgf*IkgJ-7uH1Izv#HdY5{l%4e?Ox~U60 z;KR$X47?Bu0lU5&d+WbOA4jJe(iK`j-}aRg;x>U*WqNwW#Gm730PxJGWi&)Rv_N}g z&8Vf5+D9*S*(FOgcrw87jG#7KHr-xCd+kS@yC6ayF43#y02ku;B?)t5zNwgY5N$+2 z5zL?jHq$oR7;VHTEZ+~fXeinK-0YVSJ(gzJA_oRPak`8JwWlWP?iWMt4O{G9a)QajboXTb5kqFG5j$Jr` z1A$^Cbo=v?S5)x0KH!!1qeA*KlZTh3k9c#fZt!(dQSqj35zqtC=if$qFVHMtgst9( z$k!HmSASms)_3gn~fKq8o8g{+GmX)kq8rr07XSdpq@@qe= z9_A*a7CEkJ0NbWv0K%2AS!{J)dWBKHD=(nvk(q3^;##$xe}YA8lZB(4GkSB|#6rgu zw(tJ62>oWh$J>wKMOJ?q!TLei^)(Ci$}$RH&Pte`RUBfZcFoczs7mNe-nB2lXn+eU zo%0lbeAzEjSo%Jj9gxNE1GRkR{}9`^NVtc~86$o1V^EwdLPuowYUmF zK6^hoWly=B(*zXXaDeVdnL4As_wgSL0CI@^M)JKYVHt2#e2|7_v9@szJzh7yf2+2X zpvT^VnA42FlH4%3_D(Tjmuct8%THR>Tv4wWfpW4^xXqLA0?!Di8QZ!Z%gpEmOSH@@ zEo5#gZD(%3#f8py3m(@)9&Q5ia6{D|YUl~K-raD#hMrtQQuR_{&xHcz1na-TzC{SP z)eaM3C1U;H04Yq5093)1D1R}nJv(3|NCI3SiTZn4v_!Cf_V+Oo4nQ6NjsfGa=E6pi zmFFed4JX`{a0xColbfMbR@86?2BI!{fxUik6Z;PWxPVx%A8)TPnb|SoH<$9|-r{=-%qvsC!Rm+~!0NQ@0`0)J%(FHxKQuZDrDP9nq zapu+T5~BNLEMrk%=VGWviB8-*u~eC8ihFkD7Th#iX`zffqyn$gnsl&$2Y&<_4<)0X z0)zm$01|u8q+2rjonGvDhVj@etCP4PXw6jJ{@cYEW?*?{AX1SsMmSB+Se~D^Z*$KK=d7ks1sL`YL9^tn4Kt^hrbej zU3(x^Sbm2@k>8I9>jiQTBaFTbKB+ec`Vp_hum|;B?y4q4%e)csEE6_<#ZJ6_02il%#7EbM#D zd*;c%Nso!@n_GiGxakC6Z9ve8tfk9|$%5qI(HR_nyPazuooHEZ&T$Zzql*N!)DU5B zkQTsO?{y^9`K2Tb1Vm&Ii=Z3$uOL7$7}niOuLd_xhL=0=~o^UN9=DOa_!Gj69#D6zjT!DQybJ z&?7NzH_5*$PSgwb#vNWdtQ&@FFQVO+RTv4baf(BC1i)vYc5~i|Mrjzk@W@~9aRpi_ zc6_v-p^9}$RR!;b+uxpk#L@TZ8xznxl#+v8w05J$++lyV&>cw8Z#(i5Dl6!N=&?UO{C<};XRw=d4Jtl#jD=obYy-k`C7G&{1nnxA| z@OIrhU^p74Ltx-ga)7FM&t?s6(!~A~rBafS=d zBt}ZNm4nR|C&D5?+5zAznX*sHhI6OxMd3WYz($1zR>MhgYCAaD)BA&Q>|3GqZZHO!R?tLio#2n%M@V(X z0B5=$@E#ciEnX;t>1kf@tAPJ7e7(n);9I5l3*=Wei(4t|02{Z>!K3PtY{+#yyPhFc z#&GKa;tcvjt``%);c6GgM!u*sv@Ek_!&=X0Er=p8g)!2JGn80sc4@5Ap5s70B_W`I zUEx3)t+)_pL;yq;BpDxp)?W5hc(7Y2T&?@#5tZ6+`=c!=y#3iUq$sMkHtC-@r!r<7 zuka(uUXb@k*R5Q-6{!V=y>si#>50h2)6K=2Z^=niq!@XWrC3`6THc3D`J^_<0e$Av zq)}F}aNs0R6TmQ?4=`W+GqG!QF4pQQSVkcB>O;4c zt=79X1y1Fh$q@ut8u}RUL+0(~va2v;_1i7U#oJ4FwdgWW5c?5SA2wY7eHvLLaW%G? z2_>5t|Io)R5f1{Qp5voND(PArrAY9+*2!H?$A*8M2|pqrTrogX!|PjZsyL>g&wO96 zb|)$}(VrD|iILz(!rJS_V}8lR%kVjFKpe^(Nn-`V0O>_4Qt3nB8?*`5_r?`;kp@M! zW8>F+9WjxH2`K>)6N@K7gZ;|VVFwrAvLz_I-`vE_mb5ylo-`hLHl{%K%4Ff#BiekJ z{<#UHZa!LXRlT`GpvV;fcW-!9OvY5u{{aC=4l#ZhDl$fkE@3@`7Q~0Fe zN{Lms%Y3ztz$`}!)XF4urDk~bK39SFs?<+KW7Tgxc6nB#*M`6!aH9|^j4u+ntULuQ z+>X(H`Ei&E+e$RaxPGurw2m!VN3Mr_+w~vjAZZe~KxB0G1}q<9-B`x$$@&LtY@Tx;NO>Hg{ZL(iUdKeW`zZ(_3Pc{JOj@AY`?FI5%DE(55uaLp~n5L=gQ>CGBbnT1|BMh7x972 z0X6ib6Xv~+ZeJ+g_mSj7JdqWCI@uV%w?lS|gB+V1+3#!w(A&XEWlp4);~`cbyip+PIEz zhT&KmCGX#!670FIbfwAo$iVo|w_!%?8Nb#mO<%mlVUPPO;wfbC_Vq)zMvl&zW=X@t zGI#S>$YPZpz0VrBfBWlCB3S3QE$@*EWw2U08NjYH=u)9VK*!_Uk*!%SGtr%dEuAZ!Skm>0H33jTx=ha9U*_|ySu~W)PKRe`Y*5EiKus!F$S@iMz zU(ib){OCGn2w3kX)_{96s%qB>2iq69+#IdvvUmD!kGQAPDJipvJNIqn9ugjybK`u< zi?Q4YFd>bK-2twgr6MLQM+Kja!XD3{MkgTiCI6%3-yEIsEzwBjJj-|O z8(XOt$O$*htq_zzZ%6L=20tESe>OIb+cPgS3yy=B^C$Yw4uvTx`cLs7I87WJEDV-c zHM7|eiU>%u1J&bYgzKxk@0aC*{Z>tHcYTNzj;pkj(iF6P7XJ9WyVUr(9t{5j9{yb^ zUde~K!?(Dc*KUnF#k4MW8x0lJgky%0u5HdPhSR*1<1bg8uj(??rkDf9*yK?0a9^Nsp6|BlC^HXoPI(a8gPk`V}9_cj8 zWM<+0;TCQ{_~SHg^UZRR#mnVDLx&Qn?1K~TSIoCX_fENLqu!Z{zj-?^l*<>GM`)|p zm6cE8`Oej^mnaM$yqrBDTH9Vq^*I5>*1#&xUjG2g(u*h)|JYB_H;Alf#aw_NMB2f) z(o4eMq2tlg1@}_{LLzSlAN}=$H7eklN_|a@MJ>dk9sPJ-ilOnG~bmp9S&LB=nmr&ZB?}b~i zVVFd|+Ii8olRn#zk8o8VEo(R`q9$+lnZ*tGpX#<#0X+~7E3^fEk|4qpi+biRD=+Xp zvP1T22?W|@-y~09`~R7L<%Rz+ES<3E^|jostzgc#iMQ(rnSgHYW&?2kB9v;a7cge= zx1HA~2%h9WHdv6fId=Iuq)HKN!wF#_8)aK5C{{nqMRLMrgMSGy5|l`4bQ8O!Z*iS6%xD=H zKL!9L5T}(3l%@>*+^Q~I81Ow*oBheuW<|%|lE@Vlmm&`~LJJIbBw=5j!h6r~9R4@# zqrVO+|BL6?#jFm*ds*#(JYgW7?a{QkW!!FKM3HeI^86`( zaf_%|1?lV#HOB6?&l&BMsH@mPvHAsi#KR&Bn)j02PTS+cgBB-z14FJ)Z)ijzI?r*W z5nn?gdDNv4Pk`2a1vwizf3A@@;@F@a!CN(w09=CUiKcaKtc7xI`~K<(Xr$FCptgR zB?dD>xC3Un9F{})OJ{{Xp#=5(EmJ}X?%5Mwz0M~lr1$8YUi1ml6%H}Rn0lsJbi7N+ zzxgdmcXonGcvR_{;SYQDqt%40lJuyDO-Y46zd9&pSzSoXv>33s+o?>Ln0Z$iA92%? z1wSPLXvwZD75&NFU@mc>!qcxYpi`}uKFexOm9UaK7}($Z=uU7r=%U_NO&%T}y<%Tf zT-Clp`azKujv*Y*#uVu`ajguDQ2{8QJ5B6vkM%Wuj6nCYF{R+2-(y9JS_UpXOLM!5 zvbnftkX5tK`@X>kalrDlR-UM>&9vTR`3Kc2Cd8f$tc9(~hkN5!;4O=0D)vy|P6*5S zhnd#c-?y5KMLwOJIe09GHq>b8o5LzVvlCgS`yWhGpw|918AB|OtArNZW^s3QW#(9n zfdDq2>xqpWtcRX`aEcGwFL0L^3~}iAoTC@#O!I%p`pT#%xAyOQ0vNix6-j|11f)YH zC6!K50i{!V009*gL`o$E1eBCiY5)mo=?;CCb?<$}FRty6 zd!LRTwNlX-%tPsg^KNW7aX(54_+CyOtGK{!2{En0kqM;Hs;?nK6S2Yipi3_Ph(jxb z8(?p)4#6WQ&fK>t*CPJQBcvzne~^0m5A$NWd4Wsaaw{?EnvFvDs?pQ?m&EKawE{N8 z91~Nm{sxLm$T0qN&zCiuI3Ss3ETD?p=1M`kd z9Pm4Bq&zHDHQv#Ap9CUP;b3Tw1%XbI;SHN#J?WE|Qu3_^WYg{9?urh(;MQ+j#dUltBT$T+HY;maG?@XjHOEu*cQ|lt^U+a1MmI3= ze{2XG+HBa7OegIpwrLqe?N08 ze8HHI+3~(Xyy3T_a$?Ml{;)y1;U#RUeF5;SYU-WpUe8UnEKj|;f;rq<$h=w_w$-tg zM5RQ{QR6=403f4o?#Zp(?)G15uD9bTy8uqgB7xf>-_rZ$C8lr=vd)a&>Hk~@6lVz% zK|&4Wl`4M9^Vm%tHe^vTv#hyXQCOpP{in+T%RS0IjURN5WWzsW za}egdaM+b6ChY{G*BnA=u>}I^IhQP+;MuF#$6mDn4DR3`cJ>Dxt3E%PZkC#@S4t=7 zE3#vU1Zhi!&CI+$p3{kwJJ#!Gu5t}{X!UL^_}ef{Wp)q*P0;x&jnr)W(t1`>{sC^(Ts1qU2EqeyrUvT)|QR28t{Wd{PXbvGC&;i z0keeEjtpFzOs-$nvbO?a6W{CN8s-Oac;3_+&%d&*FwD=olEcY&ANJU|wLt)c09}UQpfXRXoBpI&u4^-CwEjP4CAQlI9A=3G;<|@e+m(kUUuIQVr zc)&J(UkEFz`bAR`OW4w^dnW^x5F#6}IL%pcpq>|-emDpdCxCHdM3_U6h zK-(DxJdAh;)WMS9GzvFna7-e+g{R`~W4;X#Wh9|!m>4T0W3p@UZt;a3cp{)IF6GOi z$tKM5!_zRhl(z$a7T(Lt2;f&6IagpMpZfuRy$ose&i!YE-C+|OU4IJZi?wf-Ri*u5 zlB^LlHxwE5T08d35SD9=ckMUbV!lFEFZ;L>jyhSsULDrSfWPV34?XB1{yK4{GlW}> zD`z$Wdk|8|Am;5@{%`$Wq+@S2zSi!+aK*Zjb(PC9~pdM z$3==C1`99LIUVcS$!lcQ;#YM&;FWHVw+z4JSGZHnv9MB6`$1}{ld%fxkjs40T?XN# zf<#_rkyX-%oW$?}#xv+cRA+3NQeOm2cwp9Sfw=el-umR9)P1p|;l0Y~zh5H-fTZsj zMa;zfC~=SL4qVaIXk$CVH>|P&TXE;pLxO?;1$#6sh@>z5`t8c|oqLuPaXh zr^oM-W*c5UMGfDUc%W}Vc-TgfObI_G%>OkSE{RIVT^&m;zJj5d1~LenHz4s>M*GrU z+c|WL!+R*em8Woy8YcX$IRZG4))I9IxS0NoRUutD9pj+OV<*f1nc}c;9sXl0dWSfz6%kAV$0H zwi1u6od@&DADzIT{2mY6Oq&MoG2q_t9HmO4NYWq-qP02!tmi&AXUH*z;h(;Ef^|r; z%LR8b(>vm4_Yd6WN`!EQ7QS(4cp_Rr;zok6(70Z6rxDI-3UrR-fPlmu4iet2hL(;! ziNr-Zbr{<1QXh)9SsC{U6jZEiVQ_cu8L!7=MsA5=uqQ|eAi|A(w?)i_H|BP^u zSxTCAfDUGCPB*gclO+#4lLm;J+~Q1@Gy)jUb{x*h1#k|qvv{z``S4A_nuF?voh2B$ zXsu{#?F)LFa<9in5UUbPM)ScTXFgam<+q~cq7t##Uj5*mtoTY!UKIZ|BLfAZSPL2= zu&40L+rB^%tgqjUBBWI)-Ty$!ufhIkxjcdT(Nc-$Q9lQ)HmE$tmbj@!viOQWc?^)i zKP~JSsMO~Z?uM1?f2?W`4vtZ==A-}h^+mszwlbdb2q)iIX0w)X^^vVQ7{qgJ;PF;Gb8uNJ9Ah8*Ttc_ zc5$d4>vWA@Py-i5A}xY<;79B6l3%x6HRU?s8tiZCARTp-Qy~*q8&WFtX(^E|${_ol z+!59%u}Ix#C1T(Oa6=cT(1oV%%nD6UZ?o89&i0@d@8~==6PwJAdxW zdIChydV{Laz(q}uZsGv@zi{8dVZFco-@q-!YXH8;QKE`M5)}3Qq!tG~`&q0^TR&!i z&CNuAt-|YDvn8?(_KX}IJH{*6n+Y-eE-I<2_!tV}`LJy=Q69g-=ohW0BnfYSK7Og5 z8<~}m#>QFw$TL#(0bxWiDrdDFo`)XZP50%qyt`xX}iF1c1*t z*QjJ63w$o?)7J#vfv6;9q)?f%bRZeOr<+!ALxz67IIo$5Ey6rSL%fbMz7)?I^Qqh! zC+J93phVFZyI2?eX1wRJ>6^B=XAkB%w=}lv56MDL5;Y_Ll!uwNwPbQDLiaS6(oQn0~Ma{Xc zpt2V7_X^Q)pnsIJbwu}9urjKB`Q~;9e~%pYWX(#=Zp|(~;0cGD9l@uX-{P#A(s*^r zp46UOIR3-w8P`CaS%~5z3e^1)^G$Jp%n(Q05YS~PBFLWHD%TU8kpI)z0rMp}=?hCP zVXPXI^M+xBQRrHqhH=BIJtmUe#=ExX3N{Se3Gt;LUW8WgMv;cB+(f0vN=)-TfjmoB zM%{D)ob11FO&aW!(nM`FmH0gJld%^R17Ruk3%cn40K`|p28Fx(-N&v)0D*i@X_&&A zMQjFa!mH<^`| zTBqd+N>F=OD>^Y#{KUUQ7n6(T2+>oFAX&QdglCrDVca;b=cUVU71D`oC2}?^JO~II zhMj@n##AgM`*-GXvhpr)+vs|@<>M}*HbP%N!I%K^*RjI6!7d!&JJ-1?GS1Dne!lEr zuQ~vGoXJydjW)L?k^XQ+$Fs?B0c zUe@6TgD9%8Dlg353=1iqfn}&livS#wCAGJW#C>Cg zY5L9x#MNdKQC<1!^Nb}#qois=GjXXMIASGq+yLBu5>prNBagn#u{?KWR!#fSWWv1L zO8L(vR(dCwKOLnN_-k37LV@ASrFRM{xo)b9JIJWi_+EPIXz+o)1kaUp6VO~pV+Dx5 z+f!#W6o&6qZ`~~k>IBi`khd3G6gz4!X#CsN4@9GSzw_^{I6|x+vL$>rhFB%uU!ZQI zFsj_t$gd&RoH|QR_6XdZulqJIIpR8j4!3R*DZHw#Z}Em~id`9qy(T=LD0FORic@f0 znQ7ao)_OjjTU{2|v2K4d{;=+&e-nw*JuOC+7g;ra>f`%l07TKSZIv(WHfAM8-xtH; zS(x^~OVm8@qh@FMC`B?6oCA0!xut%-oR)1B5VkWl@wI6*V*QRR=i{fGu0^1>VAg!D zs^f1@^N<$uKq68kxx<|76u&3V!8o9KRnqVsCw#eRGQy_zJ(ZI}tUE#LVzsF}Pnm}) zHpY67!^0m}{H+dW;)Q2%_4;ju==cjgUN&obskuN^Jb8K|=>ExXTimq!SGey@E<$l? zdk&0>GIjrI9-UE=b_j>p_2Nb< zSuF%jh8|Ew!jH{G?cq`@m!qv0VR%p;-;v#gu?ldlS_)A1V8V|L-NVZNVPT&r`UuO} z*^!BLLpTyJicJ9R=7~)G;jDmZYp=#N&jg1@0t8(VDQDBr ztytoYl$FSQ+?1Idk-?Z)yl`@4&lC<*#Zx6v0yZ#TTV}Fh0;`YvvFlY|V9p9A^>CjM z+|`QQ;KYtIiAqA0^Qa?#xjV}zS&-WAP0CV6w2M6CkDh4IOXdFuo%z&o(UGcWdyrT^ zQDtZtJFL7h`DJ(a?ftE3jmj_lCgC#-_RuGwWEN}x&Qj;Yb;F2@UGhMigT8z$%NgeX zZ=8PQ5s#=yUK@UVAb?lh^y7nlz=A%Ft=>}ISq>_gDL$E`f1rV*`Ibvlbl%-#IdY19bmMPsW9-}n(a}t zg%&GR8cT&>ni$33CMvqcK1Cm*shEF<%Pe9}Z*)=jOa9}AYwcj9?tzD>69K#)i#7^( z?RJ+7sQwl}4l0UowI6Urw$K1KN;*iRP}Xt6Qi32ve<>QWi5i=XWCgT(dC-V-0*TjV zCy_PHOp~k<#hU&LVg<3qpbo+@xY#Vs`o_fae73_)+m>m&?Fy3af#gtv90R78Z;QaW zKR(pV=X^PR@H{1t`BkT}+gM>xe&llt%6x?57&6*Qp#$aZ3`sTb62|m@dSA%vhyvuv zz>a9|Xw6H{uWl>;*XwRZb>s&dmSEn?p+uVHH3I`slo@(`oD{Lh5gMi|5K001R`yw~ z3$|LH^$Sj1K@ z{jQ}fg0-EA*@2T4M#E#JeB0z2pd~1cVxWZPu|-h zBM-&Ra$}M z5FFYeewsQYp8lLAWdOr^7-v9hIm;bW3B=_*Mh+f~iu6JcPD~E)70>YF${SZk=1#Xf zKxq@CDpGUw5M4;lE;a$va&Mx#m(Oro{mLU~F!264V|;6j*U(I_&-Y^kAths#Mz~Ac zssr?6I;gg-!ZL%t_gUk_#a^6Hg&nzHRqUXbv8GhmlgY6W-fw!~t2__%7oyE(On%aC z82!mzs?UOqrR|ntId5%L-f*!*lL4d|{#4`=yE=C6ECZ`?X}Qm+c48cQ2W2=*M_z_gWr_(pUT zA!&WSMQk^pK@vhRYKM>oVQU&<@(%`b4+8JIGn|EJHHa!OojDD7(96u>AL=xtO`rBi z^#UUeahu`H+U>9JzF(fj#r8)U=|`+q7({dBdR1#Q_{m7ZwFw}vuJ>$n0?*PF-aOf> z&n~t?yR`_xVaKh>lBj{kDUECJhwuwdl;q9L9t6v<*1v&b_CDA#wd?Q8va9%z1#kul zmByu96IO=Je)4#m)PEUx`I|F_ri|(m5(lmF<-5jY-J4N|A98E{k|XP#pHbgMaK0oF z7U{QwO?vY(oH$d7pyI>+z8mH6$$p2J;@&()z&3J2Cn%)88Oae1mk7ohJ!cQ%5%GrI zc$yPR#XB;0>&GQd@%Kca-2UPMU6>C3Ke9mKYHMsRzQ$mPTSt`{Rl^hhFL*kDzkl2i zbI-FYE(0Px#xvBn2i9y_%-(^)uuB5^h6>oe+@zDpR`&A6zoL7vS)_n=n2Q=-^YDYs z_CD0O>yGRIUw?5Ps;%`RZw2P+iCck2xh%Y_wEDgn}*=k~+@k30@CT zjIc8btl(QXa?vA7My{&%bY$Ic6YP=)5ju;}-=i+qjZi-aZc{#jn72wfNo1CU)sAiD z99%H$uR<;ugtoj1XRs3dt6Ii~Jm5|Ux%2Qf>)@V>NYYaq5@ZwyJkJH)%`ypX5>Tuy z+e&tD@4nAvcS#qxVQ_6JRP{dgiwitjBTV=#9vzs8 z>K98TNEex>3THGwMSJ}ISr?$`t$`zl%aA&ppUXH*W61Lr5fsf=m5CN!MaPIW+-X`< ze@eL!-HxrsyXk`X+3R=O*1oT=j3N3NqcO4@FEFyEceJo~P#<)CP}yx7uxz9Q>L3M9 zQaYE*;j^{geIog0&1-}WQbiz;3@XGfBh?{51H<7^^48A1I-T9mP0O9^rw=8t-RaT>EmpglRkwW2)_x=d~V0UW^gfg0MO z`{mSzBwKTSRfIvgB&7sTH;fe}@G7LpacV>4dF|V>eTRp1U#ZBL(R_y3HytlL6P+{I zt&y{*F%NNLl7|Pp6~XN6-Y4a-HD=oK+t~&os9+t!M>t<5CQPnWWL&D}{HOK6gBWxU zG!y;6BrZ7Nw6lh)8Q%>5Hp(-uO!(Dn^`{rwZ%`;9LHGarFwPdNrS#Xh#%IE0&;)VL z^0CYBXR3RN-Uib(?iAXZ&$~@iHZXxPgd}84**Z=^scgvO@n5zRw6SS`C|&oDa_#H{ zldd*77hqJz3IcmMgxefvRiDOkj1jm#f3>$n6DZ#7r!mElWn50~yz_;LWUg@f^rowAaKT|RY1Z7qI>vwKy+t{;` ze=)LZ@(8~LR3YvN==<*?Sm@VfTsz^-;tJ!I#2Z`Xm(V)RdFY*%w?U7sx{b)s06-B? zzoB$T{N?@z8x64(?{rNnA&WHBrbY>T)@1HK zSs(eLDM*+ioPaZ7dXH1>Fe^;Ejj|~#p|GXbAcxTWt23Kkxp_waXv;T2EZ=WTI7lK7 z(if4j3X6`ae{$)|9)wKh+wo?fva0a1@zLAh+sx5x@`X1qfUh$I$=S+VjHL9cKue0{&D>pUPlRxqS$)qSo%(@iv~zlS4@q#&fm0hPifJ~0#KhvDXhNV zEkBAYA8B~X8fIp^;tWFISH$0vh>~v<C!g3^aK)X z_Z~b;0*@(l3$10}OQObt`#=USg8>wi@J1x*{pBDSpsJTLw6b)v9XhVAc9e=HmUC@g zbx&&K1x1xrzO=1?!hRhD^&>*$Yd#T;DLP7tDaq!%SSYpiuD$RiYOdxp#lu0gR9HT+ zmx+<%m){CnDcixjHqPDMX(eWnp1CN}Gl8$RWB&CDN1;trTTbu&EqdIu4JsrBf}HRm zGB|#lb@-%fpIH96z(S&kA^CyVWa1I>OMm6r%;H2$5=uBRL*>BXI@6P>3RI^e$>{ zD|>J}p*q}7hpd8EY*n(Shcv_n;i~1vpmK8K&?g6+%XK5@)U=;CiL2(2(9+gfOf({x z!87q8qDug(3YMrp`ob^@=K@m2&x{-XJ8XoPGDt2(4SFbelZf7J&3y4*5$H3i6TFhw zZzqghC=@u7ZbL_2FN@riG zApb;(ek^BKFF@}QkVt4~F)*ar{|&>e?v^%~Si(9>?n?WFd_vBTx-h=8)VPpU);&er z%X);H@>YTvztsd%D78ObkHygtdASdnGcxySgo(U{w4Cwb`A@c|w_|3BT=(kRU2qU4 z+47%|OuA_3L(I|7hPrl{xf#2qi;pygV7US$Zzh_p{kK0xP-Up9@bRatYg`~Guz?!a zkhY$F;@V2|@Aol%nO^Ax=(1=(TI<;j_LW8yD>Xp-IMm&5bvJNt-AYbIu*1FDeg^N}1T^y}N_DrvT#kowB zy4*k0?>v6j%W>FqeWf*o*7JFZ2Fcx1=RG2Zbz=S1fY|Dq88eE_oz$gqi*d4CJk(Ww zb^XYMvx?qS^repnIP5A;?-9AmY)K#^P16M-FW+Hcf81-KHAcLNo znyxYb#hpDpI^@(RTz&79 z;inql^V%lRj(Q2tBwE-*`$YYB_qK9&=C^WAH^aX_S?7zca>IEeU01x-5M1P$vRT<5 zNdMS^rw|t{?m}Ld)9~?p0PYks%fr=V_~v-$La`9KLB^169!Y_k|I&bmqS!WV^J1gA z@UMi7-I~oyk00B7`+rJtD!A0^L!QA}Ha~09>iD0*=TxrNCT%LkL`+OWn}_mVsA?H=0|v$LqAoEQMETLjNHu^h@e z;5dyR8L3U(a_8FDZGd)9^Il8U!V4RYD-D>Aq=;BM|CXdkIQKJ@b{;`=M%&dlZqW|0 zQC*h#(2DJs^{gn;yeLT|bEK~vGJ23wO5q`emH=ivDG6PotYR}S@cdJ!E@o*J*Vxgp zMtnMd^aiR=k~Y7T3kA~kvpudhj4;Gr2eWzXjn^&uHT65U%R*Bhf1TQ1~=CHIg|#aJk# zA+0)+SAq_WLr}o<$QALGWMy^zF7J zUiur&b7IlS5h?&GeJL+Ga4u<%ZaeYL1ptd7yH)GW>hVkgyJ6@0N<#0L!U+AW$R^>` zz)|m5BW~!uvF`c?CZ_aJU>>_Q@A;aT{qMJinOcV|@IAt=t_5umShJ!Z?m<^A1@b%a1xg&LBoc2;#pVvU{L z$RudE9U&d&7f5jHP`VSuOGCYm4-?J!KH_1^NGOx?zV4Dwz^AyMQn?x=E2(hu-_1-= z#7}OsX_c5ME_2*+7|!W6z`O3(Eq#|-@vLY=m;1#^y*28j%j0N{C6NZWL;@Eo)?8W? zejo{1bS+L!#F?z>)JJmI(=S!G<&)X3T)rp!Et4}|KAz$E1&jOBU3q^gRo)r*50#P5 z!x!0fnV;f{vEt-d2oJyjd#Z|ZT(i&_y%Ww#6ubQ7!5gWEUIlB{Y%d%+uJVZ4KrPpl z-%XujuW9I2ulxP zY?;Pkh#TS$TdbsY@WhSPdhwc1GaO7gik16nS#Q&Zp8v{4h;tjs13iT*SC@XbJUD5ooEH(*j8vO-3DkQ4?Dc||vLB(BuB-xg(n z(?ly>tQa|ja3w}R=Z1cSAcuNKnEna@kS++`vbLZVkkl{?&vZ|}vl@5RDrvLdtDw)u zeX|m~53uI!E)2#ka*|+BV9MEB(x_BwgX zjWRd-Gb#SqTW|BT>@{86BzVb57_LEhm(?F{5A_H_(s6W46wtw>Y_~0ioca?ZM*>vF zvzX`25P}CPZA5bcqeZ!KuQ+>BS>VODifPzNhD2*m}Ja4F#|cJer?%YK%6A z_+97oYhaPL9f#UiT!|n>T^M*K&Iq6=P{U}A+k=KWEU|;tF`d&_E|FRqT@{-_Z1Bc_`a5LQ(U+O~?- z!FwFx8XXH;MyJ7(afnS|0hE(-P_!ebQ@|Mrhzwir(I@g74^2-lVutjeugZQEyT0ru zU09+2w_G9#VFc$|_n$1Db{5+v_GaB?db=bSGcza>maVeuH&t% z?xd~D@^6G>sX*mtlR}6AX35*z0>l0hk`Xu*v~nQZmbug=Pks48cDy!Y5G?{}weln; z%VPp2MK1vhfuMeO=S{4-qZwA;*0oL zPeQBa8X=`=Gl_k2mRB9`>G`rxg?81N<6`X~vb|LshODxNqO-SaJFtcl}DRg6U|0X?jCpv zOkjJInGA*kQ2_MQnfTw`={a9+ce>=V9(#~QRKQi9l2&8QaFavq%@i3-xG3w=&5XjJ znuIl(4T&DZlkYDYV**>#eN#sHKGKj?AJCdQ=0*ZqrBpOZ{y^ciQFxvTwY9^P;OR)( zIq!m`%XT|&d1*dFX}K#L%JO0gUUbvvir>zi51>lVpD+oP#Bu+7BJ~W#EM<;yBAA_1 z*^K0!o`(;(jmlFmz9XXWU(b{JM-Tg5bkXZ)-dr;c3Cjz_ud9kvC4mq@ zq9;sC87zaJLi3eEQ!h|KU(O7Pqb3E>%cc^q0P7o+iBA6lZVb>iaJ0mCiuta61}!V1 zs56K1IdiBtIQJ%q+zi+dJdU36I`i@`JDD%%@YHeH3f2#qYgp(l!QnIu#I0x>4WA+w zgI^EqPYZ z&Bpde4O2T9W59E_r|n9*ONZOpO}r1o^*4%3NM~Eb)Q^1pE4lR8+TOFRr@T_A-@Ay0 zvy&9b{1EilOl#Wz(3-MWsNQYX6kB&Pd|~MP?O~bEg)as`b_wlHd{&3YUqd|;sHzQ} zyl3tn8gaPF%78oTD#Ws{V-&6yY?qEyo;i32p@5wq1mOC+5=70K?M*^uGAMN)ZD>@P zC;lF19c%VR-Cu!LIxAZ58$Ee6dQRA!l`9e}+*U--5`ulKJ@UFg!tS-54%buw04gi4 zg!!PNBX~sG?|_xBXQN)(CNp#Z1@a<+VU;@iFl*hsi<9=Z?nT?fci%j+B$rvH>SKgG zB?{_g!r8^uH;fdcJRqsvF-3c7L`9>vn3%K90nydasgTWaCv{HOXZGjhr%i)u43)bI z1ylFgb^~R6Re7O^WXjpyZ2L9ypa5K|j1sZduNc~s!x_%lQ4Ev_@maEGR7q=+y`-lBZckX!k z(#2?g`#bfAOT5ye#|-q8lem^%E47s$F!ebyq*Db_8%f7${A=Un$heLBb6@G_p+AXj zAO_8a2W&EnU@R)>{tFrdVE|7b_USvpJw|ySvX8Q@8qWF=H?c$S`%S`bVn=4w7Xs@> zD3RmN>eWX}@KlxSfyJ=YQ@j=Qh859!n8`deIjB6OV39Hrhw*-_pxu`o{xzZc#3q?T zaSv0f{4IWU)VTEJgnxgyC-+n}f8p+ox(|jQ4v;!dp+2M6W7=nusy*&?>p8Xlwhc#> zsT12p0(i-+-y4ZHR*-|g>k zyc9iUIy>U+dBmLYG{JNTKC7bfULelA?#kH)PKeP0Z#XF%J1dhfM-Vn*SMqgN^Cb!r zoMczKHxdMUk#ZrsD6{u{^8uWeWV!M}Ri3PZN2l#E>x*ihCLXR+;Pz{yKo`KP8v0!# zBic-j*Lt1cRhwIDN&lZ*HV}ESyEpL9Z;E!Y zCmoXuwxTn7gbEX&9QkD@vg?R1deOJM{kv8aa}0OUWX^~Jf~togoxn_PFq_19rFQ9zXekz?8a0j7fRkq5#hSW zJXYu0oocsDgLdM|*{ISVpJ*$5GEERODg3B*@6Du)CFw0ML&Wyog;H4ahZy#1m0?M) znkS6hT-7a4MS(qhSHqa*RS~#0^B?ltCWB5f6o&6`8*m*b@9Fs08Sey-f8N}?h{_xg zZ#~Jf3t=}rx~^Az_3O~dCKV_%VdW4!tQnGCOhvkWNxuV%hj)lstkmzAC5jqC@}rTD zhO8#mk5-;`zdf5ccuT&9} zGn9r2VK}&VEmk0iQxKJp=Y5OGo5psbxcoF)zUHGXS8&f`p>|sfH_dR1qc}qoMGO8 z>t+y&4}rds>S&dzc+GJJ`IFgFl2&X@3)<%7scw)Twq@T+ZlWOwnc|&)b%=FdMgvD#4&?iv|=AS&9-F@^R z0PC?L45b`?D1C%I!UMDqaMlay8_R?+GDn&c&2eox_Ws+NOw^FT!{+wqb+6t86zuzf zV>T-oyiV@;f*G8)``sV#|?1a;Vf*2!OP$)4d9;=K2CC$X-*>%&)+^Yhk*_ zuS>{9#F*Sj5`jmJp!!xK5L+-EPX(t$UZ$TsE563toIgSbYENENyn+p9hXRFnixY-_ zR(GXYpsFWcXAj5rq*^u0pyRSTnR&SqPcgW7{$%;}6YG4_l$NMafc<&{^C;1!Gk>Zn zocafUg%{S*_d$CHDXOWhxfQ^ORPrKC6i7onZgJq;daPoGWUWBEIUZehdPpe|ID;;* z?UCB+7tzC@Uf>T?k*o?oC#(?lZT`iuIxa#75iJdhctC> zf0mLGmL|TKCrSQDIv_E3#gGj3w&>`nH>Avf^6e#zJ-H|>0ngV;x1l0`Yb2bt` zdFq7e-KA0N8|Aa7_-bd$sI1l{U!S4X3yM06a+bt~3Niz;i=F-MPsRO{L7@4+&EJGe zc)3im|Qop@O0i>`zJJ7RV0Yd2Pe8zuDGV<=RSiJO5X`(1FOMxxoC#Qc+(K zMyZ17fi{1`Z@fRK?i?{EU772U!zoDttPuBSsxUPpH_)|y{HP~~;|OavG?WGaRjt+O zUNV_51}!I5`G;4u%8U3UnFb%_EmTeYoenkR{E+m^{*vbm1Ab z^Y!OkW-eFO%1cjsU5Ivle?Qg2R=g6Uv%46<#r+Dc-tfIh3GBbORTLqLp;=M%=}_PT z5&WwZ183z*Js(!T)*H$C>Ut!<4?F=^?n`L~kx$wM6VSB(m7E@b_ZN8>-d8XEagAdM z%-S32M;=?j=K0NmEJxURXJq1ip~#`&uA(s~aA0U}3wbjf5+vV?@z)Ti8lCo7oa!GU z?msz~j4QAT=g1Ec1Y99wCvv+-S2o!sfF$98BA#bxJ(5%SXGYU_vRwFwOu9;-&KI0l z(ss$kN)x|^(xgzn`sEA{<`yZ{#&>W}+RTuI=G45j=LldF8UPnh$x{MBv%lLZc?OOc zdwXa#z_3J41f)dCe>a)`P%eaf8DE(WBIq*JyQi}Z{?BdtQ%|ld0Yli!qr_^Rw^ziA zG#_sWR3&gcc0|Q>DeMz)urO5Y7HWh~ z8~rck5l&aGjkUcf9(*@y_=W4BCOB@qtgS~gqljWD;*Fu3l)TQZLs!jL_59;K7s2z6 z|G#qWJWnD}U4VdHZdwiAU#`CqBY9K)D__64_d6hnlErR5`ZkX3k1)jcGCJHls4^;u zkL<1#DArM61X^W5V9v`;_4X<^lf$>8W8K7^}SzQMy9`i6wV9^(9Uxg_^B(uV|- zeNl>wn^~aojbU^4ol%b0+(>`@Ir9%!wxo_Ct*X^jtM0GL(}_)1m)< zJJ9%e6K(fve=^1)yVqo@vG)mn1x7sL=8-@{V|fPYyt9|Fdob6+)KYBM(PRVbpbj^= z5RS>{J`Nlef?2~^j2i_J`&cn2?=@Ef+?2z=fxF-ZK}eD$4tOY?L&^ZpE$KET#bS!w-@6#=|rip(986_}tfRsZ^6N2{zp_caEQ=-&gVWp;-r{<8Z;v$`lK0o2nyHUCYZ5+4 z5M{u9h^oGPh-TK|~|!l?3F8wKM^pPF&Q;gBS_OyU(Lk0PM{u zldkXH4Gs1~+hd-OZOC zWmLh9k-!JY)7w9&kWL3)=f=%X=&u19*9wk}Uh4>2wU} z36B2F+`7bcuYZ4Rmrc&ctsyoZmZR1E`V-g4R=bcmHca*r5SIB-pZk@z#KzcU#)qs(S}agmvQMc=j9Uo7Q)w(*t3! z5Ym+*i`H0Z8%~9P=GB?%B-l z+4Vh6JDXP>NO*O^l$?7aRA@!Vh%GRGv)|9t9~uZeO5hr$>MOu%f9efN+%+UN<;iES|}QF?*P|g@MC- zAUN;e(*@nG{VwM zmKm|^v1cnc!nSQ1qhcGm(#QKeld!Mlx*U8xc#ph4gj><{Q^#(4$;<46q#wQKe(oer z)5}tzL4-Vk;g2fNP9Mbmz~Rwr^maSHY3xb1udM^Mew<&*UJeECVzsOC=#Lt%-TW-> z2VNN7r+}}c9h_pPMDqWU^_F2#wcY#h-owz{Eujbq(j_^d+^D2V=O6+i-3dW(ETFW^v-UJl6`4mt#dl+x7qDirt~4# zaD_<#FNF~}lJHa19urcr*l$>o8L~ex8)O#Gu870WGl)qk=;n+cnVq$S+3;jWqM$>W z`eBDBQ@UwVo*Q!-fQx9EM@znRX-y-|HG0UW;C+g%geEw3O@4mY^O@fNN%FXP=E<68 zVTVo--;^++=Ma02$F|^%R=YN&5e$np#`aNB}Ngo(qPneFe%J$;wi;a1&*rb`MnMqbA2f69gi00whw+Qhcu6s_`)(*{zw zI0Q1M)zhE_xgJ){U;`bXH)R#i%zyekOjERH=Ljk}Y?M$_C#blxvPz(jOSWzsenl4n z8}54bjpNLyNSou%NA}`(i!rbJ7M|so3Vv4Mf@_6J`+6&iv%nm@bMd#?V5kD_t?4M; zHJ^hc3LXV=!0~k)bxZBoZ`d9I%-HOXpA}^-^n1zq$4y)-Wisjb3f0@aIFs6`|A_a$ zt1(nqQilxzVV7_4Qui7ax;y@H)unVrx4V~P`fl@#>waW@iK^{$ z)fIoqtnnG7dnj{A{%=7(lPg0feGbH<^EFa@Uz!jm#Ep!K^S*#pKN!4wc&*|hsw3BbhzBmp((^*)vP&wz&=X{I@7_o84d#uMiDER^%3lLoJ zlkzn2=0W$K8K3(7pqR%VOlp8gBb{zvVlYAT*?5%eCghU%k5ln)dQDBURLjN~;5&4RU?}JoH z-~3XAV2i=L&N$ldy5j-$c6O7Ze?I?SSBkP#mQ_pS7f!ZHa>OZM$1N(@&FdtGalR6U z;53@fA+)zcsw2*x6ni_D|5Uyasiork_Uqp9@!HKqvW8E??zO!x^}Q|CZ!ea5Z#?(P zXnwQ!_XtF({S|Si3COzu9fw6FfHwwcJaiSg6-tuGtw%u_VL^)F5b(?5u+3fld;C9C zcm)=k0ZyTls~p!nxLE+720Z{N1yHoxGyX4)KBE4l{q9ElKmq;xdt2YfuCA*Nr3a3? zX35zlI2pz(^=u8>E(9L zzhqKQeo5TrehkVefhjayrDk`o(XXfwp$*=*D`MzH&ghL!%1F0>^tZOpd5xFT&i06< zcvGk!-@JE%5al%?+$Ui#P&hXVtZw7|5^c*ZQ)%;{^1G+RTj}!x;9hu?tp4AF*Pu3> zcxb#c<`8Oil~o|t3?bNH_A0Q(GPq-l`#Kzl#tN%3~ zI2?|O!?T{=Pb>ZA-sQJBY?s!RM)h@40JS^L!dT>z0-*4Bi0;s*1Vu%3;SLWDWMvxn35EvM9{oKK{r^zp08L1I3L3F^ zm+@2Wqnk(+Dvn-~q)?QYpign&J#o%xb7Z7DedPPxVK`=A^hf=bQwv<_9^H!(mdZ22 zmnYNSEk?@~`ITWdao%q{e+n9u-}H{$y}7cir&Tz8C!bcF$vI&}5e^()X$>}b%7p$X z!a=n!###TYZH6LDYDY0JX1RfYUFk!L%+j%j`6a@ZB?^4))N^nTzg%7%J%3Wr}YO&ARO-E7Pbye?PF z$O*?Nx-pT(9A2NXE?EdZ0wpg+zRBy8{fz)M-x+;yE(1fI z6>vYPn^;*JEuV0nX?2{PtOe)-N&a&F$4>!`B7pqI6CxnW34ePp;mh#Y)+_b-4n5OX zM12n#FM+S}^nNT~xQ-FrX6?Q2e-!pD3)62(xM%W0mJ-~jd66A>fM!uv9PnJR`6-4Tw(LF(VP2Wa_!iUTxm7P@;1ezY+nVRmktHFzX$LD@2B_CX(DsPO9o zxQK3-PbW+*k~`p|ED>z3O+1U<+tO{(zCs1{$3F@gmb&MMGM-Mi9SRQeelNe1^uZRE z8?#4%K1Oh}xvi1<;2FLw>3!}u0eA==&Cd(wRy9JsLMp%(tq<-SG2o)O8oSvN6;i%@ z4~B9TndjwvQe(VQWjolIo}Lahut~52^PGR9} z@+p|ZpLl~j+zgfIc?asqP%YJWAiuq)`5t$c`E3iQcNZrHOA*XSMPUE=^cU?nuWupX|9P-3G$Oe(9GQtm8nZKW_*eH&E56^;A#-`Rs^+=y zR3KpguxxyoG8|J#iWTRS+xcXjgx1Unj6GqT*79qz$a{7W>u~wYZ0GBZ>&~u~=^IJB zgLMJLK_x-bqIFN+!9!|rX2MwwQBC04ne$o`hyb4!9Tf_INB$GIE+?U4cU7zmEyi6p z4<88F`a;Y}50J^-hk3jK3O(C8EsCz>zzdUlO{?jZ4oxz0pHNeQ|9wK<-on5eBB6yNZHQnzjE@{kgcf_@x_GGQMqL81?R~H+J8U;gHcIV$1yqZx z18W*P?X)?cKw@q_Oz!*@Hn25dc5?j5nbOeuVJ&!qyR4sY2)~sh4oj#JT``{vvHeU3 zWM*bOPSgc-Eb9`lhWsL5%$nio3g7vN_lgEX__mrT3iY3-Srx89jh%Uwn5u&Eq&qpo z)>U{+#@WnolTx|ZBOFL?^I-nEx^^whYGY@Ux9PN)x3C*7E@q z=fhUojrl2H+XUa9RmjlL#fe&tf`#QN5y>T~x|!*@`mzfg7Iz?M04>R5Z4?QhQSIK{ z;$}8|pdAHiR5@m{?}5jowPt2##;7~67Fri#6dkbf_`TMD-#Y>xCj!!9HR`LHgVhD+ z+ohIhbM*Xc=LsJnK+$wp%f<;k;nppZYWQt@p^r{rpto~F-`qQOM_uG~gmP6-O=*7F znKFNiIBX|5C{#KKorAJwBdtQieB#)_{0vt1aBaeMBGk-FwJKb6CON|P8D{4yf|*r) zqha2h+D`GM6o1=>G}fFCSWiURvXwiQXk$>=GSyxn?y&9srul!rCf1R6NDEWdSegWX zK|OIFS#sk=7!Se~?=DKnK*9ery$%P33R=V36j!%R`XU|k3XCraeCDTm{q=<1MCEI| z!m&*mlNx8e=~V_u@wT_*?pzvnGS1pb)? zXEW^s5|O345`Kbpww~CdB99dniXNbkn=;!ak5aMB2!@eH;5OPYG+2}5O5x$sR-|`S z`46?N{IXgH^n1^>KCe@|@2z^i#RATCEi;sOr4h&qDh6`bSvKA`vYKN|W)4@2hM7BqaoV zngn(gD@l7`$VeJ-9j-hwaqP-c_36xw9J*uaYogced-t+$N+=pb*gj?BwGyzAH@l&4 zQh?EAhhNdtYT2WjL`Q}RhGeJP74nf>41J$GP%7BHgriR4Q>T(i$wnC5xCF44B%Zn$6!E5)Ns@Cu z(c@YMd4{800ExZ9Fc(yGG;*DhU8=o{Wlzzdb>GT?(x*eupU@N+J7`7%du$Ly9)#y| zDIB+@J(E$ZHPPu+);S`TTDPn3T6|F2Q#YYqd|;BewSQ8Rz2u*@-c2W@^X(m)jI&0B zFcP&VWNh+5D#Xs=$Cw!{r#vZYVS62S#i*^E-FaKgmFW05#_215~g^qK!&dmpKFBdTaH#V&oAxtnNN-CpH~+Zz=3de zlwI4mudmdViD@;hk|UrqLF`;z$ajJ|uZ1o9whI2hI2m7Z3phmr@bsdmuTO(mjkyP< zFD9S;O<&vIs<~9lN#gOV$KUx6fs&3ZT!VO&-o(OQX}phl^l786(fko3nJ9ih<7oc8 zGRF4-V935_w$IsScYyO(M;%R`98(FH@rbV%K{bg9!wU$4Zyd_k0$qB4LEUtXQrOf> z2ZhwF9+!<_eCxtszz(6kfDlt8eb>TM(wPRbO*5gQAvV0kioa}vBXg!zvDbMJKjan; zg5BNS<*$vAyBIjv*pL7g?idMAe}*$z0sD{pT12yLx!l zZ15s-rzx*4RP_nMQlzYb;UJ{1)ly1TkB1ncIx6RW1U?2W5P0Nm=srEKa)ggG8jL0s zYJtb^_qTeS$9bnMG46P&{0?K2UsFYa#k(5^!$pBjZWq;bY8VAcrLB(R1|M6LArZDu zsc7zP8C+yhyGclo7sfrriRq49yHIxlK9vIeZdEa_*8}=k;+ej(hbshLp9?9wf7DHF z0=yfxD?FbwP*DrJclo~%09x*ly7=DI3;ULF1V?o;?-y{WvQ2i= z5caOgEKhE&N9l;K78WJOY{1Uq+H%N+|QaMXZAnMu0k~ZHsV-Ou01K-?FX?V(nQ{mfmvc zu!giNUkEdDof&MqsQKJ6Id|%M@2>hkpam6N8IWWvD2MZ>34o4sWT`q2vU>Mpn$p#o zD*@KvX%J46vp*dk8_G%$UF9|Y82zw8B%8qv?}Me?E?4kSqdimS(M=wLkEL2j3K#4br~ zPrW%P35vc+wcWO8Q}7QnY<}OVMF*4$F`WWACMr(@yuGC}!LP8Km2l};73Mz|+UgDl z-frXil@|ajGJ`)_>ykaAP|2oWE?SP{hT?j8TijEfJY^@tUwS4kr2&^cZgBJ zB@@_o0E^t1FgDPz#(U1`F$4*70B5x(`+FdjY;c69c!-wgn3p^#1t~Vuv_|fL_3)HOlx{cVA5V}TbVU#Tose4>@hgOi zpZ^FJ)Z}yF1*(ACS>;d$|D#Ada3gzw=)iDPzh9~w=AjoxV&b8|wRfV!83Xl1BfxBU zZ`qhM6KU4>3oaR=vkuQeEzAwuByrh)mmNn(tqcEjWKD|Eov zFOa>Kj?*hZG?Ne39f~0KP7QO=+zQrX%kY@_9$WVS7^}J)8-g#O-sQ?l#y9;2AVF~x z+~EN9niIUGRhlXv{uu~$p+LA7!Rd<{`QCu`nbn>qqgz>Y zt0?NGAjlWEO=`d%!Z|*?JPE-Geynt%@CV<-ncgLj-uTfZ`t(8P1>+hehs9Wsm!`BU z^)Z8O16d9$VE_m(w=sR<_ceU$oQeds#kzM`J(Ey@YYLvZ%Ma~&Sx_;g8u;X%#Xf;k z9yH2@VY04`)cM^#Z`5>rMFQv>N8WZ4fHN7^x3-#pe7P(JWL)O}CR7T${)m!h;w#}Q zOZ|P>k5Zhy&_eofWC7~QQ|%!SmMoklxywnY0A*~W=?k}6%!}dz{-Z0PH4`fm%R;T1@Wf)N4cc9Rofk}*oq+wgA+)rq`?&ARueV<1;pRh?KpM9 zbMvCulKv@aHJhzHaW(g%Mtp)U1%`nKuYKBe)Cw%UhJB}Wz`JlMe6koF+TKHmu}{(c zUqC}25HPxhIuaXdw4U6EN$}Z=*c_tUR*Kj3NieK|zdHP#@Sda41&qD$%57rwX5)yy zDaixBp&V`d=DLDln${|MXafR*N z|7nXJ3#zKu35GC24C37N8Q%lO?Mw3uves**7HK0lqsQog>qT{X8u$oLU*86Fb#+46 zvrr?zp_o>Z;eVCy_Xp_yi#Hs@yZ~PBID3lZO$CSHmCMNecciWhu3BTml-a;}+45(z zQH6`iydEAyyl?O^LuMqS!Q>6_InSBVU6-!<=T=X?HZ&M5j~JMJo2a`3BHOH&GmGZ#rv#< zi?Rn=D)Vb~ue+Sl{a)P-QwRM{v4Maux+268WJI$9wRj)bgU3im_CeGW5>feeX^Gsf z-Tp?sR3bKU*e^AnYd1m6;xBxy+Tl0EgX*TsJLu+4^Y3e)p|o3`{rwHxghn@8F)+>l zVEspz1@4zcIzB-7=FgYU36r~um>ptdvBO9DM*rxdXrkKVI)|YtEb_i!(8U;3T0atnud7tU6m-w6!g4C09SVqSVG%5aTyrcaRLUj>am@B<6bDMu~!wQalus^ zp7|r(E)K-VuS#AQb#a*oQa|BTmfBum4od4Sd)LGl|H_uk=qq%E#{n{mispekbE+Xh zfX-E3)Rnh?e!(G8kYuAjl=!fQ7;Q{yZ|}*Fu7_G=zYe;1gpYxo7H*a}l)%OQ)b_YyJ(+Rj&szTDLVUg=?PEic-^(FciAUS0H}{wVBYF7 zdnC@-;?Jy+i*DDC9Rfby1y0E|eTR$e6QePrJeUHJju<8KwLPi}Xnjb4*Hhk4ZKN51 z@)i~m43$2xxU#ZBlK?^&C-cWA!sS>pwEjV9{}-zrihCNTD(@0gG1)P!zp4qa4^d8i*)EfTft|wwqssWE;^vCr z7Vdp2GoyxPJ<^lDS7ffHS5g%*MS{Ay8(bI0@}}%EObrEOyOo$1xjkg>`o&reD;y#O zU~6Y#*6fj9B&ayKJ5o=*-jLAZm*vd4z9`RF&`DtYWB>c~5*>v$=LPbHNWJZAT(IQh zV=dSgHCx&AqL;xdIm34E82=ih`3)8VPHTDvn>+MF8pgSeNNVMuMXK1tL=AP5D`*jM zzo{Y-h1p3Ox@)N=(Unu=Jg9T8Qn?4QL~JH7y6s}B6VmAD=;FP-J$rQZ@`7x($Vd&T z<60m-%5$lEeQZ?7Fl}*UpofLAgEXZWeC~6cw2f2;5yt;IUC41GL*Mi>oMswk@&l{l zk1DX)(7>x>{jNQj-?uW%JE^uygNES+0}UO6L5tTu@R|}?)@-E!wNrRpN5?GiJ%wW&-Q(!;RJP#6EU(a z_q;W!-1AKvw~HY0Hh(lpxQd;VlhEPn_hK0P=G(q3q1T_V#}MjGscz0B6?9#$QU)z%CLRaQGVCzhz zz?nKYGP9=2uj}HT9EZBY105od52DCJe1l60^rR*Cw3ReQEr~@g#;ncT6WAl_cMN2f z>ou6lJ#*UrLYeZ}Ex47f{jg$G?A+qsqkf?2DT)a4oDSrJmca}N70S4 z7s5o0Ry;riX-*_pcLpuX-EsatsQ=5WUu(kXv?XTe`(Pf8^81C*PT%CT^baGb?HYjk z>T|3=ILhsP8YoyhV<#N>ru7z(%@2Df<=a+RF?4|W zY20f~xrHB-XsQW%k&?sx{gU~RC2Zd14W?3-=YL?~^#~O4t5)D zh)182&4Au#$T?`PQWY{P6TpZj8Rx*!Gpid7u2av5)}e_v7v&!+gYYUe^S2rwcnxWR zR7$UZ6^m>PPMesCm9>di-~$D?z2iwN7MTTEgtI$8lp0vE7jplx>LD#$Ls}>ae3bCn zUXgtFs^Fj)#HKnjF5_;#yL?1|qGFB9atUucRb%`@ljF>H!1%&fa`ygON@s-C>Cu%S zW^qH)UdMCqrj5Ey*I?syj|>@MLkrK%MN&Sn%gp0KrFoHC>c*%OaJr}de)O$2)NVG0 zf&r&5WG61-y*mp;e9_JG&=((a<$V?bX5jSn4Gg69sUjjG^hI4xz@Imp&g;$Rc6W^8gnGD<9YIyEH9_QE zz`l2kqPCr3q@Sk`*?BgX@Z+6veYDmgfqx&;^Yb^8kX`CoAv>ty zcp50+MaIPL*>c$GZdUB#mE8S^y##ouisFTzp0hW3lmMR^zAf~QC!vaqh2CW26P@pv|A#FfXMZbmP+Hr(#d$=dorhjst`A% z%I0ebd{hKn@NzFL#0Akx{t1M}@I$<2GHi&Ej)DihMmEo3`F7L*>8Q^wyMSoIF=EcA zSc{hZn|*GoWnylyCEV{rbGfOPV{WY+YU}v9MQ_mUrSnD`JA3DfnmbFS&3cpn#{pSw zoL_L>``ANetW(lX2_(T}t^p)a?kd7YzQiuHV8f$&YruIjE{*!tX}zZ zA1d%5+Fz+$wW1Zf?p*Qx*!8VYExfStEGCnxVQ zNqB=%W`!Tg_tpMj-w^PFRFp7w?|xF;E1ZcK+Enz}lE(^g@#&e8ga(U9LZi40 zP=2E3e^Iv=aWe?zz(rI^D@6LSICIyKizv*5ItsUM-FLQ}3yfi2cDn&4cL#Yt2anHn z=bJAj*X30SGXPXa4dlqgUI0txl9^8mm7M!P^*O&T{~ue`MF-BOdmke)9GtI-U0^bt zS>Ntv#5OheMRdwu;4K%N5ujT|Oz0G$aRaY8QK z(A?ww&azNin#<1U>BUTCe+2JsfD2)45YH5eaV@v`@6(QM%Jh@}pAJs+O_To6PUwHYP zXkw#I?^J(rg1u^na!byf1YnBZ8@P_;YrkDjs)NM#<+svAtY`(*ZBX3VP{qEWCE97_ zR{_zAii)idIbOz#JLeB*5k-7gYxf zq}5JZ+aPzf2t!}^UMA`IB~*f|Q(QXVZ6zI}aB-VdMZ<`cPEw<=3R3^|ptU_gGOYATU0rl~)B&&B#PeKW4|9|$?yV(W9zt*xz6Vq%pr0ietRE9p!7 z@1NpQ2$74IAhsa+;L_;cLhD)( zD15{tLn-)16h1d53<&Sm5_ZhW+f=OIFMkpQ6p0TD8JoG5mCrP2H0A;?hH$kw@t+st zR5>t!+ruf)&#y7cr`QN5WhPm^>lxpwWB#B)lJQ%*9rG*eol{Dd`?7d~?!=IQP|uE) zjZjn~l0xs~eFy)O-&-CdUl0S*_TS#g6tBzLUoRNa> zCVkLPq2TZ1ej0Tx>;r@Xd+50qA_8w#s3Lr}@_QBi<{I79g)rPdqMRxN@MezIZ|)Z? zj$Tl7-QIZ@s-zw*-SU4V5aoG?tQ_%Ro;O{o(uj_KJ>5wLAClaU~a^s!?+IBdvjnrSHe zg`eEhuE$VKP@xUbzB-R?y>2(n%JX6}LR}$n9h!t=c633wvmX3BH2C#16@G9!iNoUX zO9X-*x6DIyK{|F2-z}>@?0(v|VF)+`-K(h|^P&UpXnxQ?rlSL9zkSmsCPBqgDjp#d z^U3O87D1e25c$7k>}F9I-8l1a$*1>~U9WiUhdLs35R1hYbpRfnds&)R)9SH$8RRDN z(&K}7IApIi1%CIuKG;;4Zp$U1Rb*{(I`PF;abUb?O8-~6nGYq&DhVn_$E96@ja#eP z!^x9=0@R<&q~mrd_@oJLNTbJmw%Uolg%h#K!j6;*U`X=aU6Q9by-#0!WxpK~toBZu zyJk4(jqVfA+yybOy-LEK;vud9&nYj-8=n7s8^46@bRm`lbzbNGNttoN)FOaze~m|h zTkGYYKWS1UMbkwzvw>Wdn&{9;A>*@*phA*Luy}S2}Nu)+B{(_wI4F z?Fj^QTg+(^_%J=!XrSIAKx5x94w`xfji?^W3vwc1)R2mGmx=g1a+YwIi6RPtzZGds zgmYI{SC=m&8!N*{sNLMS1!Cd?RDod=_MJ|MtFFLDKD7qIJ3BiiAB#yn2B{2IE|ALZA4KicVfRFoK^yoJ|cBJy*0m5v*VRk#r9sEhK8 zZqHIhSFo*``RDE5;8{*s@tFKOAd2TWT|#+EP6 zVAxk*aicBZkHHs_&1AUaUVE8c9YDuviIwyCk?0o31k12K3Chtk$)PWjPK%722-kUh zd49`Eat{j>P~+?7$7FWguYSPJ5a=+;MgQ1p$pL5Ycv)}Mx1Fztk>-h=wp z&O_71k9NyqQ--i1T4%=;vrUgK2=M$_xMm&2w?4t%8Zdx;vQ`A%S zf`z9#R3TQka$>xDch}d~Cldt>mYk*Yc5Y!2VukTc?)mUQ(f0ESE6QTy!k}^HI4Ez!FQR>y!P{@jW<#@w zZ}yT!2P04mkI~9>1(QL9GL37)Er{?-7RA3?kgO|5Epr#X?Ua++QYx3tPp6War)M%|*+vk-(q;H4` z4Edmm>S%?G9$&8R(Vh9GNCF2RlR+rwE&qN zL=Ted0wuFdn3vX<|IJm&tixHvk2DEZM^iD*NkBdoa$SIIOlZyxX#6xM1oHC{514t} zaA0OSpr~K%7dExnDeCR(?{Egv_OTtUFqFl@1o6o9LpkZxI=AS$qAm1Pz7wbAtrxdK zRi^WzeedLO0 zHJcPAumFd4?l`iXgo*LM&VeCV&fQ1?B5{|;B9yd|WacOcjEB6x_D2MTyj4bpD%c)r z{#-76-67DcaRXB;&on3T(3n8CORGx}+}$Rmq9E(w=A8Gt6tvu!9p9wu`Zk})hjsli zKflgLetokif#gkKvx}2WJ|xKYdCS5a-*QA_xsf2pzy3Y=DpRfE-R| z7DBf=iC*Ra<=|ou)D-Y0Ha7Me8}ovzRWzEwu*ar~_l)sTsmVG09}MyD0Ll3-Se?jg zd!k7_v|bi41DGC8tE!`jObFs)8s~&Bl7Dj!){pzhb(P$I*iu%g174IrySrt=ZE?NL zM$3eHHuE_jG00=%&0lT$7Re$%*F_*#6ac}gxg?ZMKz-{)8s?q_2_iz#!t2TLsBjJq zwTu}2NJ3XcxfM1W%KTUc0Ii3)@F;I0bX>e!%oK1x{!;zV&yfQyIB?UK zsg?4YsCwl+C^8Zd%v;a&1QWAE+nVuZ`XMFr8gOuZ{V$kve)#PqS1c&OOkE3>XlZIL zQVDmkAbpWYL=(6^F<2D$Cwe+aM-+syJ%h~(_mnA?&S?mDLl@1Hp6ZA$(~aQHqgEd8U^&;>jL;KJRRP1_V? zIkTqJnJ=T+*V9+D8k||8#kgH$h!ZTYw>>4^!~gWjlt4!%tLivFY)%am{n{I;{i^fg z#^>7D<{ONU={POpEvr(jHz>;Vkmva+#+sA5-=?P6$;ip|2D23WpLlrew?OovgJ03V ztEMwANPFSyeYO6i;=A)TE0ar;+#*+m>kzjNzws3flW49uN{1 z=t)aU8w6aO9q%qIEbLMSZQ~t@>HTRDqzZYfiGklA&=NPyvP-Y16*C46<)VMYaSgb4 zHEjaINy|TMxt2T1e%l(`=`T(Uwn3C5tjXVOMtaoju%|d}yU$J`Jv7>X@8Vm;BE3h- zJnYL^K9L>jZ5Yid;H9i`5o{^Y(4>>pbck%KQiiaB^GkaWG4_Nq;&7NF3 z6qO8_0`fC@E!7d)%+Rom^4w>bIAScbu+=$EP!Py>nrUr0JKCA&P6F5K+qAUa!B8r) zH+Lm17faqMeo?tus1^bh&v7FMPoLy)YA=`z1bgr&f0D5LPWoRQWB&yvp(zqqkX2`y zF;nAWPSWY@0>nRMSo62bOk?Uu$RfKS{?J6QeT0qOCKGo;I>2z?F;_M$Z1 z_=#>}3L?=&&rv;#hh}Azir~qK+198<{q!XHXiX!yj4CXMb*w56#KD5b-vMnUW{rBM z8%d+()YxXERX_fN*Fq^-USIr`V%UMMsqf58m%F-3r>G!{S!4o$D=pRmkmdo_coR7K z9bBK->xNXVOI`v&4T+v?&dZ5It_6>OQa)di*~TZBTw#J95O}(d5tX|_bKTDZRoC5h<4gDd zYJLP#P)@B@k|r@&siDU1l1T#sMAgsZ8&yzjK1{_+nMJyA3SRJRYl)L}5W^irkhH_P z9nYxJpq4szDZQ&LphYmXjr><(E>B z^iruOf2BT<>$6-6{<;36Dp@O2))RDGAk3lAe)-2i1+&A6XrEE?8EqBA>Z#C1rSP@&QTh_~&@*PrtaPX+XUcg~gu*u! zUcV=1za%^zQ6aNX_ipwX<|>Tpz*bcB0{f%NR(fl?MJ{M3E~> zx`i{}ju}!*1%X!u?uY=#vGDU0JO4b9O!>LJoQ){#Le4Es!V#SC#T;WBR*_KG)Y#(o zwSS*fCR8!-(*-lvs}rGZ5*T4yg*`JfGje=zkDux5Uuan2291u}mm##k#hJ56dK?d) z4ji7MyB>7$DbL`;)^%|GVI+V4I~4y-S=pG8oa&Tx_x56D#_QJ`9(#~!QP_3q>_uWM z_oibDTr1Bk8?VQz!qccB5lLV^de0E2MA~~qE*M*&1hf(zT}j~q_WCKj>=rdlkUx?v zn@CVz?BkrqX7%^tTF3=t+=jdat@=N}WEYcA5*i(^OaEP|yQ2}}?K5zb%a*?Bzic$J zfmo*eT|LME5R>Jix=w+xMm#mc^CKiQ9Sq|Y;wx*SvmK>e3-yaDhPAiqhQN>`dFJx& zv)|xXo|-dK#DDCG5xS=CGDE`cl0b~i58i-i4dKnHro*|WtyYtE_zg)Ip__UuWU1O; zptW9Pdy%>;-tSgiRn2kg_-ey&G_l{Nc#Iy&yu#BwM6k2_3Wj<__or4fZ49FuJ4gDG z93|N(49oZJ&(HxSR^vTCu9m%}6us2hOe$(+9)#od=+HA^03t&aC|fleETg@ea zsUsPL2gm$GlmF^h{+bxi32tIj!&Y!?Hn`>1;wq{=HwIf6!ai5o8NH7KrXv%+|zkG^+BMDgR zqVH>|Do1O&gHrZ2Bd1WMUg={3L?8*w-Jk-iA_zten7M?<2QLgpouMV{?`OZ!~)jA1D!0?bLzlRu&@(h2;jmhz}XtW%#RmG*l*^ktS8Fq>&fEteg zqM?CcY6gJRgEjD^t;NSb$L>mJ)?z(7at&!Pu{4DmaY$F?tUNMjx4I?(1#fMM1FOm=%($vm^nM!8{`;1RkFc7@Kj}(7|Q5o z+)uUHwo)H`QhQvN3H3(N3#-gd3E9~7o{A1%%pT4cJb=tIs*^{P&uDq`E7-ALPq*5% zV~M=sI{${OR?3|GLwouBR1yNx?b5_uHXYaF)+*>Y`%~Rg7$e8%Ia!$87AY@!9QVmP ziWLPxCsWV&HIT9U>1E|jmQR`ub>ifC^H*PqjtrakiI&LcAh5=3(nV|{p0Na7$s zO6sBNUr+PM$-J@^c?Imdt}EUNzJ=|l#s+&se22OV|TWW&b~@EX1zn})XTsb(pO0@IS?h5IoW>|f^K&0H^Rs4u4(xa1Hzd%k+fT`A{a2-RYvUkGe zb4u3c$I87jz^XBau86uj7z_`AP$@B@f6D7N)hQv0R>VwRt^UurTgJIF8^Uo9!+ zfc$x6Q9g0s#WTrF4|O7>9x;=ket5_#5DK8~Nvw8~7XP3LUpVgh(_k8fF;PQxoa(oa ziyU}E(&H$VL_HgdHg4yhE0@i8QrvdDP|v}~UcCR0tv8Q{vi;k~uNh;PCE2pJ*>@FL zCz6T~#mF+2klVhKWd@Wh_o-?HltFQrERAR=MXZ52xMlW%0e89TBJ!Sf_d3+dc+~nwgQt z?L`(^`#vVls*Qx0xu_OOw4U|2L1zdlt$d6wqFe@hWs{!y?O@!M#oIMk$W?CaZ$6wc z-mYI&zo)9fyb5y(nnAeC%TBIYs}#(i7}0A?mUH0IvKSg0OBWCjU@l_>UN(f>NYE^} zNex$^)?U^7gQu~(g_8tCH(vEEx0_6SWa^q`@nYy}XaG@@xF0=T*?A#4iLzYyGj+&9 zdL6@+md0t8m!F<0?ic_P=!Xx!M{1DEVx%qOtCaLM8v_M*i3St%SDEh(oeaASBV_Yw zUj2lg*^J{=bR)0%V}s=7c| z%!G`>P-7nX&91=L_~xcFrli(M+egfuRM)Q?ZgUMCk;<0ux0(clBI>Uvag94iJ$uTx zZ$gZduks|m@wuxMlS?llAsudec6u<1TO^{Jq)-|3QNFYN1c=usm>^#cY}lNS96b+i z66(_S19n#|~*N}L}hS?*fG>3_J69r14BR?&FRntT?Tj3c7 z1ab0ct!{mSilkK=NY>K-;fi}p&dotMhzhk&8&}B5G7HCk7 zs|)lp;JAky1Qt?#<=6r;;XDla$&rzfbu5DF^#_Z2*%LLs%YzILkm3*mQa`QwN7IB} z-@cu0Md;XTc1E;c=4fkrtK@bksImAdoAEM=%@0C1MRx{UU0n^!Ll=aEgwT>OPX6h? z$>>f=UPLIc)px zc-?BPDaHc!^^6}AB0YG&?x*FeAvaD$&*H7ZYjn3Rq=1TnZ|9laY?Pjr*^K-3hPq_D z^39iLQ?iDh5&onoG~W}l^;Kj>>D_B4bWArvBb_pp$;anak$2t<)3sec)C@XMMZYLA z3gap!Bu}i+m^qfjS2NuLXs57%5~D}F(!k`T21^7mD!4grG6YZlW8miwdMYm~P!#2b zNec1Q4xjHrKhOFwBcy9?DN|(wjut%nkb=CP<}22mJrH6J9pQ8*#01aB+6d9>QhFle zQ%B=ZRlT1X6S`x^m4(GO`*2B8eUP564ip5Tt`a>is#QwQz`!7QZ^SVXi8|T^NskA2 zuA8OCL#o(UzK-==Df#sCDHMk-RdY3&YY)vt_V{dBo3Dj&+wN&#D=RCX1UNi=xWFW^ z0Qv6PPFZkP%!mF)Bm|g)n9I3h0#ik_yTSp9HFLZLaqji2v;&p{hp%iFTGp&I>$QO* z`BNyeVle{+I8({EQn#7hSsXhg9Z}*B$|r1NZxes~)o99^3bURyZ~eO0wXMvW98QW_ zezZBRJ$ypw@g=yV-uL$IvatrUj0fdEazUXN@fw;LFfE(;$sk;#i#W`x*CUn0HamEh zuV(#nb!aqm6vlxwRMpP={Hnbr74_YuiulFryj_I6phu6+(ve5P!ou8E7-Yj!280Cg zZdrxDm&UVwuh8_3!aEA?_MF=;5>-lTFI>$`TR)%Ypd02ulL2wZ9-C;Ou!hA*I>!Jo z^~^W2eExd48OOeVt`xP?El0h~E3NF=e^293%#W%XHUzu3LT6~~H5@Xmc0W`j>aDtV z4i%KtTLi~vKi;6Mf()TMNKP>&0pp$h4?I5f1e}jVooco3w#BT954Vo_z6{Qga+mA< z{FdZ!$%Oe4?X< z3k=O;3+a!#PXQ+FujRY*`bNuKOl@RN0m9?nLKrtL;%dOQ3vat2a7~sX^Gy&}<2`?N z1^n=ABOt9wFWZ&)TXzLkcx4f5%?6oMBAtaj9Yy|YtgJ(KAhNOx9rHcs+LkO3w6F^V zDEa~%Xb(etF=sajIE!7`mq(y1q~bcS?dW*y@tuM=W-c#!UPWmzeB#Afoi#-UX$rAW z<9-ncgcF5C?DoNYwnmNrx|N%+?~lQw^yib3a{!{}d8~789ih&Y0pJZ+`#ZGDr=SJA zCBgj&en5V{H{0MU#AEOCQ}*@Uy}hiDjH3TN7zcrHKqi`gt5D8n!q)l3>$moqnOytq zj!TYH8A@Y6X3x4b>4=1#iCov5@RjPSD^^wAF&2b>4Uc{*shV%O@R9!lbr;I0mvwi) z_MyvnZNux;>>?Jj$~2B>57i?vln=t~$*n*VOx6&XTR985l2N%z^o z(vZeu9xW7p0si{QAR^B|%RXu}|I>~YDe?)s1kk_0-AH#H{eM!n;BMZPV)8<82K9zK1>!pf@HI_|T4Ff{fYN-k4ByH%^p6~ghq=}NQzq1qVYc@xVjpf-2g-=n$;$FgPCN$S0YWyYWNA79F@S{B{9UI#OalpaXfNVP_i!njJkd#N zS$g=F!8(yG18P#H0_PAW+(S^q*!-yJrjj*S1RZ6m=gC=i6Nl)M`E|vxODW-^~fWZ)RapPu!aA9P=RUW33IeVR~FnBkk&UiF236 zeoi{u8HLfUpnPr>AEk^l)b}L!Ox? zaq`;qx|KL!JJq1hsq4-$)>mX%NQaMke^)$mm@VfStuIwP5Dl^iXzmI1)3;zMre*)d zB7%}0949OoGHd`^nUdw)e1|Xmg#lQ%6nMC@lorM9L~NY_H+t^7*7T)i&tSpOyJu!L zbWvbgv+*Bi_IQZX&eN}>W2U!6Vi`+Su0HEvx_C4Gr?l(7V_@sq(jk}-Nk%iOA!L8; zX8|&Jvvt6EsJL5SU*81Jf^Jripg)KOMbEQEw#LxX&>@==4&bs-P}h-CsK7T|g6rI5 z!iY}BydN5k0M!mV3t;1pngfCG#@^IIRnEwVvsrn66hl0lY}oL#mw^(F_K zDlsKnNuu!8Z0SevL_C?cgp+au$DNN{lW#{0%xwtG!O1f~U) zV0?x9JpRQRzp-1OApD%QX1QR6h(@o^fIP#`4SFzR4}MXWTLo5V?V!G*-`)r{s=2UZ z?9A?8I;Qas_yP|`?_TxU%kW;e@PY(GJ^0Ev;6KBg1WR)Lg90;Upi*>()-o+Gjv~NH zfI1j)%nsQGVQ;am7#z}!&3t)kN2>P```poRzaKg4^VkSAj>a(P5R0u(uK2u!n9ECB z-?7&4G#3S+lGHbvoSF|~xMZ?!-@cvMZiFs#xf~0eC~uGFn$5VC48_<@k*LsoFTbLQk;37W)2Fs8yeERt13{E+59de{MQb$ z0Dd#a?0t$t_;Y-CYb4Mqc*wLJ&iqR@p(UsbrfbY_S<2&9M8m+#%4}aS(7}&zm~ZfZ{H#!206&A^KA| z+w1@_c%3ON(fBt?2uz!~ihKOaVbjFE(4B8VqY`Fqc6qt^HJfQvL?i3+Hh&?^D3Ad2 zNPR8S;tpT=njrF#`@2c&sn-hx7KZ4JX=<*c9Y^Wl`OM*IA>7I7w$%E~GTplDqFU1i zI+qkckK%ZSG#RvkZ%P>|L86$}DHRF|3O|^K$mvGtl-+?b{_8rc{%?R%#^E>4nhnVc z`h#ZaCS~+Hob9W?#mAf%Xk91zq6I?(rhfWQHauyh^+2dt>HgVBX+ecWD{AQ5If<5t zwAN7mffLIRhb2wLT<#QoyEG@ht2g?snieOXhnaouFhnEaQ9v35; zE~B|Dch|{1HU2U~7$ATFOzCUu8twXuvSP~3kshZn-4T|466f}}rJe#kO{Eiz0C|rWg{RAFsH>Bq3}Gp<+DmIo zOQ*HZi9t@kP5SL6g#BcfwHZ;QC|=EONQb+wo(`nL`~2$eJz(vm`Y_*9*FUmd3PTTt z-lwvjQ&+e$)nB3e5b6v_CsgKN^&7uwO=NI5?9}Fxd@U$RJA7XC{2{*DHRGwcy|#4~ zjL>V|#8bHM*(0Z>QS(H))P+nuFsQhe_iBrG2s>Jq4{r~18h3ApGw?~6}sz0RUSGndu(Fnkjn zNj-id=gI0R2l3>NnAfjg>#k!dWaW;0;CF5p9K=#X*!RYKZJO1`QZ;ez2^VVPW+8)7 z4h^Dl>DqY)b<>nXTCOG$xbM#Sj^f%iE(1$0AAs%ELzqrT5&u4)fCj-if%m`uXiq50X(-NMDxcbH6T%6sx>& zO}9*+Ukw^|r$+yLEXd0`k&(+Y=7Lq*>Rv)%ni+GeD=RNE_C8||*vwd2Ul+tN>NEm3 z?*4w<_<`r;k%?t0-W`g?s^a<^|IYa)m;@xnTOfSDZInu&c8pVEK9s_^Te~P6DGmPZ z_JhyL3|Z~_dQuo%WRqw}&%21eAOTATS@DU{@87?7p-Am0y<<+GVqjq4-Ba72e#}`z zD;ifoMq_R$Nr-3*o3(I^ zY&beaPsU1`Sk(8B=^FiS)PRy3>~yoL+xRIUR8JsuqCd_nb#dS%&W0XN*Mw!51d@&O zrb{R}2p`K%3F)Qqq0r)GMfz|N^PIOhrxt0#`7eHT9qod3OC=N;F3ZL)GtHFdK)>z> zE|#ShS7ClP(3CI>qDF%KA`4|6MV=qkI2zFS83LaBKCcaBc`m!P`0Yke%JdWvY1#Xo zGuMd+j*8HV6UqlLvp}zLzY4zyPV<`9m4xTq<~(Efb7as^>t0YV`GsPaB7+Q7O#BL> z%HOG)CpZCC*{dVjn^kT_(rJ!08btTq6O(`>{(eaCqW?XK;?bey4_q=e%`&LSA}G<5 zsTPzwgU%o&Fc3|p^3qqKoFp`BE|qD+PJBT3z@ zP`!_jt?n4vmR?!(yIQkiw5%(QetXio2Bp_4oMFuLr)25XROIA5x7*@)kv2w$DqUoEYo|wE&@oe> zw5NC5s7nD6DCG~J{Ousm`LcdqQO+?Kaf``PGBNa zgckfh#6uV7U}uf}T|OrS9TO_$4;wiJtYl%Rx)dwuo-DgCJ>+r-vUr>e%x06vXUnv6 zIvp(ckJc^r-?U4AX(_}`R4U7}nlmM#j`oYUBvyn04QLZSM>n}N4xmbA1aT<}rirMK z)P!toVadx_t5EX6{PuHgyOC2VdJKn+v15|mC=-eKCuwe+_mdT!>+DCsK4H`{HlmXE zfl3{HTPB|{VGR6=Hu~a6ndE2|!5%H*7L&{iIZ;TI4ZR1a%quG^&@%8_V`{xlZ&<1b znOx7DWs2=ynH(+a0{x0r!S#dL%XNjs#I4 zp{bA{s4)S*B9bGPUHQ`a&X0?wM`6)N!M8}f@=ZTGNU2T~S(|Lx009>4M9+!RA=`t3 zlE(XyS~yQ7niXuo=Jd$a)D(L_*$oK%(eJOMv>hh;xr!lURWU5vH8^at!_1)rLL5#Q zn>L`^CWEa0J@V4I6b;}0WOXuc*IJ8{5Fd%!$%W_1PpZG!We?T-1so_XpQLD(F*KLO zDX&&cufq1waB2#+6R}V6adTUft0bk1bH)r;m6vg-*&_sQ)_k&T{86em;d&2Suyu47 zxX8=x-j;Q{z@4^rNly&#Y!YrEZ5p_@Vzvkx-akhcF5*yD zg<>FoWXhpHDz&Htz%?`k+tA36Nxmh+wl)p|xe3s4=!hq=yviRw5R|FnpPG!?KZ>xq zK+C!w3B}R48JNrWj+M$&FbIcPj2kDrFmZ3WF!o5>gARc{Xl)+IGdSjEu2540dnY|Z zl&T}%|LbsKe<fZzx-R&(3z14CBQzLgp1xZ z)1yWYan;$BmftVNRDHB%8x{_`_33_QAgDjA&>&5*7=vc_2)RRsIy`pT?=gxTL@bvg zT91TLi}&q`gV8gG6~PtN_jo#2h4ggI#|xQy{m}CoADEe#9_U=Z-fswHdM(K~a8?}h zCy&Sc9BxFI%k4gkTe{!6^Q)JKEG>W-n~b!COjEHJJ4sSM>HLP|f>BN-!74M*M`M>H z=Pq%t-1oeWx|ZV&WmR|sLa^+X9ZFkXcIe@*JBm0ahIn1lEC>WmX>fA@t4V;1qh_eQ z!_Tm&hEiboFC3`NH4TEMQ(3D}gsw5Z10I@i;@Gt4T=nSRaaSC7jB0#&JsDTDqS50V zzvbJ3bdhy7$esQy3}ToDzx{kq_{rFn*paBF4$0MQM|E!TPU^&wE0?;Kdexs!6j5Qdc)qEO%O5jmte#1SN^Z#0$k!bqam2obdlL{*y8@Pr5uoe z!|bSb%Cd(ttO0T*~K8P1lGi#PDS)m+L6xZr`B{VgTOeU|Dm6fr- zdGp56P)q_iY4m%q6>=WWI9boM9m?l;a<;ptOg<*$%w&h8L*@^29y>}crfOM&GYk}X zl1f0?Fq>Z*aSN=R`&hzs%-3VTp`l4pwjET>Zkx)w44I-wlrOZ*a{UL>)#+pDL08u( z^8`9qs!~3tXnfjX77Q8?=Wa23m@BWLfenvVjkE_^)*Fdy^lzO`fbNeKoj*zs9!;0J z;VLK7`EfSUiGA*N>Asz_vukSA$K5e$hsXwOuLkEQ^=%rzxYIgC9o2u*QY;sREDsuONH|c3yy7Cr|l*@$Z!O+ zpYDpD(k%QTsu4`^pm#Xki+?)>&ZMl3(M-uey(7iqU+hz9G)y$rUD5El;yT5zaTe6> z7dX1mj>)^umo|Lb?!9*(cApi`M4=fxFc`1(U7niHMv+e~lf6?dioI$AkN6UGRMIvb z&5`l;T!RJ;brErUEl}K=(7|VOkiy7Jz7%6NxB@1&teFF_V0?`Nuv7;IO`bk|`qov# zIuAEDcUug&9*KdId?|mNxNt_OaFSw-S>?}&6eoZE7@PM9kjZ27OE!PZcd)XzIyOY! zh}IbYJW83rcoeMwf0DWxifP>F^{I;pNeBI`s0PKC69!jPq1A#f1F_OsH9BFRHtpU? zt!KAa+_(6u|GEJ z{lZb@(rH!8Yfixkm<`1tt+GB>CGNmZ*0AhF$Nct%RF}dt0u+1%OPe}rqlK}Q<~T0X z`#l(lroW)5QV%>2_^QT$lKfb z`C{h#?hNR+8@<8hU5`Uzin6py<=;&rl=K(?_8t0`e&HPAfu9qV)4b>sPjlqHsE&8)$tB!}9WS!qme0 zo*;$L?o2r>p&XK$B4|4i`aRNw-tV{i6sNMn8&Dgn?0evV<29YT7d_5Img($Ox!br< ze1eTD!qK4i=*D0ru2o+t9coFW(<@ur;et3R4QBX&Jon=cP2U4;SMaf9}zu zbZV#B&ca7LoxHrZ*ak_Hhezuu3hUyfB+s*HObL6nSY{`xD*prlDja|LFo8n|`-7bT0_)YK$b4}T9U6HE>H zvmn&lKu_(Y^ScKiYDr^S05hdUTj?OkV|VF?3^<>f9FH2JaP1Hh%-?2or8cY2JQ(dD zad)3~H47DOxe7))x80UCm@68$9W)<>c^{iJ4>#?wJv}ypBnVW=^NB~&6igPa0QX<| zo_|%6k-I4-cWnLI@1v39LpZDo1I)IZcq{^{)h0ovoJ&#T;8)_!LLyST=4;O70rxVQ z6-8ZkOtOM&nEi2k<-V|PV**@cpDS_^@qA{k*wfve%q9*Z32?aRk3>$2o`T+mBC_2V z^7`!m*nc3P-%AG^$cnN96tCc5(jiFuxHpq1-;NJU8#(=KAc;|hwW{SRJ*&-4I7|ec3sx4%cy&=I&9^8Mz`Y;L zMfpR=b?CcuPF_Gm#o*5|s@hsfI+l6RMxk~Ye-*IKZAkZwK>S<6%go|=6-Dq&$uQWSGn?M zn*?Gq{1n{Tsi)_GI?D(ouT2K{c=J5tccD(pySKofw=-5)|X|SKiJ} zx|(n*P7y?T=$FvSS*c3DSl%qsa%A@?VO6TzZx9ng2&BDjK&K6-)X(4)g+hZ&>q0E(SF)_SvP zaw|zLP+3%)2=#c1_4)!U<4mrR(_g;6yV4FMEMcXhcWo*)0Bony#y;EqQq|k2 z3Ko%bf3?ajSvzu63qm$L_f-oqTb3z~_E{@{@pb%}zs>BRC#Q@3MK!oSitCdDiL zzNY$5>Tei;hnD-}iQ_xXakCB%n=q)D7`+^`N_tRtU4Ro{Ba3x(c6PF1pr^{Dgnm(q z-4HOQA4R~#c@Y%px469j+_=ka^cYsg_T~PSNQ!~R(N4i}FT?`IYE_q)+cqoNv6Ir) ze&Lgk{JI3wJh)-z>~kmX%e&8py10TJb7zIC*9q(ov#!hOJz>UA#N$uA3eQmX6$jNB z>mFh_p;6z8vOh4y@e_U_WOyHmL@8go@dX);1Df$FwL zHuQb8dFVHWu=5-Yp&I|kE!PJ^hZm$e?DkM|ivxLzjfYDG1senuZ5BllH0{)!M>jnV zZWHbzI!QQlZU;*^9^Qy-0e{>2R2!&wk4gWLX1G>mQ)`)ZL~tctM17IX?$tq1ke^SY zzvFOlE(|R70(w%0c;`1r{EwGYNfjnUG|j`W90`Ey>bNeUC^0gPso@(5$&(!HTVN7j z@|`QziwNn$`9Q}mh0?4hQvhLEG`EX2|A7r{Q^)XKphnYAHsaP&*b>2*9);k$d zA(qsMRmFPG_t;wQ&3`VT-z;)CESj*LczWDcwCTw62~(pX7q8aeo9H+i?z!0(n*PfL zRiM1wV$=DAH6043@4UA*gF`TY69VefA_Eiw)d~QZvGw1c-GBZa;0?Qs?>!nhBJP(Q zEgGO|pN>$7tYp(WCe6?F8Y@OZ+2^FPV~euz8@a^~L@0EyKJYvU3jjuufV$Jer6m! zfK@RqvC0er(E!b_OAG|z@9CwWsEV#AQ?O$EFemt-uOxVwM8A0t+<@*!`st3b%vRZ_ z{h&}*EuFmiTStDljg-68qr-qO_(}1b_r#G#$sb4qq_De~X)UAr=W)+(-EhIR@zU_t z<1H&ct($fR^;qyPzE%ryTuXlZDWiCaxKrV~uclD@Dz8c`QCCEq_rTZg0LA6@Ub>J5 zpML%w8)17DP*dXDknMqS!{^2z8L?1Tfx^}RFdqQl;+;8#Xw9NCBKbfG280G$Q(_VQKLQ;U%= zZ!aaz)D4>~O*VS9G6c-f5llkhKTr~mio{^z$VnIS!-gz-B6b=7dP z!ZA%XqTtvQD@4d{J6{w|yx|=Ie2Z$Zi+!&b+WRh36%gtxfclJTrqMD}ptck9n>472eX+Vwzy(~gY#a z8UW_T@Q6pyUNWZl&X3#T>7o*e1y;<`J_!j4G70hVmp`5aHc>+x8yhzDJU9u6(fMxP ze?9f3b2wZuPu}5VW_C7qYadHF!eS4)-Fv2eQHsJMB0Po8;DiKf~T`!<}VNV{` zy8O@5`rmc-J{oW&uTNHc&a7xq4tf*7CqJ3p>O|Qu`-P&}veo3g$hDwbj7F-OWAyII z8(nC9I=v73*-Zu10t{cYFNplmPL$3qPqqktn=id3$)z|kJUqOWC}M!Y8EoqTOfX6B z3&29t+L{~q)UR3o`>Fq86NP%~l}@zjQCd+)%Sgc^5XY+}3?2OpXVNJz+AFFNfA6ks z#p`Cv-VCL zit{IXVQ@E`_1c#g=fJ&IN?XGCYZ-Ed?)kP%?XMqd7h7KaG2XA*P1`JH* zIZlS`|Li?p2;=RKmoKtBKvJDQamYiI%kz4rD{`6^CTjOme^#@4NZoG$K$i|tb0MQU z@;Gw!4^4bABZel0FkCtWTN4Aj99_+Y?Z`< z)oGxwTL^EQ<@L2g)c$2by!>c?)bbsIA5b6dC7`%)R-P7G>mdN=qJaXLBv3fy;JWr z>qDNgOSkt2=iQjE4a6jG)f(L?_KNSwW4_1#4O0&C$~2JLQVz5^^qnU&?rbGg(gv_b zOF(dfQI=__!cP1D<0Zgz!Z^Mg4;zJ0b&_N<)PnZdyAF{p6BJrS_X!t|Ny=$DhB-T2 zHpX7-v_gSU@A=c6cQ|Jy6><;X`J{xbwL<`!iP`{$<~N0F7n0ob)i|Mr)~wd_ikqsH z)RJg@8&+%khY#N`FMNA5&VWk>lwa?$kof)qgcd5zuMtWDCYbsXF2d5Rkaq^7?0>HU z;PMPpdkReFnn@nC`%%hd1XTk(*h&a0`&HPZRb>aVjt5|E=jIjsZb;gqdV?NHi2+q56Zck*P~rBJ z3MJjRriSo+?uCMkr6=hRp3QpIPiq`JUyJ$3MFaS}p4NUVIcqP%zgsK!fY-h}Ce+^k z0JC^khsAAe;@h`x_Tydb!!7cPs;c!KTfc5*(R%>qRPngyyLW#iJGXfKd$kn90bQ~q zo1ogY+SoMmHV9-jdK$o{r^*9ADQZF`i!-%o3%CtI-O7!*s_tr(m3pJC{G`3Fk!78- zubMY63*cfA&W)B}<;uPH-96wF+s7GUWScxjJBuF8n=WFu<$=?7p~w57A$OIzCHzMI zyE^}KY?QXM;@(oahQL;FmY$MFA@5^R@ep)6f?77r8{n)7f3!+`2f+qVZ;QzU-r{L@ zvKDId|I0C-WCQjVOu zsw#hAo{Fz^1W@IcHH}`9zx1!-wIU9a-PVZUrf}N6Ht5OLpwMGT*~f{|f}tSwq=4A! z<$khxG7+rbpZ2po?SJ84DJ=&6415_Xh2qs|sODs4OJQoRsdgSn6HMHS@iXzP(?E{i(>>zl)m9+|F0`)n zX_-f9v5&rLzv*@8;2T+LkDKsbpHOq7Po>fbgP^sU0Y3F$0_)^STz%U073V*G8_gCl zNN3%=O^-Q3d4e=0O5FgcVB!c)RoA(*uW;5XtlR$*eJ|u2S^03w>E$Oek!FwQmB`S znOXV_0SQ}eKNB{761Vc;Uzaj`n@-PmcDn)8qgl674h$%VL)g%8Q_@dmP@p#R;sx8< zzNt_zLW1T{Tt}R@zg*8k)bZA?{iel$S2ie3hX9t%-LUx&T6cY)-fA@KIDAxn66mzS z$kCNPQH1GDtD?=mILZNi5%Mf_s(N+ZmmN_5-XZ=V4;@Z4bMbEsbM55<6KaSWk_Xsu zDoSIMIQjr|a&j#2Fv=MwTn#NKcQNiL(c&?FE3SCS0QK%L2{mfRazhp9%V?c%jc*E( z+?J0Sx?P)_l64Nr&12qVg4QO#2U6uWlv{X>i6GGZ-pQmi4U@ZMcone1;+1#)6O;4SMP)_EO%)w%1N{B1l=c=CN-AuotH*+?a}SGrEpLWI(1 z{sQX7a$?LO%zR27+z~*iE}Ul+!}AC5+R$UeSyAZgmq_X+im3RbqZDu;yUpWpRAM(m z`2u!L1GpT(mU5P9IvPq67avR7s^d&9`i6KHf3sY8h$NY)eUv2~1X#~($k=) zhD3L2!pE4Kp?50RJBeaX^r+U84BVqk9xYxop41N$4QUgU{28_vX^r-;*q!5$RY?^~Bfjc%=gb%KbWJv`9_(k1`cVq&8)x-E6!7L;w;ww1!f&OyD(L-uzVa=QX8k zqQkafoU)TOo-=KME1Q%Zumq_Pk5`cJJ`n|qW{hL)b4<}ifQF6}SH;TkS5Yp5j<<() zS2`HZp)RrwgCFUwonsjFuK)FSe#5V~-+wgJ7}c5V_G1puR<{e@?v0>j;RL^58}}1Z zVMj-rmjg<>S|ByCH0IF5veP+;D}bQLzqgv-**-Y8e54sAJs|gBo{peF9>^y9OdYqr zaiG3h-;NhfCC48CSBts@|ZTOh;<6m;KTk{k@`J-yC|A)qqmD z^lU4OpM`I0&Rf2%;gvMi5jQxh8#1A~SQ_jA3B=ICrgLyN>*YN-V_?G3QBk#1^B(j zC{~5QLL-VoKFi$C-R_6>{30CBccu9r*yD;=)2UWbt;{dKns%A^qkx7HbJC!7pp}CFPj*RNVN06-j;n_)(-MogG)3GKg-wun(MY*<0my31;zElAk7kxaKf9 zH>1AGulMVocg}nKeXdLG%QT$HYWcw*9_}oDwD{PB6_5X5lYhJHB!GH|2vksDRDOy_ zG0y;u2sT;t^#C|Nw6QUB+C}5fhXsWqUZ_TK|B{|C^ka)oLLP#z(3`Vlk2sx8A(sqpq~dfjR;>v4Tx&c?OVe zwxl2f+^@}XqT@^~3@fXvmYQ>8P|`c#jO$;2)Ht{VEZ`A^0LF&x>Ldt+9BX(CJZdR{ zjT0=LN9%S%);nNy@piBikGM^63tt4$#D3&m($O8uw|dh9IUZ7sugF28i0%{z0-R=|>u-zv$T?C;mJB_A= z9X=YmI(Yf_v(uV#wlp?i8Zx07Ix|>gKHo^%>g+8Yr!<4?iO2l04!Zp+DkjzEbH>bH zv4OU@k{nCOp_&;Etx;XCyN6eg>__GX}h=nl)5(%l*WjVT*f z!!!rJ|FQNVZQR=kZPjqX6ffVF|K{i?=kaBfKojLsp9&}g&4L$}p|yY%?jT&2I>WTe z>uZ_5qA>`g!n2iP9@%wC~1Uv1` zlU9m70bym4&@Ju_W6YM^lN5bFU(q{x{KoN@Kk+`={CkVt{q*rg0_ViGuFL4=tIobj z@F{xl*2i}*q(3iMU%$@w5->4R^CS!%n8kv=iZ+X#zCA6Qpra&VeUd700HmV%V2Gwl zG=$*6ilc&D>;3xsTVCOZaX;@pV_=s}kt*bDe3nB|$XG&A=Mj-@ViZLXs!xGt+Dmb( z0G|+I?!lRrG>)z+tyz(0e?6|t%l>r9RzNHSP0z=q6auoc_G^6bnrgvjIJ|Ck=NDghQ$XuALN5@nO@V!YSoW+mwaJlmNGTM9EjWmZK!ctFmeUrLOq=d%~33Ws&`l@ z|CMn@RGSC`L7SuExp=;$c+KKvAv_1Ld-a}B=A*Y>n_{`h`uuysw_OVeA6a|@2RpmM zvelVreC$+kC&>$W1T8RL(LhL0#p@RxlB4<=2ZR>x)T;&kA#y77Pa=7EimnhpULumZ ziH&w7>w?ZC?8dQ2VdYrCC_~;%Km|u6lJkVzt?N97M%7Vj>k8`m>5V&@b=cdMY zc|R5GF7DOKp$i}aQ+>FniW31dYb+>2OWm-5$29o;_dFU}+H5WL_{+?~A=Jx%woW)^ zxb+Li;HgcroIJ}`U8E32J^aWyAbB#R5NM1TBHn(Jow4aC`Gwx5l|S}^ZBFr3bgfr4 zs#9aDFyiS&%o{zgR*COdT;-rvkUsUC8eVx31M@Eh=)MZDfBgXyQe1;O0?nVb7>}+&|-x!EONhu$;;BPQv@8 zGlHwF`#a?a#I6uVmYw>=RDb6%^}yk%F}B zC@IwFa?7CaBSr|4@T?1c2BBMtDU*+ui&Bo=i`b_eki0Aq_@;p2-Ab{Lus7UH+>f(+ z>4hHY|9F@vaiHkpnLdTge~2b3Nlf6%**EU zxsM_+R(DZ!A1a=8lo)p$vJLp}+sYU!nm`Jt+ils-J@Hn$_~0ZhO}tGyPKy+vXPw>W zgB0Xq_Sv_-hdXoVJNo|U&t?3O1)`eholoKC!|z|J+_1uV6K5H@q%E48LWktGQTw2f zVFui_)JW>a4mEP=(6;gn3-yY9Qn`E$Y4{Gt?wwj92@(Hj^F_G@X2JA7&t0BwLHNsi zsp2sBGnvui5qowc$e*4wdIJ)Pe7H1OcE#d4<|rcSW84dLkT#9ZX1A~ zZ>a)9{C4HH3J@nesyXbz|3mcHyl=A zc@pM@c;~hGwm$7rflSt2g&mjh`f``fhdYTVl_b~X5#yfPv|%Lq&VJ)YGh>K5m_H|L zLc@dwMFZ`!fb32iuY3LD;3cqLQ`BjxgjAk3ML>!f&@8m+szLzkAM-UhBMg%>BX$&Q zJj@3@Fw^_22KS%X=f%Nqr!{>o{|F0Z5{+f4=9vwM_ zF!bM(alN1`=BxKou_o_8yk_T}t56Q_n-g5=CPL3!E+)s6XmM;TchP{$Elb{NOT42* zoAO<{BVQswa(}%|5+(CcP>h*+<)~FA)N|{&70W-COii}igo%_{;?;RRk-Gfn z@KON3R+W9cubaon220{o)dB+HO3WZ%oqSVA=R zZHyF^LY9za$ky0**RGHlMfS*&EZMWhFynvR_wD}Qd(Y={=9!u2%sKOHzxDfjeyL6Z zLGmW#%IO-V^Af&)TzYOg|NeHmdK&=MaFMt!7fbg+z={rQ3K7_1jL5ZM_$f8b<_%Gp z;qa!8rsQ~Ji!>r{;i?8t-)vEW><9!Wnm=C{yx!j)K z)?8*!xEhWI%S<9oK8E|df~3i>(a(DQsHRLoHy5qdle#jrr{?0QOs;Xh0O z5hScKw3>O#nkFBO4~0X6VC7pO)U6TK^?{&SDLB=o)V(E-@asDq zP|O@t(0f``=-rg>d;+MZP_q7Hp%@J)X)8&xr>w^_ba9@QQOxra*hZmnU4<*!Q?JZM z&^5(6&n>N4inO4k9mHbGS3X#OH~KpHPl+AP2p0;rgVT-U=$Bv$(bZs^K$n+O;wmBw(M09!nAoxK-CPphAjX%dKgeCVF_w&lX9AN@x zOlOQtJ}Y|bH9m8`0I>aeaTIRCBiKgqR-soe`JLSsGL{=O$@)H-eDROEMB)~03fd@( zZXj~DmB|JCGXsl(9g~m;Z)u~p_OahiHSa>3koDS&%*=u3w;fQRwK!mxY`Oz9LK%q` z{5Pqxjt1eLu!#7qdPGW-QoA_2E|4cb#35#9G%ycaNVJvB;qYowb%o_yk#NbOenm2~ z#B7S$tgeRNQ*Cjje0(c=R$WnCKk4kTkmKd&fR}HdyTM7wmM>-6_Z;1`iJEeUFu zhS+r0VVAu1+J(vx?JL-e3aTJCW+-Lk2i0*YZ$xY42M&4=)jzqmJY$5q$R_TsRM@9o z{qN%?4FHb#)|x*0{mGgAgE#=s{!_{MNE2vCBB@)H5J|MnF-=LxaU@`fx?Q0HFewE5CGg!_j~B7ZKz5=KtEmJ<#O zq7V7SIhVaA*<9uYqa;56#(?=g%d|PwBpa!Ml{28Bx$5lVk|JTy4tkZ=|LKL4vYEGT z_$(t`uy3Ob?Ok^Ff1nv-TJKmP4JF5`q1BnHo z6ZGa#yNcN$4<2TXL%}s#F3!$gEQVT;x{UpDpmOr7e?lrEJa1qr4?gnvXq`X=ZM$Wo zRgazN`r^1#aqUKAI*~2T4mUEb#1Jx~-bqoTqJQYPLD-Jr3izeuwF+umrLmpE+gfk8 z{NcwQs(aNXeM+v_hy_7?!tfQtZr+Lcti|H_!Ss7PkS*uQ_s&*+=V0hDuD_Vi?2yca z4u{a*3m5Yq^By0f@X4Fach4}g4}LwkoVuwYG2`=NAO{0rm^${cs(@esyZ+1+6ghqw z`v?+ES?Mq<_ahpJ(!)TY5KX%i1voTzZXMcfC|7^xU%F4kx-!=5-J%k?J9Qa%qXPLf zjqC>7$)zF}BG%#@@h2iS-((+gg)>)5t*^OWj;5bh|z{D^IwXESMseUtUhDC89 zpG8C@3L<~a#fWFU!?xcq;R@s^J`?@o0`q<(Z^60Tk4Vt`MyLCw&L=AP}?C zg1Or$r_XQ#)i@Jfg}B3slFLCi;wusuN-fxa9AZu1&hS8@1_WZv)lyS2DL6TEAO|Pi zJU^iRQ^#U)CUE!1=L;*MSzcp;>GZaYv&QAh&A0Stt_P3sXd|8Z53AW0gb8|ep?WE| z!k+eT)EFlKB2tD`@X#g*Y+bXNEhK9gp}cY1q$fY_s_0JKbCqD~VPn>9!~TtzTXIbq z3Z>Ehy~FvK`It^-4i^ggVhE!7*UvQ&KQ(;U(IESzw0`>1`zsXD6{fSya9C6&P|(tL zDud0TY@J2e4sX_nGl*^Q@E_E{RC_cz;PdE`T4#s>ySh94v0B%c+#4=^10zn-oNiz_M4aXKkm1*Zf zvCwfK=K+M0c6PR%+u$CUx-3$s#k`3G-WbE#5b76Ev6G zH?I=z#dPx?2|CIN=&$!7p)j@q1?a$)S0z9%*ff&|=reT0dYvs9Iq{H?QSS7lK_FX7 zE)7c2Z_R-u(!I}vd-=sB?3cyHyIUvitL1GNL=aUmgm_;Aq^3&wr!EKzqr3(ONnzhc za8sY9cA$7G0jGf5cSJ;hf6&+)MEFu2gOg|-?Ce16_a(41LcdzZ1Ng(D`Iq$n*I5wZ zPxrV#X!m)4h_H03sPnE06C%}dA#=p?#{z=X_+JYn@(KHKa_T`w_x|@Cn>F{$_RPK7D#x(W-EH$G09^&h zuU2VwgOz=}HZ?+12Oj3F-W$5>4boA3N5-dk{O;nz zMZl*Gnh|r-o0Gmzi*z}Vds^|XopaBi)6N`R-uq&yp1YhY<7#0XSy&S}Izq!asYNhV zn0zWTpUm68l@L>~pOC)61*11u&lYRAat6}iZelJbZ$vgs(6AJ#cH5>l({k&tauqQa zx9v^4o>R$@?5KEG^?F?{T2FwLM712U8f}4mQ?q)*4*3)CN^=|lI1c1PQ%GcBH7Jq< zE}_46^J(7>gy!d0kW(2IGw;HcGY!2UC`Dxa)_ICYS^Uf{KXUbbnse#{k3jJAL?M^= zNYQ(e1KJPfs3AXzN^39w*C?f%G*Xj;%CIDY9$H zs$wR1dbpZbD3QoB~;{)%(=8g&8Lp+sA(MKB#@+1&dg<+-bvg!qs#XO>nWJOb5(ssec%&>lA0JFVv9Lki2M*a?%Xb|m@?*PL^wyXRFWXyLtyK9&%P~Pqr!6GbbhH^ zQh0&`pRhe3s>6s~+@U-?Jc$+s$QaV0!i#XQ3JLNcbfeq$oiyX5@cwc~O7t4LA@*n3$SC&E`%=~f>*_}ImlxY{FR%7Gq**_1hUgitSehw{bQ7J-`CJt5YStwf z+VIB&AHJ`qoEwC}(W z$3CF!@yK=tFdK!%_j6Cf4Z_&CTrWJk!4*-M$^&Qf{!!rJ`7>v{)qtw<0oJYb);rJh zkESkBe7X6fT7q6IFG(xbVXLKcwaNIC8ue?hBJpR(_J4DB1!EXJ+sYR{a$7-(=}U2Z zuhpe~lZ@AG8ntGvf%WVTD{}@4@Uh{nxO*fsB>Z64183JxW{T``UDSya0eOkqx`iv2imh{#B@% zRHFvW2Pc7vnrYYKb1K1=Xb?DruEcS_jkXCCtX26cn+XN~rTF35NR#~xp*>51koRoT zE#_;qCp=Hg*Z^i8n7i$K3HQd>^3R~R0~c}F(hoVR2$m-!zdI+LgU1b>?!M{YAM zJr3`)i>+RfM2uD=NN-%k_J_+2x6b}#X_n3wfBC&5N&ye0ZtuSrcoWm_=$kp?g?0?(v&UgMrUODXr`{F8akjK6VuJ)DmsCBDem zGvv=wnjeW>Mfpv$Zc^#zFo z&Eb}(eQrm7ECi|#O^C68w{_7fNJ>P-BkU55w?qWE4Nm=35k|c+_8xqb<-iBfTEYwF zLcukOaB^2pbdnDUo0bXdSF;2#8wI&ul2o9q@t;jXL;6Z4-Kz->6=xM!h2iY8DRVT2 zFMgQsKH1mGy!zpg;S>2c`o5wAar1=p{l;=yZs0Ek2P^nopZ4;J!l!20!eJFVwYJxo zj(wzDd5p_My5Zs|kSG^hzTyQrB+CGDywp4uAeH6oU$17tI$ zTvUz!Eg{5eDl>(52Mn{9sAaF*2CQC7Z!Q(sq*Ya+OL$(QIHB*QPF%au$zdM3reXNZ zi7(Xo;ulvJUbp5Gan^t4Y_N(TB9Vj^T8?=`z9Y0WN_%h~co*+y& z?dhW|>PbuYYC&1`)v&yxA9wQTg(#19Ik6tQVHWCQU3ES(Nkg$(H9dbI2~LKaRsXeQ zMr1xzCWcGz>z)ibsTQGY?ubhxXk%*u*ohBME39;T7+ti`YZQv*B zL;R15DO#u?pVs@KuxeN@cccjg;@Zcd_%WK~)RiWq_w)@S-LTjEcR0R``MWz4C$to@)9-nmF-qSppQA4E@3yDc_ zn86nXdmmy={1eo(FmtAH2WG8!-QwWarNnrnJzEpc7=8S)anQUEin!>TwB+jt^&iOz zp39Dy(DUrnZ0YqA^h_OgP7HaqX(EOkvVN?biEOt%sQrrKGVt^C0kD)51rXC7tz@^0 z3v;<8rg9@A3x622?_afO=WHyhBG$8L+w$+#_IUo33rfz!yfF?xG&MZLX911wi+cf zV27d?#yKa{Ebr=Y^7oqJR;ESzgMIuAy7S0t^83hSruPT&r#fzPnT>xz6C$DtId6UN z$Jd1mu%a?gJ>02*t<-h6vX7IMVrfkZh1X>d5>P_zY1c6%`AKxO{=xTAzlRTC&<(Cl z+rr3YpQ~dwpIXa8n^sCETi1WPkkl1Q<5GBPwlGvL*@w|2EKsd-6kdy+rAzeCB0rqWE3wL3I zoKaU1gk|HPGQLrBlupaquu?d+DgV?hmW@Z@rtJ6gu^xOp<(R5gK>_h2VeLBw!(~EK z@rBK6d`zC^HVXn_v5OOgFJsAG<}H4c^}j;_BBmZHk5ro$&g2gT7a!*_ecTftDQtd# zQk1CtaYDo+?2A$;0gqRpOo{3-+aT$zHlmIAVSEhs;Y9DREdFa(M`S-sS`+BTiKSA?=gNgid*UO z8r2)q-+MAzYQA6a+lsi)18F$PeRuiSNlkCLb~#bKc+H2{xIL`b>^ec)qh7pQRjit; zdz+DSGWXW@O<)meShHuzNcPxDZM{w?^sOe=DD8w$foVZ&IWdRNTD6H#9-EUlSEYoD z?irPfu;87xXS9nN@6-xd7p^Y?>##8NlRnyT&o)%Mco*Mtphueb`hQ@Q2RkHq<8J+X z;kFDV0rMk#tFaB{wHqnHixQRD7rKZy4zGEF+HbJVQo6P6j@I8vNWTn0SCVmkw<~R%530`B=8_+KrTow1@BH=nFow2~J=0p3zXyu+ z5Sx`-w<2#ok}|Y3zhYjrnUsQaz1=oHsb%@gf7o^@O>4bi=1#NgU4bC&)row};x8@; z2WUK!$uByL@8j`mw;oa%Z#DIDDnNa;uF2HDNb@QwDgh#IcODry|f?m zyZ4{9!y&<#iFl7Plls;SYwMu9<|!$eZ(2(alFXKkkJ#Ew_iBo8jV8FdE7QYN9&)D- zL*ESWd_?3PWV#6jDkc_ot90-yDY(E1t(U~4t*YekCKJEKEug==mOC*4HlxAJ zsrzg<27js5DW34GSDO4ykR%|iR6l}TRI3_{rif^NzXiPY>FOrd&H2=nO_?1nO(ZL5 zj?n(4@_bw|jaydI0AMRe2Xo=ww$@0Cv-Cp@AiUDTLW)t?a}%4crDHUDBxU6k>4=Hwg~~+^^L81NA`cC1&_dBMNZF=fYKuI!kH2)@@t}!T&wYE550Cn@|M4r zYdhs3vVTA(W3iN=I`%nWhic4^T?%xB&0T>by=Al7TnxT7sVLlUp-P8j1UzprMqBJv zZ&%D{E#Zrf*sD>2phDl`)zuo#{l8fUCt_gdqgmKk5fM%N*t;NJw3+x_KH2=xba@Dq zzYjEHFC&SV-+ZiAyt_Wp1N66V5U5@DZMB9n(wi7D+zZ;%0bpw;(|FqnOjGE@y-!F1 zuQA)bysPH=cT=`AiTQh}vVSXFbsS(t{n|S|)@>P6&I|Z(VBVK&+vGE4RbA9wkW&gP zOU}g81v*n5u=0Cr@53Sx89Qn2&wM#_E^=~6EHLVFB^%? zfkY5+XsPR|mEEv=;N~bP2?9~9J~7bKJb(7mS)l5?)=f1dpyWC|so=n?PjK)qP=I}m zG;e^)KCvwWAJkA5TF$za3rnILc7T7Ndul+pI8$rxe#=Uop6t9Y7AGd!U&XE7KERj`xtwEN%;46}^_+k7 zXNU6Tf-`?ay{FWAE`A}`?UwFiqGs;%wo8ddtd+V%u3;HZUCG-L%JC)=Im(ax7f2Ih zE#K451vFIzFbVGRR!jft3kqH8OY_;3N;PnETb^!iZth<94>`M}piT9bvGe68o!Tyl zDlTn=->$YHqyD6Ea{BZ1=iy=Bk<~r1k%kj1L&N*o_4W0UY-K!hq&ni!QB!eov2DYq zq@Ag`c|fOlgWkDchmj7A%cWfIz!t-tlz+mtwY8r<$Q%9e)9T3J*4X4j_q_gLqoAOm zG)`DP=_P&`Dm68xbYY{P+gWUs%9e^%56H;~F+e|-l9sMN`dnhqeWgESfvU4KQP~4N zo{Oq@Sdo&Hlmz5o{Zpr>zh9h+yIQ!;ccWpKf8gliLBZ9)Lk+=Yb$ieFO=|^iZf?nv z;j=P(AJT0EmY&;b$+c%(9N)g0bn}kII*dfP@+Eq;F#gVu-{W5t2VlT$hkw`=COWb8?Qsrw zvRTw!V_Z&CjQ3Iu&TUHTf$ccdKR8bd6`)b6$pls3wtvFKwZb+0Micw_eg(U_ff@7Y z%Aoi+-o+a+&})zSC(0w6K%N&Pn7yEcR}Vr6{y+PeDhA(}Q7i8ZHvF=E9iqXJd%3+p z0RdCX)w~tR4L@U|DSJTn72I-rn|AK4B_mem53157mjfVJTFRS+Q9M8OPL6r3hS@^A z*_+wg`|U(1gX5@+^5-LND>3J2Shk#e&i>UKtM2du%D0|E2q6=T4p}T7AJh#8ImQZn zKN&n&gudxz6A3|Du6>->idekUX+~MLLg#+9LlMlF2;o&Iuochoz&_TZ;9QL|(9*pw zk(XWj29>my2l~Pg|`o^a|njnhSOiLqF+Y+T2LLG$>bmtdYav3!nlAUTJ z&IIFF=_o(J5xsbso*awEpMNrZaiUIe@O zc>VVk+VWT5^eZoF(JT+${&}f+QYMnHla;G-W{^%BkrbrT^~UO289^tkMZ{Hx=S%ss z*}i?R8I5p3XVnpcScq;qlIS!bI{Mt(rmySoD>uaRS}p3e!)vCJ<9*PJX~!D~S52 zT9^~d>h6eW6LCc=tJG!2@PKWT>*;9SRDVZE)%j{Se~arvs#={Mem9QRgKvJ{y$%m( zno4S>%>6L;3t?!0ze2b%`RCr5Su0BC{RL>av5a8o`WoK*eM^QCjpjS8hm(o*>eCs@ zRbBiY=rRUrQ_9_yMWoC_g(x6yk@TO)s6OilNUqR5YzXKS}=@S@Qjm3Js- z1_!qb@tv2_I0iZ8kE2rYMbuSlCkgkCq*F38Nha}~*CppqAY&~dDx*(hVsuEL`PYC1 z%ztx*Tk@{E`$r_>{@NGgiLYNnzjGfl_zst%P$+QFJ! zR^^H}H^>;KgN zD!NO&LQ=9?w+xN%*t>d%Ja`oSQML4HAu(1H z35_32Nt>t`X?>}L; z+gqGY=M~n~5OqcN9T*rWYj1B~pP!%qq;wt;5#ix^7o;5kRa8{GFf=q&t7)3b&krQA zFTpU1P4j(=obNu*m58rCF%6&JJeYBYE?w619Dp{`s3S%52F6=6_AvR?U zl%V3nbqa*g1G-?w#3@$YL=`E*eQVV(mz1zJ{@&eMzFrXj%iC3 z&;k{fXA~SM4IF#vMp2aZ+S=MV&CSgo{>6(Isk*v4B!1pG4YA)0BXNTRQ&*{=B?9!K zio_KPuKyi4_9p+#nKR?~jg5^|Q&TgW=ie4!s(z-MPJxs?c7%OC0$Qtq-eUGL)=MhZ zW(SXbFn&{06P-SNdbXmt+cjP`n@h*7Q5}PKbo7nr=yB-i8rE^mrlVs>M?u2~rhV-K zeZlOHS?@A?B`Zb6&Z8>2?Yz(3e#15lGXB2vmun%{MAnT7;N&$8o2|T$DpjmGsbY17 zg7k6)@02N6Rq95<9%g6jpmog7WTi9vRRPON74x^&pEpC}%P~p5>?L^lI_)|R z{vnW6rDFLn3YHctMxIjS#`N#ppj_r}WcDYlHLN!T!dI(U_=AQEU4hxs8f^aFe6zQF zgX9{NcWBs9r{c9=6+C-DL1aGf^=-`G%-qjdAF$E{7VcEh(rfk(oQJ~q_Tb?4Jj?rf zceB8AJOBjokMn-%|ME@0BW{63#r(c~t0O!|$JA^Marpv^k1D7O za^{(RWjZQBhIG{fqA=Yx#~86yXz#uL8%LVXSvefC{(+6f+@kGo1QZ}1SDmI9WHuu^_^Z!qe@c&U^9CJ!dP4#0u nG?3hLMiNA+V?^`pL@`}Nky2-gEDu7`mz4A^89LFndszGn#{SQD literal 4286 zcmcJS4NR3)7{?D{ple}jTIn*kT)9^2DzUX`exza+nY9RJE#^qePza`$OwjNXorI7w zBXPB|oRZEtMF<3?P^XAZu>3%ik1NVY_v5|q=fD4Z;mSqsBH*Q?Nf`Wo~Zr!?dRF>u2 zx~{9}rD7O{rmAXFb93{t^78WVg$oztQB4Ha2!pQ&ZEy zwx_-K%^|5sNwr~fs?@=#)9EbC%gY;5Qc^OBYh&rq;65uF8WqGR+A!!zCk`Fy7)p$< zrrO%tkjs}Zf6Vw$?i1Ip`?YE(B9_?UH%!LZNizMfw|n0DLuWk3S65djkngcN-kN%^ zlT{6>=4so&xr-8}&38bIQXn2zuw;cfHSgwaHruAUy1F&qt#?&xAgffukxHklp<(FA zKjpxf2nk}03h|7Jeorenc(kMM-ImEuw^%Ie+`oJB*i!<90Iuh;O@CKXXTY#1C)e^1jOCX)RUHCn}@ zB;UR_?U;P}e}mg*cRw{<$Kw4m9$u}Zf2T+`9jqeoMHTz=eEZ&mzp=Yq zce_jV3dW?W2#C`m=2H>WT(W0TQz-JEovWbQ;u)Ln-ff?)^G|UlC&mw2W#}4oO#|~3 zm>VD~Dx9(chf{&%l(F@=gn%!|jHaTfdDOe)&Zf*Yn7}pp%IWH>)0VI8W%BDSbtxC? zo!EKCift#YNH4Ww%kNffJYmI}Vk=f1vm&9uiskuM#2>XG`mhb7zUEplGa#0byMX$T zdXL;tYC1JZ#Ve~MEZA#D%&&Ho*LY7aCjTb+4U&QVe`{ErryyjHjLARAn98`Gc9&k` z@8Ith1gs_dONwhRKA|G1_sN|@&CuZgx`qJ>ItC`|`0Rj=+jgJ(-;BQ$_lj6$14aL6 zSXr!K&b}7@^j~Dm@X+Wi75*kafr_UVk?k1+AsPbbX&Aaz$FjpZnmIRL<<9!w)xfC% zWsIH8Csl+o&dqt7<1qd5*f$#btS5IRwUoL$2Hwyx=yM&3`8sTzPiMs!-`z)J_e+gB zzCEYnqeC*r)Az%->*%|Y+$3r_PE^PgD6-D*C6Ao!rWgGtf6)M-X$- zb30Uo?sMX7P0KsMv!A!`_rl-%7vpaWnd=Np$TTqVI}L-=bd1}jx?;qPm2Iba-sr|F z)#Nk(_bC7UP@!S`ZUfuT8m@hnS*BuawsL2WnEa?i66*PW>Z-Kzd-VRRcNnlZ+AP;t zxz7p}*B){2(^-3*D7f178rbdjG|oSX*18VXHe`oybv7LPnn;)c2);!`-+>)af!#3J24P(K*BYi0Xr!==O0&9RW*fY!CpD{-{#sRm$Zz* zT#K9v^W5v*wVZRa)oPttR8%yO_l~2TjI&3N8kui5{Gqts9m{@`ASvE+0q0!AyVfH# zE_e=o+Z<1iK%F#hb{g1pQo-CDC;qg^-dfst-w8L_6%`etxVZQMNs^Xv3|4QA@1@Rs zm!+OkkbSPh8rXTRNMzm(Xl!hB-2r(Y6TGJea13Ge%L(#ql=p?}!C=fWoT=qGMt3D6 zJLgx*^UOSQ1G)Fx-GO;OcHIRV8XAW1ZuBPGC2*YS^ivkK(-h+*o7&Zdvfb@fRmtL6 tDuZ@bvThFJ{n6myU~%Qjl{@SzAp#49@K55s+?4pAi Date: Sun, 24 Mar 2024 14:03:16 +0530 Subject: [PATCH 436/864] fix: tauri update to fix some tauri plugin build error --- src-tauri/Cargo.lock | 333 ++++++++++++++++++++++--------------------- 1 file changed, 167 insertions(+), 166 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2d663039..1e2e0d02 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arboard" @@ -68,7 +68,7 @@ version = "3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2041f1943049c7978768d84e6d0fd95de98b76d6c4727b09e78ec253d29fa58" dependencies = [ - "clipboard-win 5.2.0", + "clipboard-win 5.3.0", "core-graphics 0.23.1", "image", "log", @@ -114,8 +114,8 @@ dependencies = [ "async-lock 3.3.0", "async-task", "concurrent-queue", - "fastrand 2.0.1", - "futures-lite 2.2.0", + "fastrand 2.0.2", + "futures-lite 2.3.0", "slab", ] @@ -161,10 +161,10 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "parking", - "polling 3.5.0", - "rustix 0.38.31", + "polling 3.6.0", + "rustix 0.38.32", "slab", "tracing", "windows-sys 0.52.0", @@ -203,19 +203,19 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.31", + "rustix 0.38.32", "windows-sys 0.48.0", ] [[package]] name = "async-recursion" -version = "1.0.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" +checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -230,7 +230,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 0.38.31", + "rustix 0.38.32", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -244,13 +244,13 @@ checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -274,7 +274,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -302,9 +302,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -344,9 +344,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block" @@ -372,18 +372,18 @@ dependencies = [ "async-channel", "async-lock 3.3.0", "async-task", - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-io", - "futures-lite 2.2.0", + "futures-lite 2.3.0", "piper", "tracing", ] [[package]] name = "brotli" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" +checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -416,17 +416,11 @@ version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" -[[package]] -name = "bytecount" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" - [[package]] name = "bytemuck" -version = "1.14.3" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" [[package]] name = "byteorder" @@ -436,9 +430,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] @@ -464,7 +458,7 @@ checksum = "3c55d429bef56ac9172d25fecb85dc8068307d17acd74b377866b7a1ef25d3c8" dependencies = [ "glib-sys", "libc", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -595,9 +589,9 @@ dependencies = [ [[package]] name = "clipboard-win" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f9a0700e0127ba15d1d52dd742097f821cd9c65939303a44d970465040a297" +checksum = "d517d4b86184dbb111d3556a10f1c8a04da7428d2987bf1081602bf11c3aa9ee" dependencies = [ "error-code 3.2.0", ] @@ -802,7 +796,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -812,7 +806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -836,7 +830,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -847,7 +841,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -879,7 +873,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -998,7 +992,7 @@ dependencies = [ "cc", "memchr", "rustc_version", - "toml 0.8.11", + "toml 0.8.12", "vswhom", "winreg 0.52.0", ] @@ -1036,7 +1030,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -1141,9 +1135,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fdeflate" @@ -1234,7 +1228,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -1317,11 +1311,11 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-core", "futures-io", "parking", @@ -1336,7 +1330,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -1416,7 +1410,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -1433,7 +1427,7 @@ dependencies = [ "libc", "pango-sys", "pkg-config", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -1447,7 +1441,7 @@ dependencies = [ "gobject-sys", "libc", "pkg-config", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -1459,7 +1453,7 @@ dependencies = [ "gdk-sys", "glib-sys", "libc", - "system-deps 6.2.0", + "system-deps 6.2.2", "x11", ] @@ -1550,7 +1544,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.2.0", + "system-deps 6.2.2", "winapi", ] @@ -1596,7 +1590,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" dependencies = [ "libc", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -1626,7 +1620,7 @@ checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" dependencies = [ "glib-sys", "libc", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -1667,7 +1661,7 @@ dependencies = [ "gobject-sys", "libc", "pango-sys", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -1686,9 +1680,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ "bytes", "fnv", @@ -1696,7 +1690,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -1730,6 +1724,12 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -1751,6 +1751,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "html5ever" version = "0.26.0" @@ -1934,9 +1943,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -2114,19 +2123,16 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "redox_syscall", ] [[package]] name = "line-wrap" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" -dependencies = [ - "safemem", -] +checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" [[package]] name = "linux-raw-sys" @@ -2339,9 +2345,9 @@ dependencies = [ [[package]] name = "new_debug_unreachable" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" @@ -2361,7 +2367,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "cfg_aliases", "libc", @@ -2544,7 +2550,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "foreign-types 0.3.2", "libc", @@ -2561,7 +2567,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -2600,13 +2606,13 @@ dependencies = [ [[package]] name = "os_info" -version = "3.7.0" +version = "3.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006e42d5b888366f1880eda20371fedde764ed2213dc8496f49622fa0c99cd5e" +checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" dependencies = [ "log", "serde", - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -2653,7 +2659,7 @@ dependencies = [ "glib-sys", "gobject-sys", "libc", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -2704,7 +2710,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.2.5", + "indexmap 2.2.6", ] [[package]] @@ -2811,7 +2817,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -2843,7 +2849,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.5.0" +version = "3.5.1" dependencies = [ "clipboard-files", "fix-path-env", @@ -2884,7 +2890,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" dependencies = [ "atomic-waker", - "fastrand 2.0.1", + "fastrand 2.0.2", "futures-io", ] @@ -2896,12 +2902,12 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" +checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9" dependencies = [ "base64 0.21.7", - "indexmap 2.2.5", + "indexmap 2.2.6", "line-wrap", "quick-xml 0.31.0", "serde", @@ -2939,14 +2945,15 @@ dependencies = [ [[package]] name = "polling" -version = "3.5.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24f040dee2588b4963afb4e420540439d126f73fdacf4a9c486a96d840bac3c9" +checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi 0.3.9", "pin-project-lite", - "rustix 0.38.31", + "rustix 0.38.32", "tracing", "windows-sys 0.52.0", ] @@ -3011,9 +3018,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -3198,9 +3205,9 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.25" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eea5a9eb898d3783f17c6407670e3592fd174cb81a10e51d4c37f49450b9946" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", @@ -3293,11 +3300,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys 0.4.13", @@ -3325,12 +3332,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - [[package]] name = "same-file" version = "1.0.6" @@ -3430,7 +3431,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3439,7 +3440,7 @@ version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "itoa 1.0.10", "ryu", "serde", @@ -3453,7 +3454,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3479,15 +3480,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" dependencies = [ "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_derive", "serde_json", @@ -3497,14 +3498,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3612,9 +3613,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -3745,9 +3746,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" dependencies = [ "proc-macro2", "quote", @@ -3775,20 +3776,20 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.6.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags 2.4.2", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.6.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ "core-foundation-sys", "libc", @@ -3809,15 +3810,15 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.2.0" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" dependencies = [ "cfg-expr 0.15.7", - "heck 0.4.1", + "heck 0.5.0", "pkg-config", - "toml 0.8.11", - "version-compare 0.1.1", + "toml 0.8.12", + "version-compare 0.2.0", ] [[package]] @@ -4036,7 +4037,7 @@ dependencies = [ [[package]] name = "tauri-plugin-fs-extra" version = "0.0.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#adbc333a0f233334a97cbabef266bf3fa6037d17" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edbbcfed8f8c057a15e02318e0ddcaab132" dependencies = [ "log", "serde", @@ -4048,7 +4049,7 @@ dependencies = [ [[package]] name = "tauri-plugin-single-instance" version = "0.0.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#adbc333a0f233334a97cbabef266bf3fa6037d17" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edbbcfed8f8c057a15e02318e0ddcaab132" dependencies = [ "log", "serde", @@ -4061,11 +4062,11 @@ dependencies = [ [[package]] name = "tauri-plugin-window-state" -version = "0.1.0" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#adbc333a0f233334a97cbabef266bf3fa6037d17" +version = "0.1.1" +source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edbbcfed8f8c057a15e02318e0ddcaab132" dependencies = [ "bincode", - "bitflags 2.4.2", + "bitflags 2.5.0", "log", "serde", "serde_json", @@ -4172,8 +4173,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", - "fastrand 2.0.1", - "rustix 0.38.31", + "fastrand 2.0.2", + "rustix 0.38.32", "windows-sys 0.52.0", ] @@ -4211,22 +4212,22 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -4365,14 +4366,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.7", + "toml_edit 0.22.9", ] [[package]] @@ -4390,7 +4391,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -4399,11 +4400,11 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.7" +version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -4435,7 +4436,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -4479,13 +4480,13 @@ dependencies = [ [[package]] name = "tree_magic_mini" -version = "3.0.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91adfd0607cacf6e4babdb870e9bec4037c1c4b151cfd279ccefc5e0c7feaa6d" +checksum = "77ee137597cdb361b55a4746983e4ac1b35ab6024396a419944ad473bb915265" dependencies = [ - "bytecount", "fnv", - "lazy_static", + "home", + "memchr", "nom", "once_cell", "petgraph", @@ -4582,9 +4583,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom 0.2.12", ] @@ -4609,9 +4610,9 @@ checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b" [[package]] name = "version-compare" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" @@ -4717,7 +4718,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", "wasm-bindgen-shared", ] @@ -4751,7 +4752,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4783,7 +4784,7 @@ checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40" dependencies = [ "cc", "downcast-rs", - "rustix 0.38.31", + "rustix 0.38.32", "scoped-tls", "smallvec", "wayland-sys", @@ -4795,8 +4796,8 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" dependencies = [ - "bitflags 2.4.2", - "rustix 0.38.31", + "bitflags 2.5.0", + "rustix 0.38.32", "wayland-backend", "wayland-scanner", ] @@ -4807,7 +4808,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -4819,7 +4820,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -4902,7 +4903,7 @@ dependencies = [ "pango-sys", "pkg-config", "soup2-sys", - "system-deps 6.2.0", + "system-deps 6.2.2", ] [[package]] @@ -5482,7 +5483,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" dependencies = [ "gethostname", - "rustix 0.38.31", + "rustix 0.38.32", "x11rb-protocol", ] @@ -5500,7 +5501,7 @@ checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" dependencies = [ "libc", "linux-raw-sys 0.4.13", - "rustix 0.38.31", + "rustix 0.38.32", ] [[package]] From 85bc285e52d7349dc5531987ad411e5b28a3241b Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 25 Mar 2024 08:24:15 +0000 Subject: [PATCH 437/864] ci: update phcode version to 3.5.4 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9a6c36ce..c35bcc6e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.5.1", + "version": "3.5.4", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "7d7704e1de9e3be00f5c18110f4cbf6ca8786423" + "commit": "0fa699b93dc577691322f1ee3edc5aee41e0c6de" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 10bdac66..89d4c982 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.5.1" +version = "3.5.4" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 3b376d6c..4e72cd95 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.5.1" + "version": "3.5.4" }, "tauri": { "allowlist": { From d60c859507ed3da2bfd41f1781bf43327adaf427 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 25 Mar 2024 17:16:03 +0000 Subject: [PATCH 438/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index f4c2b67f..fc2d403d 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,19 +1,19 @@ { - "version": "3.5.1", - "notes": "## New mac update test pre-release\r\nThis is a test release\r\n![image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/29cf6ddf-d0ca-4cc9-9694-9a17d7e65ac7)\r\n", - "pub_date": "2024-03-23T06:00:26.784Z", + "version": "3.5.4", + "notes": "## New mac update test pre-release\r\nThis is a test release 2\r\n![image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/29cf6ddf-d0ca-4cc9-9694-9a17d7e65ac7)\r\n", + "pub_date": "2024-03-25T11:18:00.236Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZWSkZmOGZFcHhZNEc5UkJpMGlmeWp0ZTlVenI5UDlZZWxTV3ZUTm8za0dQU0MvRXJpUHRzbTFpM2p4NlZad20wUnpQclVkV215c0V4cXBNa2UxWmdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMTcxNzQyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjUuMV94NjQtc2V0dXAubnNpcy56aXAKN0FpT3ZPa2Z4SWNWbmxmYlFLZWJib0I1c3VGcElhY3R2NHAvSjkwWEQ2TlRlaCsrL0ViZW12enNTSnBsYkMyOCtCZ3cxcExvd09QR2doY3pVUE1EQnc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.1/Phoenix.Code.Experimental.Build_3.5.1_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnQ2UGVYU1pkUE5ndDhwQUYxYWRFYmpnVEpzL3VuOFZ6RTZuZWUvTVFIaUVIQWoxaVNaT01ITmk0MUl2NGNsbzNLbDRVaW8wMmZWTTlCbTFDd0V5bEFzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMzYzNDc3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjUuNF94NjQtc2V0dXAubnNpcy56aXAKL3NiOUFNdmo0RERPSzVKamk4c2pzeU5BN1JRdGdQSGtkL2cvWE9ISXdCMmtSNTVmeTBLYnNkcGRTcTlya1pZSmg1TzZUc045RkRGWlBLUitXWVRtRFE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.4/Phoenix.Code.Experimental.Build_3.5.4_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmcvK2FXbDdyVFdCSnREMlk2QmhlY2pucUdzRkpmMVdxMFBGb2duNVhPVkFXbXZZUW1VSnZzRWdXZ05sd3lCdE4vRk1oaDFPUG5UU0g4SGxnN0Nla3d3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMTcyNTk4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cnc5Yjc5M2lBVndsS3dYblNwaDdmU1pPOWZ4TXdmQUZKQUNObXBuRm5YTkQxNGt3WlJ2QlhrN3p2K3dhd3JqUUhpVVdFRnhBRlpDQ1l0ZjcxU21MSUNnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnMxSFE0Q0pxTnpWZXlETFNSbmFFVitoNlc0TE84b2NHWTNEcjA5MkN4elVSRUZNcTRmM25HRkpsUDEwdW16RlBmTkwrL2txQ3JIYVJlZEVhVGJ5WUFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMzY0NDc3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjU1VFhYaVVuY2gvTUEvTlpseXdSNVBpdHpsU0RaMzBFN1Jqakx1S2dDZ2pWOFVObWxOcmQwRzBiaVcwV1dxdmdpUjFKTm52RUVhRHZCVk4xenBVMUNBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.4/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnJncytUNi9pa2ZxdzNaSXBoOWZWcjhXdG5aZGZDaWtyeXBqVmJCUXFxenlpRHd0NHZuajF2cFRmYmdPRTl5NDFGZHJLSWE3MWtMVmo3ekNaZzdtMXdBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMTczNjIwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmlVaHpQclJlNGQ3b0M3cVZUWVhXRXh6YVVMNVZSbVI0WjgyS0FsTUM5NXFxWUZCMDE2YTNZRlorcEpoM3FCVDdCNnhxM1lrTXZqbkFEMjk4aWNTbEFBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtueWwwQjZhQzdFcVVZeHQyQXJYNmVyekZpQ2RUcTZzQ3NFTDI3a3FqR0FlZWpXaXU3UThaMEpldis5ZmpNYnBzZU9TNGh5NjdtRmFxRVFpbXVxMlE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMzY1NDcyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmpsYkl3VzBrNkxHcnBScERudWxpK0hGSjM2Y1dxd0NycVdsdCtuYjdoK1JCRW5VUTZCaGtoS2xnVmE1UEYzaUI4a3ZZQndCMUVDTmxacWRrb2kyQkNRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.4/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From b74ea53c8c9f99a59852dc93146e6b678c40b80c Mon Sep 17 00:00:00 2001 From: phoenixide Date: Tue, 26 Mar 2024 06:36:32 +0000 Subject: [PATCH 439/864] ci: update phcode version to 3.5.5 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index c35bcc6e..0b733907 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.5.4", + "version": "3.5.5", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "0fa699b93dc577691322f1ee3edc5aee41e0c6de" + "commit": "7ee85edf2b8338a4730134f59c70a8402be51fa3" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 89d4c982..54ec9ceb 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.5.4" +version = "3.5.5" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4e72cd95..9688adda 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.5.4" + "version": "3.5.5" }, "tauri": { "allowlist": { From ee879a672d5edd8364981c15c24c3b5987d9af7f Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 Mar 2024 05:40:21 +0000 Subject: [PATCH 440/864] ci: tauri release update notification json --- docs/install.json | 6 +++--- docs/tauri/update-latest-stable-prod.json | 22 +++++++++------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/docs/install.json b/docs/install.json index eff91b92..4590a1ca 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,7 +1,7 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_3.4.6_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_3.4.6_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_3.4.6_x64.dmg" + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_3.5.5_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_3.5.5_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_3.5.5_x64.dmg" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index e78b278b..ee97029d 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,23 +1,19 @@ { - "version": "3.4.6", - "notes": "# Introducing Phoenix Code Desktop- Now on Windows, Mac & Linux 🎉\r\n\r\nWe're thrilled to share a huge update with you all today - Phoenix Code native apps are officially here! 🎉 . Get your copy from [phcode.io](https://phcode.io) !\r\n\r\nWe have been working hard over the last several months to make native apps possible. It took a lot of effort and perseverance with our limited resources to reach this far. We hope to have your support in doing more :)\r\n\r\nWith this update, Phoenix Code can now run almost anywhere! Native apps are available for Windows, Mac and most Linux distributions. For Chrome-OS and other platforms, simply use the web browser version; no install needed.\r\n\r\n## Looking Ahead\r\n\r\n> Our guiding principle is to make coding as intuitive and fun as playing a video game - for web developers, designers, and students.\r\n\r\nWith the native apps now available, we're starting the next phase of our journey. Beginning this month, there will be\r\na new update of Phoenix Code released every month.\r\n\r\nHowever, our ambitions come with costs, and it's your support that makes all the difference.\r\n\r\n## How You Can Support:\r\n * **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n * **Spread the word** about Phoenix to friends and colleagues.\r\n * [**Consider supporting us** on Open Collective](https://opencollective.com/phoenix-ide). Every contribution helps us to keep improving and expanding Phoenix Code.\r\n\r\nWe're grateful for the incredible support this community has shown us so far. Let's continue to make Phoenix Code even better, together.\r\n\r\nWith gratitude,\r\n\r\nThe Phoenix Team\r\n", - "pub_date": "2024-03-04T17:35:02.192Z", + "version": "3.5.5", + "notes": "The March release(3.5) of Phoenix Code is now available.\r\nThis month's update improves support for large projects, Find in Files, and app stability.\r\n\r\n## Inline HTML Number Dials\r\n\r\nYou can now use number dials in inline HTML styles, not just in CSS files.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/f56ab73b-c080-4f01-a083-f41aa10c3d16)\r\n\r\n## Search Filters - Advanced Find in Files\r\n\r\nAll new search filters to find exactly what you want. `Search in files` or\r\n`Exclude files` matching the given pattern instantly.\r\n\r\n![new find in files](https://github.com/phcode-dev/phoenix/assets/5336369/9a46a6a8-01a2-45db-aebc-9b280977bdc1)\r\n\r\n## Other Improvements\r\n\r\n- Projects with very large number of files can now be opened.\r\n- Performance improvement when opening minified CSS/JS files and other formats\r\n with very long lines.\r\n- Added support for beautifying SCSS, SASS, LESS, TSX, and JSX files. The\r\n beautification feature now preserves the cursor position.\r\n- Improved startup speed and overall app stability.\r\n- Bug fixes and improvements to new project dialog.\r\n", + "pub_date": "2024-03-26T07:44:25.476Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmgrdFFUblFKZXBONHhCL0tiMTdEQ21PWXp3VnNpOHE1b1NpNW5yVGxucnJlNmIvckVNT2poVzUvSEV6WEgyRWRFUTJ6Z3g1Ykc5RFkwcXFkMmRMRUFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5NTcxNDg1CWZpbGU6UGhvZW5peCBDb2RlXzMuNC42X3g2NC1zZXR1cC5uc2lzLnppcApDRU9WUTFuSVdNMDI1djMxMk9KT0pXcnRLeWxhWjlQUmI3emdualA2MnpBTmpqZGhKNlhXazc2TGFkWnMxVTNFL2N3d1hxZ0NTS1RRNks0Qng3eWNDQT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_3.4.6_x64-setup.nsis.zip" - }, - "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRmNVRTZXFrYlJCeGw1YTVIdTJpcVlZWTR5SnZaWkY5eXdDY01TaFp6MDUzQjBYUXA2a3FpTkZ0QVIrNmI3VHlaamhNdVZRc3BJTElnMTZ2a213ZFFZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5NTcxNDg5CWZpbGU6cGhvZW5peC1jb2RlXzMuNC42X2FtZDY0LkFwcEltYWdlLnRhci5negptOXNnQUNYYVk5a2tDVWN5ZUZtUTZpank0eUdMUHo0ZlVxOVRoRnNhU0VvejJiMEJIbGxnQW1Vb1lacWJyaXI4Y24rU0lsT3J0Yk9FK1ZualhjUi9EUT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/phoenix-code_3.4.6_amd64.AppImage.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBWZEVhNWRhOTN4VHMrWng2UFdxRUwxOHBRa1hMR0FrNmdncXV4ZXAzeUhPODlOSG4yc1E2K095N1VYUkhQbHZ4MGdIWCtaRTlVNEorYmh6M20wSGcwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNDM1OTI3CWZpbGU6UGhvZW5peCBDb2RlXzMuNS41X3g2NC1zZXR1cC5uc2lzLnppcApKMXl1VGc1aGlHQ3hSV1htYkg0SHlNSUNHQWdjNVgrNmdNTDdmRjkwSUdxejVUUDJuTi9jUWdoNkNyVVZGTTU2aWZRbkJjWUxvdFhCUHJSajlRNTFBQT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_3.5.5_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmx0RGdMYUxESUhrVEtiSmxlMndKQjZmWWZmcnRTYWVkUEt2YWlYMDVBSk1hVWZqOEI0RnUwVEVFb3JFaU5idUFraWFXSk5zR1hZNmNFRWp5Y3dqM3dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5NTcyNDczCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKU3RiYVdpcnp6aTFlUTVkR21UaERldWxwQ0FYYTk1eTcvSDFTYnlZUExlbEtMODZUREpwL3hYYnFqb3FUam9uNEp5ZlNGekFtNklSL3FIUWFpMUpaQmc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVVVVlkN2pMUDkrdjB6RGVudWJQZlVLdlRMN3F2SjFlOGRUaG9nMHg4TU5UVHZEZm9GYUZaajRJRlhRa2Z5ek5EMklaRlJGNmE2bjBEM3p5MGlVV2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNDM4MDAwCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdmtiNitPcld2SERwaFpodUc3Qjhza05XTGE3TjdrMkhWMGNDcEIxZUJJMHRic3h4UHF2QW9kR0taZmpvbVY0WXltUmhYVzEwMldnSFZ0UytIb3c3Q2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmltVU02SWdVY042bXZYQ1dqQ0JyUWRDbDF6VXY1d1BlV1RiL2xUQ0haR2l6c3RPcTAvMlVtWmxwT2VOLzZwZFFKajl6a2s1QkM2RStDMmZjOE5yN2d3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzA5NTczNjk0CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKZ1hVcmN1Ym5EYXN3U3dhbklZa0dyamNuTEswSzhNWG9XTlhyYVZKVTl1TS92NzdLelNKMFhiSkhyZzN6RVlFQTlqUzBEamFaaGJ5QXd5M0dtb3ZsQWc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.4.6/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtla2Y3TlB0WEE4TWhVZ29yTXoxVXJlVlJXb2hFc0hIeWQ1Mmkxa1Npays2SnFIMXFoRzFQMlZ6RW43OFpKRllqYXhLU1dFY0g3aXYxZktYTkJVNkFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNDM5MDU3CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKS1NOTHVsY0diWS9BKzVlVTZiclVOa0krVWlwdjk5N2lJNGgwR2V5OW5jSEpjU3E4QmhQWVVQRFYrTGtKbHFNeTJwbUhyWWZhQXFCTDg2d01aZ1I0REE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 1b0263a31fded441a87b482fe9ae8db81d6d615b Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 27 Mar 2024 08:35:54 +0000 Subject: [PATCH 441/864] ci: update phcode version to 3.5.6 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 0b733907..3449be6f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.5.5", + "version": "3.5.6", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "7ee85edf2b8338a4730134f59c70a8402be51fa3" + "commit": "d3636c1527dbbd772b34a542b606978f264ab97b" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 54ec9ceb..9c41f911 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.5.5" +version = "3.5.6" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 9688adda..b63f39de 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.5.5" + "version": "3.5.6" }, "tauri": { "allowlist": { From 37d20076657b10d2808b7c03b3fe583c428aa4b1 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 Mar 2024 09:24:31 +0000 Subject: [PATCH 442/864] ci: tauri release update notification json --- docs/install.json | 6 +++--- docs/tauri/update-latest-stable-prod.json | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/install.json b/docs/install.json index 4590a1ca..4ea8a7c7 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,7 +1,7 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_3.5.5_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_3.5.5_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_3.5.5_x64.dmg" + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_3.5.6_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_3.5.6_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_3.5.6_x64.dmg" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index ee97029d..2bcdaf7c 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,19 +1,19 @@ { - "version": "3.5.5", - "notes": "The March release(3.5) of Phoenix Code is now available.\r\nThis month's update improves support for large projects, Find in Files, and app stability.\r\n\r\n## Inline HTML Number Dials\r\n\r\nYou can now use number dials in inline HTML styles, not just in CSS files.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/f56ab73b-c080-4f01-a083-f41aa10c3d16)\r\n\r\n## Search Filters - Advanced Find in Files\r\n\r\nAll new search filters to find exactly what you want. `Search in files` or\r\n`Exclude files` matching the given pattern instantly.\r\n\r\n![new find in files](https://github.com/phcode-dev/phoenix/assets/5336369/9a46a6a8-01a2-45db-aebc-9b280977bdc1)\r\n\r\n## Other Improvements\r\n\r\n- Projects with very large number of files can now be opened.\r\n- Performance improvement when opening minified CSS/JS files and other formats\r\n with very long lines.\r\n- Added support for beautifying SCSS, SASS, LESS, TSX, and JSX files. The\r\n beautification feature now preserves the cursor position.\r\n- Improved startup speed and overall app stability.\r\n- Bug fixes and improvements to new project dialog.\r\n", - "pub_date": "2024-03-26T07:44:25.476Z", + "version": "3.5.6", + "notes": "The March release(3.5.6) of Phoenix Code is now available.\r\nThis month's update improves support for large projects, Find in Files, and app stability.\r\n\r\n## Inline HTML Number Dials\r\n\r\nYou can now use number dials in inline HTML styles, not just in CSS files.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/f56ab73b-c080-4f01-a083-f41aa10c3d16)\r\n\r\n## Search Filters - Advanced Find in Files\r\n\r\nAll new search filters to find exactly what you want. `Search in files` or\r\n`Exclude files` matching the given pattern instantly.\r\n\r\n![new find in files](https://github.com/phcode-dev/phoenix/assets/5336369/9a46a6a8-01a2-45db-aebc-9b280977bdc1)\r\n\r\n## Other Improvements\r\n\r\n- Projects with very large number of files can now be opened.\r\n- Performance improvement when opening minified CSS/JS files and other formats\r\n with very long lines.\r\n- Added support for beautifying SCSS, SASS, LESS, TSX, and JSX files. The\r\n beautification feature now preserves the cursor position.\r\n- Improved startup speed and overall app stability.\r\n- Bug fixes and improvements to new project dialog.\r\n", + "pub_date": "2024-03-27T09:12:43.357Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBWZEVhNWRhOTN4VHMrWng2UFdxRUwxOHBRa1hMR0FrNmdncXV4ZXAzeUhPODlOSG4yc1E2K095N1VYUkhQbHZ4MGdIWCtaRTlVNEorYmh6M20wSGcwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNDM1OTI3CWZpbGU6UGhvZW5peCBDb2RlXzMuNS41X3g2NC1zZXR1cC5uc2lzLnppcApKMXl1VGc1aGlHQ3hSV1htYkg0SHlNSUNHQWdjNVgrNmdNTDdmRjkwSUdxejVUUDJuTi9jUWdoNkNyVVZGTTU2aWZRbkJjWUxvdFhCUHJSajlRNTFBQT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_3.5.5_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm4za1hibVV1cllUMFlEWkJBcndlMi9aVmFwNFdPY3RCMGlSdlU1akdzNHV6cUEybnE0U3Y5cHpKS1BSdXpORFVnNDBud2RTNTlKdHc1RTZiQVc5RkFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNTI5NjI5CWZpbGU6UGhvZW5peCBDb2RlXzMuNS42X3g2NC1zZXR1cC5uc2lzLnppcApoclExc3lGRGEyNDN1YXRyN2RONFVDNWN2RmVjYjV4TFR3ZGRpdW9ENE1BeXVOY3R0Tnd3SERXb21oUG9QVHFwVmd3NGxZOU1CMzR0SmNRemRSU3NCZz09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_3.5.6_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVVVVlkN2pMUDkrdjB6RGVudWJQZlVLdlRMN3F2SjFlOGRUaG9nMHg4TU5UVHZEZm9GYUZaajRJRlhRa2Z5ek5EMklaRlJGNmE2bjBEM3p5MGlVV2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNDM4MDAwCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdmtiNitPcld2SERwaFpodUc3Qjhza05XTGE3TjdrMkhWMGNDcEIxZUJJMHRic3h4UHF2QW9kR0taZmpvbVY0WXltUmhYVzEwMldnSFZ0UytIb3c3Q2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRmcWZITmkzNTRwOWZORmlFRUtZWTZsN1FlTGJoblBVejhxUERxMTZDQXpUVU5pWUMrNytkWHl0aDZGMVdGVXZVRk1UK2xzaUNvNnBtVFkvNDZqcXdzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNTMwMDYwCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKUjJVZVM0WHV0WmhySzlRdlg2b09DdUxKSW5UUm1OUjA4bkdDK3V3bngzUnlUYVhPdDFvT2tjQmFLQzU1bnBnclRRTG5nNDdQTml3SzYzQ2FuaWFDQkE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtla2Y3TlB0WEE4TWhVZ29yTXoxVXJlVlJXb2hFc0hIeWQ1Mmkxa1Npays2SnFIMXFoRzFQMlZ6RW43OFpKRllqYXhLU1dFY0g3aXYxZktYTkJVNkFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNDM5MDU3CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKS1NOTHVsY0diWS9BKzVlVTZiclVOa0krVWlwdjk5N2lJNGgwR2V5OW5jSEpjU3E4QmhQWVVQRFYrTGtKbHFNeTJwbUhyWWZhQXFCTDg2d01aZ1I0REE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.5/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1JcFdPTDFzdHRkbjhYU25maU1yTE4zbVlCOEZTUG5kcmFSVi9naWZqc2o4WEZvalJBUGpJelYrTHFnRExuT2ZsV1M3Z2xaaHJUb0p3N1pralk1dWdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNTMwNzUzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKQjVtTStrYjhHR0V3ZnFvaWN3cldDUnEyd3k0ZkExRjNucXFxNGNNdWtHUHgrU0dtY2wvMHNZTVZCOGxsVGE4UjBkSEE5UE9FL0N3VXRycXlTZ0RwQnc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 63e08314d5bfd9eccbb8b614efe530eaf57e032e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 16:39:19 +0000 Subject: [PATCH 443/864] chore(deps): update dependency axios-retry to v4.1.0 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2732730c..57e123af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@tauri-apps/cli": "1.5.11", "adm-zip": "0.5.12", "axios": "1.6.8", - "axios-retry": "4.0.0", + "axios-retry": "4.1.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", @@ -270,9 +270,9 @@ } }, "node_modules/axios-retry": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.0.0.tgz", - "integrity": "sha512-F6P4HVGITD/v4z9Lw2mIA24IabTajvpDZmKa6zq/gGwn57wN5j1P3uWrAV0+diqnW6kTM2fTqmWNfgYWGmMuiA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.1.0.tgz", + "integrity": "sha512-svdth4H00yhlsjBbjfLQ/sMLkXqeLxhiFC1nE1JtkN/CIssGxqk0UwTEdrVjwA2gr3yJkAulwvDSIm4z4HyPvg==", "dev": true, "dependencies": { "is-retry-allowed": "^2.2.0" @@ -1535,9 +1535,9 @@ } }, "axios-retry": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.0.0.tgz", - "integrity": "sha512-F6P4HVGITD/v4z9Lw2mIA24IabTajvpDZmKa6zq/gGwn57wN5j1P3uWrAV0+diqnW6kTM2fTqmWNfgYWGmMuiA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.1.0.tgz", + "integrity": "sha512-svdth4H00yhlsjBbjfLQ/sMLkXqeLxhiFC1nE1JtkN/CIssGxqk0UwTEdrVjwA2gr3yJkAulwvDSIm4z4HyPvg==", "dev": true, "requires": { "is-retry-allowed": "^2.2.0" diff --git a/package.json b/package.json index 3449be6f..f43fd925 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "shx": "^0.3.4", "tar": "6.2.1", "axios": "1.6.8", - "axios-retry": "4.0.0" + "axios-retry": "4.1.0" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From 30113deab9c8159f60b3cb869e541a306fbfaf53 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 7 Apr 2024 19:33:49 +0530 Subject: [PATCH 444/864] feat: adding support for kali linux --- docs/linux/installer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 73eb5f1c..e8abc0f8 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -196,7 +196,7 @@ install_dependencies() { # Install dependencies based on the distribution case "$DISTRO" in - ubuntu|debian|linuxmint) + ubuntu|debian|linuxmint|kali) echo "Detected an Ubuntu/Debian based distribution." sudo apt update sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ From e614def28dd6e688f2ff9b998aff05dd267f40e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 16:25:45 +0000 Subject: [PATCH 445/864] build(deps): bump h2 from 0.3.25 to 0.3.26 in /src-tauri Bumps [h2](https://github.com/hyperium/h2) from 0.3.25 to 0.3.26. - [Release notes](https://github.com/hyperium/h2/releases) - [Changelog](https://github.com/hyperium/h2/blob/v0.3.26/CHANGELOG.md) - [Commits](https://github.com/hyperium/h2/compare/v0.3.25...v0.3.26) --- updated-dependencies: - dependency-name: h2 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1e2e0d02..5500d87d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1680,9 +1680,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -1831,7 +1831,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -2849,7 +2849,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.5.1" +version = "3.5.6" dependencies = [ "clipboard-files", "fix-path-env", From 9fb59ba5c09f4ebfcb91774774791d0aa9490f94 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 11 Apr 2024 11:20:56 +0530 Subject: [PATCH 446/864] chore: update github sponsor funding link --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index dc5664fd..1ba68ea2 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,6 +1,6 @@ # These are supported funding model platforms -github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +github: [phcode-dev] patreon: # Replace with a single Patreon username open_collective: phoenix-ide ko_fi: # Replace with a single Ko-fi username From 2a6d6b16cdf149d9dae62765a932f494659d1537 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 15 Apr 2024 23:21:08 +0530 Subject: [PATCH 447/864] fix: extra / is path when show in os files is done --- src-tauri/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 166633b6..e3c7fe3f 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -173,7 +173,7 @@ fn show_in_folder(path: String) { .arg("--type=method_call") .arg("/org/freedesktop/FileManager1") .arg("org.freedesktop.FileManager1.ShowItems") - .arg(format!("array:string:file:///{}", path)) + .arg(format!("array:string:file://{}", path)) .arg("string:\"\"") .spawn() .unwrap(); From 15695dd99000c313f39383c8eae6fe9a986f86ad Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 21 Apr 2024 18:21:46 +0530 Subject: [PATCH 448/864] chore: add survey link jsons --- docs/surveys.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 docs/surveys.json diff --git a/docs/surveys.json b/docs/surveys.json new file mode 100644 index 00000000..5cbeb0bb --- /dev/null +++ b/docs/surveys.json @@ -0,0 +1,4 @@ +{ + "newUser": "https://s.surveyplanet.com/g837j5k9", + "powerUser": "https://s.surveyplanet.com/v3j59a7z" +} \ No newline at end of file From 1ea997ce5e5c4482e0d565272014c013db898183 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 26 Apr 2024 16:02:07 +0000 Subject: [PATCH 449/864] ci: update phcode version to 3.6.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index f43fd925..31073c9c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.5.6", + "version": "3.6.1", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "d3636c1527dbbd772b34a542b606978f264ab97b" + "commit": "1823d82dd96304616276ae654dc00d795791a0ed" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9c41f911..37a99019 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.5.6" +version = "3.6.1" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index b63f39de..510b2111 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.5.6" + "version": "3.6.1" }, "tauri": { "allowlist": { From 875c167348a63ccbdd9c0b077190366fd703e9c2 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 26 Apr 2024 23:38:57 +0530 Subject: [PATCH 450/864] build: script to list node modules folder in mac before signing --- .github/workflows/tauri-build-dev.yml | 8 ++++++++ .github/workflows/tauri-build-prod.yml | 8 ++++++++ .github/workflows/tauri-build-staging.yml | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index be8c5b57..27a20fd2 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -167,6 +167,14 @@ jobs: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} run: | + echo "Listing all files in src-tauri/src-node" + echo "=======================================" + find src-tauri/src-node -type f + echo "=======================================" + echo "Listing all files in src-node/" + echo "=======================================" + find src-node/ -type f + certificate_encoded="$APPLE_CERTIFICATE" certificate_password="$APPLE_CERTIFICATE_PASSWORD" diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 0350ca74..990a72e9 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -168,6 +168,14 @@ jobs: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} run: | + echo "Listing all files in src-tauri/src-node" + echo "=======================================" + find src-tauri/src-node -type f + echo "=======================================" + echo "Listing all files in src-node/" + echo "=======================================" + find src-node/ -type f + certificate_encoded="$APPLE_CERTIFICATE" certificate_password="$APPLE_CERTIFICATE_PASSWORD" diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index d85b7fd7..b700f4dd 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -165,6 +165,14 @@ jobs: APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} run: | + echo "Listing all files in src-tauri/src-node" + echo "=======================================" + find src-tauri/src-node -type f + echo "=======================================" + echo "Listing all files in src-node/" + echo "=======================================" + find src-node/ -type f + certificate_encoded="$APPLE_CERTIFICATE" certificate_password="$APPLE_CERTIFICATE_PASSWORD" From ba8e23b8a9127602e3c95daa9234512238d9bf3d Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 27 Apr 2024 00:33:23 +0530 Subject: [PATCH 451/864] fix: release generation break as github migrated default macos runners to arm from intel --- .github/workflows/desktop-mac-test-pull.yml | 2 +- .github/workflows/tauri-build-dev.yml | 14 +++++++------- .github/workflows/tauri-build-prod.yml | 14 +++++++------- .github/workflows/tauri-build-staging.yml | 14 +++++++------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index df53d242..2edca26c 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -9,7 +9,7 @@ concurrency: jobs: test-desktop-mac: - runs-on: macos-latest + runs-on: macos-12 timeout-minutes: 90 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 27a20fd2..fc0f823c 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, windows-latest ] + platform: [ macos-12, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -92,7 +92,7 @@ jobs: node-version: 20 - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' uses: actions/download-artifact@v4 with: name: src-node-darwin-arm64.tar.gz @@ -108,7 +108,7 @@ jobs: npm run _ci-release:dev - name: setup src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' run: | ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node @@ -161,7 +161,7 @@ jobs: Set-Content -Path "./secrets.json" -Value $content shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -229,7 +229,7 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: inject src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' run: | ls src-node rm -rf src-tauri/src-node @@ -239,12 +239,12 @@ jobs: - name: setup env for mac arm (Mac only) env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 990a72e9..2ffa9831 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, windows-latest ] + platform: [ macos-12, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -92,7 +92,7 @@ jobs: node-version: 20 - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' uses: actions/download-artifact@v4 with: name: src-node-darwin-arm64.tar.gz @@ -108,7 +108,7 @@ jobs: npm run _ci-release:prod - name: setup src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' run: | ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node @@ -162,7 +162,7 @@ jobs: shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -230,7 +230,7 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: inject src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' run: | ls src-node rm -rf src-tauri/src-node @@ -240,12 +240,12 @@ jobs: - name: setup env for mac arm (Mac only) env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index b700f4dd..a74bd54a 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-latest, windows-latest ] + platform: [ macos-12, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -92,7 +92,7 @@ jobs: node-version: 20 - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' uses: actions/download-artifact@v4 with: name: src-node-darwin-arm64.tar.gz @@ -106,7 +106,7 @@ jobs: npm run _ci-release:staging - name: setup src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' run: | ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node @@ -159,7 +159,7 @@ jobs: Set-Content -Path "./secrets.json" -Value $content shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -227,7 +227,7 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: inject src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' run: | ls src-node rm -rf src-tauri/src-node @@ -237,12 +237,12 @@ jobs: - name: setup env for mac arm (Mac only) env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-latest' + if: matrix.platform == 'macos-12' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 69d8d3b48442f460f59067a1826d7790f65c3f27 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 27 Apr 2024 02:23:57 +0530 Subject: [PATCH 452/864] fix: installer was failing in Fedora 40 --- docs/linux/installer.sh | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index e8abc0f8..626b4664 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -404,7 +404,7 @@ downloadLatestReleaseInfo() { if [ -f "$release_info_file" ]; then # Only extract and echo the version number, without any additional messages - grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" + grep -Po '"tag_name":\s*"prod-app-v\K[\d.]+(?=")' "$release_info_file" return fi @@ -416,7 +416,7 @@ downloadLatestReleaseInfo() { } # Only extract and echo the version number after successful download - grep -Po '"tag_name": "prod-app-v\K[\d.]+(?=")' "$release_info_file" + grep -Po '"tag_name":\s*"prod-app-v\K[\d.]+(?=")' "$release_info_file" } # Download Latest Release Information Function @@ -475,7 +475,7 @@ downloadAndInstall(){ BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" fi - done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") + done < <(grep -oP '"browser_download_url"\s*:\s*"\K[^"]*_linux_bin-GLIBC-[\d\.]+\.tar\.gz(?=")' "$TMP_DIR/latest_release.json") if [ -z "$BEST_MATCH_URL" ]; then echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" @@ -483,14 +483,21 @@ downloadAndInstall(){ fi echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { + # Set options based on wget version + WGET_OPTS=$(configure_wget_options) + + # Download the code tarball + echo -e "Downloading the code tarball..." + wget $WGET_OPTS "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" 2>/dev/null || { echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" exit 1 } + + # Download the icon echo -e "Downloading the icon..." - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { - echo -e "${RED}Failed to download Icon${RESET}"; - exit 1; + wget $WGET_OPTS "$TMP_DIR/icon.png" "$ICON_URL" 2>/dev/null|| { + echo -e "${RED}Failed to download the icon${RESET}" + exit 1 } echo "Extracting the binary to $TMP_DIR..." tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { @@ -504,6 +511,17 @@ downloadAndInstall(){ exit 1 fi } +# Function to check wget version and configure options +configure_wget_options() { + local wget_version=$(wget --version | head -n1 | awk '{print $3}') + local major_version=$(echo "$wget_version" | cut -d. -f1) + + if [[ "$major_version" -ge 2 ]]; then + echo "-c -N --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" + else + echo "-c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO" + fi +} # Install Function # # Purpose: From ef6953be116e23db5176f55ceb3e584f72869b0b Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 27 Apr 2024 02:28:43 +0530 Subject: [PATCH 453/864] chore: code clean up --- docs/linux/installer.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 626b4664..b9efe6fe 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -486,8 +486,6 @@ downloadAndInstall(){ # Set options based on wget version WGET_OPTS=$(configure_wget_options) - # Download the code tarball - echo -e "Downloading the code tarball..." wget $WGET_OPTS "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" 2>/dev/null || { echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" exit 1 From 73b07365a772143f16742685cff2b56c25d237c9 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 27 Apr 2024 13:11:20 +0530 Subject: [PATCH 454/864] fix: progress bar not working for linux installer --- docs/linux/installer.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index b9efe6fe..89202189 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -486,14 +486,14 @@ downloadAndInstall(){ # Set options based on wget version WGET_OPTS=$(configure_wget_options) - wget $WGET_OPTS "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" 2>/dev/null || { + wget $WGET_OPTS "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" exit 1 } # Download the icon echo -e "Downloading the icon..." - wget $WGET_OPTS "$TMP_DIR/icon.png" "$ICON_URL" 2>/dev/null|| { + wget $WGET_OPTS "$TMP_DIR/icon.png" "$ICON_URL" || { echo -e "${RED}Failed to download the icon${RESET}" exit 1 } @@ -515,7 +515,7 @@ configure_wget_options() { local major_version=$(echo "$wget_version" | cut -d. -f1) if [[ "$major_version" -ge 2 ]]; then - echo "-c -N --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" + echo "-c --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" else echo "-c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO" fi From 4490efbdad4aea3172f330a9a7ad26e7745c97fe Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 27 Apr 2024 17:27:50 +0000 Subject: [PATCH 455/864] ci: update phcode version to 3.6.2 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 31073c9c..62fb78e3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.6.1", + "version": "3.6.2", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "1823d82dd96304616276ae654dc00d795791a0ed" + "commit": "6891ec37d245bf9d4aaffaa740dda00fdc2b1422" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 37a99019..5a45a851 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.6.1" +version = "3.6.2" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 510b2111..17b798e2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.6.1" + "version": "3.6.2" }, "tauri": { "allowlist": { From 1394a7ba5416632d96f8301bb06e6ab0a8f458cd Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 27 Apr 2024 17:51:55 +0000 Subject: [PATCH 456/864] ci: update phcode version to 3.6.3 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 62fb78e3..9e5bf91c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.6.2", + "version": "3.6.3", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "6891ec37d245bf9d4aaffaa740dda00fdc2b1422" + "commit": "5b19c350c927573472ec0fac8504baeb12690a16" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5a45a851..a9b73a46 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.6.2" +version = "3.6.3" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 17b798e2..ce9defef 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.6.2" + "version": "3.6.3" }, "tauri": { "allowlist": { From da3d12fd1d0a8f72d25323888f23ab2435a365f5 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 28 Apr 2024 07:26:33 +0000 Subject: [PATCH 457/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index fc2d403d..d908492f 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,19 +1,19 @@ { - "version": "3.5.4", - "notes": "## New mac update test pre-release\r\nThis is a test release 2\r\n![image](https://github.com/phcode-dev/phoenix-desktop/assets/5336369/29cf6ddf-d0ca-4cc9-9694-9a17d7e65ac7)\r\n", - "pub_date": "2024-03-25T11:18:00.236Z", + "version": "3.6.3", + "notes": "Pre-release test\r\nApril release(3.6) of Phoenix Code is now available.\r\n\r\nThis month's upgrade is big! with a lot of features you asked for - PHP/Custom\r\nlive preview servers, advanced CSS/LESS/SCSS/HTML code intelligence and tooling,\r\nUX and app stability improvements.\r\n\r\n## Custom Live Preview Servers\r\n\r\nPreview PHP, React, and other dynamically rendered files with the\r\nnew server settings dialog. Read more at\r\n[Live Preview Settings Docs](https://docs.phcode.dev/docs/Features/live-preview-settings/).\r\n\r\n![Screenshot from 2024-04-12 13-08-34](https://github.com/phcode-dev/phoenix/assets/5336369/69fa0ee4-7262-42af-97d2-26154ec4a3b9)\r\n\r\n#### HTML Code Intelligence\r\n\r\nCSS class hints are now shown within the HTML file's class attribute.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/112ad909-8fd0-4fc4-8042-041ecade9481)\r\n\r\n## Advanced CSS Tooling\r\n\r\nSupport for the latest CSS/LESS/SCSS syntax. Code intelligence and error\r\ndetection for CSS, SCSS, and LESS files.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/9c083bd3-9e34-418d-a1c8-c152393c37b2)\r\n\r\n## Reverse CSS Highlighting\r\n\r\nClicking an element in the live preview now highlights its selector in the\r\nsource CSS file editor.\r\n\r\n## Editor Rulers\r\n\r\nAdd multiple, color-customizable rulers in the editor to better visualize line\r\nlengths. [Read more...](https://docs.phcode.dev/docs/Features/editor-rulers/)\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/71b8b04c-d2ca-47b8-84bb-53cd0fb4593c)\r\n\r\n## Open Live Preview in any Browser\r\n\r\nDirect buttons to open live previews in Chrome, Edge, Safari, and Firefox.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/05f92c99-8a35-45a5-a8ee-75d581e6e96a)\r\n\r\n## Docusaurus Support\r\n\r\nLive preview [docusaurus.io](https://docusaurus.io/) based markdown documentation server.\r\n\r\n## UX Improvements\r\n\r\nIncreased stability and more predictable live preview behavior.\r\n\r\n## Community Contributions\r\n\r\n1. Changes to files and folders made externally are now automatically synced in\r\n the Browser version of Phoenix Code.\r\n ([view change](https://github.com/phcode-dev/phoenix/pull/1566)) - By\r\n [Andrew Young](https://github.com/ayoung5555),\r\n [Faizan Bhagat](https://github.com/faizanbhagat)\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", + "pub_date": "2024-04-27T18:54:57.783Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnQ2UGVYU1pkUE5ndDhwQUYxYWRFYmpnVEpzL3VuOFZ6RTZuZWUvTVFIaUVIQWoxaVNaT01ITmk0MUl2NGNsbzNLbDRVaW8wMmZWTTlCbTFDd0V5bEFzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMzYzNDc3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjUuNF94NjQtc2V0dXAubnNpcy56aXAKL3NiOUFNdmo0RERPSzVKamk4c2pzeU5BN1JRdGdQSGtkL2cvWE9ISXdCMmtSNTVmeTBLYnNkcGRTcTlya1pZSmg1TzZUc045RkRGWlBLUitXWVRtRFE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.4/Phoenix.Code.Experimental.Build_3.5.4_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBObjdwNXFnVlRBVG16cmYwaDZjcDNrd3cyNG1zWlIvY2p1K2ttZ3ludCtiRFdHV24yclpwRWN1R2pXM3piSnp1TktRdy9oSGVaUlEvd0JPQ3VrWWdzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MjQxMjg2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjYuM194NjQtc2V0dXAubnNpcy56aXAKbC9EOHgraE54SlBKaWxDN3Jla1FNUGVQU3lFZCsxSEgvODhzbU5LQ1JxL1pQV2FqM1JMSko3MVh1K2lWS2VJUTJWcDFKSGcvZ2dSem0vODZLS3ZuQ2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.6.3/Phoenix.Code.Experimental.Build_3.6.3_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnMxSFE0Q0pxTnpWZXlETFNSbmFFVitoNlc0TE84b2NHWTNEcjA5MkN4elVSRUZNcTRmM25HRkpsUDEwdW16RlBmTkwrL2txQ3JIYVJlZEVhVGJ5WUFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMzY0NDc3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjU1VFhYaVVuY2gvTUEvTlpseXdSNVBpdHpsU0RaMzBFN1Jqakx1S2dDZ2pWOFVObWxOcmQwRzBiaVcwV1dxdmdpUjFKTm52RUVhRHZCVk4xenBVMUNBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.4/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9IaVNXc3VGaGJzMUd1em5wUjg1dVdWcGh5MnZUdmY2dXdETzFyU2tsTWhZcVRZZlNlcWR5WDJ0MUNpY1o2c05zQnR3VWhoZC9oazhGa09TakE3WkFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MjQzMzM0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjVmR3ZTeDJFTDl1Tll0b3o3QUQyOVF4aTFLYUtWSi9WR2JwLzVjQ3BqWGtPRlVLVENTUG4venhUV3VkZFlJSkxDLzJPcUFWS0dJN1ZYYSsvM25sR0R3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.6.3/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtueWwwQjZhQzdFcVVZeHQyQXJYNmVyekZpQ2RUcTZzQ3NFTDI3a3FqR0FlZWpXaXU3UThaMEpldis5ZmpNYnBzZU9TNGh5NjdtRmFxRVFpbXVxMlE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExMzY1NDcyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmpsYkl3VzBrNkxHcnBScERudWxpK0hGSjM2Y1dxd0NycVdsdCtuYjdoK1JCRW5VUTZCaGtoS2xnVmE1UEYzaUI4a3ZZQndCMUVDTmxacWRrb2kyQkNRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.5.4/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBDdFIvOXlXQkJNZ2h3L0pEOHEwRU01cEQydWdDZ29IenVjQVhYSUFzb1ZmZGlaWlcvRmtoQitNRWErVkRzcEdxY2tBNEtEbTNYK2ZjQjVVbVVEMndnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MjQ0MDkzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CkVmbXJsVnNiekIrTElVelFtc3Vmdys4bXFLUzJOOW0xODY2SC9IMnYvbmRsTGdDNHZrMjNSVEUzbVhRaG51RDBlcnk5VTcxeDNMZEtVbGNTRFpqUUFBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.6.3/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From e1ddd98055ac9891d1e42b5b6da1ee52f75d6ba5 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 29 Apr 2024 11:28:17 +0000 Subject: [PATCH 458/864] ci: update phcode version to 3.6.4 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9e5bf91c..589feba9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.6.3", + "version": "3.6.4", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "5b19c350c927573472ec0fac8504baeb12690a16" + "commit": "ec66f0ad0e752304047acb3fdacdfba0ea1d5026" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a9b73a46..eac44a3d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.6.3" +version = "3.6.4" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ce9defef..b477b1d8 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.6.3" + "version": "3.6.4" }, "tauri": { "allowlist": { From 5e382726f46a15847ded9a3558a68c9727655ffd Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Apr 2024 14:11:22 +0000 Subject: [PATCH 459/864] ci: tauri release update notification json --- docs/install.json | 6 +++--- docs/tauri/update-latest-stable-prod.json | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/install.json b/docs/install.json index 4ea8a7c7..14968c43 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,7 +1,7 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_3.5.6_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_3.5.6_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_3.5.6_x64.dmg" + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_3.6.4_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_3.6.4_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_3.6.4_x64.dmg" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 2bcdaf7c..95c70e56 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,19 +1,19 @@ { - "version": "3.5.6", - "notes": "The March release(3.5.6) of Phoenix Code is now available.\r\nThis month's update improves support for large projects, Find in Files, and app stability.\r\n\r\n## Inline HTML Number Dials\r\n\r\nYou can now use number dials in inline HTML styles, not just in CSS files.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/f56ab73b-c080-4f01-a083-f41aa10c3d16)\r\n\r\n## Search Filters - Advanced Find in Files\r\n\r\nAll new search filters to find exactly what you want. `Search in files` or\r\n`Exclude files` matching the given pattern instantly.\r\n\r\n![new find in files](https://github.com/phcode-dev/phoenix/assets/5336369/9a46a6a8-01a2-45db-aebc-9b280977bdc1)\r\n\r\n## Other Improvements\r\n\r\n- Projects with very large number of files can now be opened.\r\n- Performance improvement when opening minified CSS/JS files and other formats\r\n with very long lines.\r\n- Added support for beautifying SCSS, SASS, LESS, TSX, and JSX files. The\r\n beautification feature now preserves the cursor position.\r\n- Improved startup speed and overall app stability.\r\n- Bug fixes and improvements to new project dialog.\r\n", - "pub_date": "2024-03-27T09:12:43.357Z", + "version": "3.6.4", + "notes": "April release(3.6) of Phoenix Code is now available.\r\n\r\nThis month's upgrade is big! with a lot of features you asked for - PHP/Custom\r\nlive preview servers, advanced CSS/LESS/SCSS/HTML code intelligence and tooling,\r\nUX and app stability improvements.\r\n\r\n## Custom Live Preview Servers\r\n\r\nPreview PHP, React, and other dynamically rendered files with the\r\nnew server settings dialog. Read more at\r\n[Live Preview Settings Docs](https://docs.phcode.dev/docs/Features/live-preview-settings/).\r\n\r\n![Screenshot from 2024-04-12 13-08-34](https://github.com/phcode-dev/phoenix/assets/5336369/69fa0ee4-7262-42af-97d2-26154ec4a3b9)\r\n\r\n#### HTML Code Intelligence\r\n\r\nCSS class hints are now shown within the HTML file's class attribute.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/112ad909-8fd0-4fc4-8042-041ecade9481)\r\n\r\n## Advanced CSS Tooling\r\n\r\nSupport for the latest CSS/LESS/SCSS syntax. Code intelligence and error\r\ndetection for CSS, SCSS, and LESS files.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/9c083bd3-9e34-418d-a1c8-c152393c37b2)\r\n\r\n## Reverse CSS Highlighting\r\n\r\nClicking an element in the live preview now highlights its selector in the\r\nsource CSS file editor.\r\n![Reverse CSS Highlighting gif](https://github.com/phcode-dev/phoenix/assets/5336369/dcb9a111-60fa-479b-8766-dd3109b2134f)\r\n\r\n## Editor Rulers\r\n\r\nAdd multiple, color-customizable rulers in the editor to better visualize line\r\nlengths. [Read more...](https://docs.phcode.dev/docs/Features/editor-rulers/)\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/71b8b04c-d2ca-47b8-84bb-53cd0fb4593c)\r\n\r\n## Open Live Preview in any Browser\r\n\r\nDirect buttons to open live previews in Chrome, Edge, Safari, and Firefox.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/05f92c99-8a35-45a5-a8ee-75d581e6e96a)\r\n\r\n## Docusaurus Support\r\n\r\nLive preview [docusaurus.io](https://docusaurus.io/) based markdown documentation server.\r\n\r\n## UX Improvements\r\n\r\nIncreased stability and more predictable live preview behavior.\r\n\r\n## Community Contributions\r\n\r\n1. Changes to files and folders made externally are now automatically synced in\r\n the Browser version of Phoenix Code.\r\n ([view change](https://github.com/phcode-dev/phoenix/pull/1566)) - By\r\n [Andrew Young](https://github.com/ayoung5555),\r\n [Faizan Bhagat](https://github.com/faizanbhagat)\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", + "pub_date": "2024-04-29T12:11:31.618Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm4za1hibVV1cllUMFlEWkJBcndlMi9aVmFwNFdPY3RCMGlSdlU1akdzNHV6cUEybnE0U3Y5cHpKS1BSdXpORFVnNDBud2RTNTlKdHc1RTZiQVc5RkFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNTI5NjI5CWZpbGU6UGhvZW5peCBDb2RlXzMuNS42X3g2NC1zZXR1cC5uc2lzLnppcApoclExc3lGRGEyNDN1YXRyN2RONFVDNWN2RmVjYjV4TFR3ZGRpdW9ENE1BeXVOY3R0Tnd3SERXb21oUG9QVHFwVmd3NGxZOU1CMzR0SmNRemRSU3NCZz09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_3.5.6_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnJrMUpFUlFJNUdmeVdhb2VSMFhqemdWRmpUN3l3VnRpSEFyZnYrS2pwenA3bXRzY1FlT0s2LzlRVlJEQ25NMFQxL3lSbE1SMzF5b29zd2xBRFNQS2d3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MzkxMTQ5CWZpbGU6UGhvZW5peCBDb2RlXzMuNi40X3g2NC1zZXR1cC5uc2lzLnppcApaNkpmc1AyYWkvQWZCZXZRVFhqN2oyV1ZXV0l5bk9NTktoU1AxMERiTk8xdnk1U0owZEVBQ09vUUFHTW5HV0NzM1VGM3VmN1o1R3NGVXNEQmgvUjhDQT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_3.6.4_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRmcWZITmkzNTRwOWZORmlFRUtZWTZsN1FlTGJoblBVejhxUERxMTZDQXpUVU5pWUMrNytkWHl0aDZGMVdGVXZVRk1UK2xzaUNvNnBtVFkvNDZqcXdzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNTMwMDYwCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKUjJVZVM0WHV0WmhySzlRdlg2b09DdUxKSW5UUm1OUjA4bkdDK3V3bngzUnlUYVhPdDFvT2tjQmFLQzU1bnBnclRRTG5nNDdQTml3SzYzQ2FuaWFDQkE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlIV25FQklhTVB1eTFzOXkrZXR0Q1FTbEp3MmNZRFdoMkk4SFZUaUthNjljbjlXZHNGK3ByZHRTRHE3ZVQ4aWM4dFhQRVdNdFdUVnBtVVRrcHlRRVFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MzkxODczCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKWDVlRFcvSGRDZ0psSy96QThjSmk1Tzl1RDB6T2NxbkliZHJONHIycWFwamxCNHJPUWI1SG5LWTRKa0pJandDYTZ5UGpLbG45TE1mazdtV1ltK2Q0QlE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1JcFdPTDFzdHRkbjhYU25maU1yTE4zbVlCOEZTUG5kcmFSVi9naWZqc2o4WEZvalJBUGpJelYrTHFnRExuT2ZsV1M3Z2xaaHJUb0p3N1pralk1dWdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzExNTMwNzUzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKQjVtTStrYjhHR0V3ZnFvaWN3cldDUnEyd3k0ZkExRjNucXFxNGNNdWtHUHgrU0dtY2wvMHNZTVZCOGxsVGE4UjBkSEE5UE9FL0N3VXRycXlTZ0RwQnc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.5.6/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9PUWpBRlcrWFVZWnBRUzhIK3FrMVRhckdLdWpHUkRKUXZJdkVWOXM1V2cwZzVEV1laekQ2K0ZUY2RwUnEyZUxTVWREU3ZFcDZnNk5XaldaMDdJMkE0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MzkyNjg2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKa0xtU1JRVVYwc2tiNUMxME85WlpkR3JCUndxY1R5anFZY2p0Q2I2VXVFYmlEN25XcHVaN2tka0F5TmtoK2Q0NDVxRjdzVHpYUWRFYUNuSjdkQjh2RFE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From f6a1fc7ba41c1333e15f579185f4cb3c43239e5c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 12:22:28 +0000 Subject: [PATCH 460/864] chore(deps): update tauri monorepo --- package-lock.json | 189 +++++++++++++++++++------------------------ package.json | 2 +- src-tauri/Cargo.lock | 8 +- src-tauri/Cargo.toml | 2 +- 4 files changed, 89 insertions(+), 112 deletions(-) diff --git a/package-lock.json b/package-lock.json index 57e123af..1c842b08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "phoenix-code-ide", - "version": "3.4.8", + "version": "3.5.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.4.8", + "version": "3.5.6", "hasInstallScript": true, "devDependencies": { - "@tauri-apps/cli": "1.5.11", + "@tauri-apps/cli": "1.5.12", "adm-zip": "0.5.12", "axios": "1.6.8", "axios-retry": "4.1.0", @@ -22,9 +22,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.11.tgz", - "integrity": "sha512-B475D7phZrq5sZ3kDABH4g2mEoUIHtnIO+r4ZGAAfsjMbZCwXxR/jlMGTEL+VO3YzjpF7gQe38IzB4vLBbVppw==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.12.tgz", + "integrity": "sha512-tMvcMVIrvNjoPIVO5pZk7lJrHVXw7NBggpJXRAQsD7VkMW9hT1uX3jVZeoPCmQ5KbpXvjoNXe+Ws8nE2NR/8Ow==", "dev": true, "bin": { "tauri": "tauri.js" @@ -37,22 +37,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.5.11", - "@tauri-apps/cli-darwin-x64": "1.5.11", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.11", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.11", - "@tauri-apps/cli-linux-arm64-musl": "1.5.11", - "@tauri-apps/cli-linux-x64-gnu": "1.5.11", - "@tauri-apps/cli-linux-x64-musl": "1.5.11", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.11", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.11", - "@tauri-apps/cli-win32-x64-msvc": "1.5.11" + "@tauri-apps/cli-darwin-arm64": "1.5.12", + "@tauri-apps/cli-darwin-x64": "1.5.12", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.12", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.12", + "@tauri-apps/cli-linux-arm64-musl": "1.5.12", + "@tauri-apps/cli-linux-x64-gnu": "1.5.12", + "@tauri-apps/cli-linux-x64-musl": "1.5.12", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.12", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.12", + "@tauri-apps/cli-win32-x64-msvc": "1.5.12" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.11.tgz", - "integrity": "sha512-2NLSglDb5VfvTbMtmOKWyD+oaL/e8Z/ZZGovHtUFyUSFRabdXc6cZOlcD1BhFvYkHqm+TqGaz5qtPR5UbqDs8A==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.12.tgz", + "integrity": "sha512-ud06E547WE7oDZeN5rH4eeB90Rie0aSCFH0Zb6XyNb6qgg0ZIftM+N3OjVONxk84/g//nr4/x7wW6LOwiwvPHw==", "cpu": [ "arm64" ], @@ -65,26 +65,10 @@ "node": ">= 10" } }, - "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.11.tgz", - "integrity": "sha512-/RQllHiJRH2fJOCudtZlaUIjofkHzP3zZgxi71ZUm7Fy80smU5TDfwpwOvB0wSVh0g/ciDjMArCSTo0MRvL+ag==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.11.tgz", - "integrity": "sha512-IlBuBPKmMm+a5LLUEK6a21UGr9ZYd6zKuKLq6IGM4tVweQa8Sf2kP2Nqs74dMGIUrLmMs0vuqdURpykQg+z4NQ==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.12.tgz", + "integrity": "sha512-FanE15/c7nz64CcTFe7f+8b7+rFQCb3Ivju+4sxVSPkAOJXHc5no3Y/LxFt85SAOMgPTB2FMuxHUdjvLjd2D1w==", "cpu": [ "arm" ], @@ -98,9 +82,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.11.tgz", - "integrity": "sha512-w+k1bNHCU/GbmXshtAhyTwqosThUDmCEFLU4Zkin1vl2fuAtQry2RN7thfcJFepblUGL/J7yh3Q/0+BCjtspKQ==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.12.tgz", + "integrity": "sha512-ETVyIcR4xVGnuhTgTY+kPG5LbAJQobPA8OxSLRY203f0cqYuSPffgyahtS65uPJ9egWIN3fflDKGTE1xcgFNAA==", "cpu": [ "arm64" ], @@ -114,9 +98,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.11.tgz", - "integrity": "sha512-PN6/dl+OfYQ/qrAy4HRAfksJ2AyWQYn2IA/2Wwpaa7SDRz2+hzwTQkvajuvy0sQ5L2WCG7ymFYRYMbpC6Hk9Pg==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.12.tgz", + "integrity": "sha512-ZhMagbS50dDV9glHrtRg1bkUa7sUDPsZ9bJ0xnd0vr8Smi8RiJ/dgQbF5eQNp4ahzYl+FtLjBkMTZKACrKgusg==", "cpu": [ "arm64" ], @@ -130,9 +114,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.11.tgz", - "integrity": "sha512-MTVXLi89Nj7Apcvjezw92m7ZqIDKT5SFKZtVPCg6RoLUBTzko/BQoXYIRWmdoz2pgkHDUHgO2OMJ8oKzzddXbw==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.12.tgz", + "integrity": "sha512-H6jXU4AG8g6FZxX+U3M76zigbLvj7bE+wG+xOrS7xCRwkfAEKw0aulymdFfOl44KBZDQQsV5KYA6T6csx3KbIQ==", "cpu": [ "x64" ], @@ -146,9 +130,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.11.tgz", - "integrity": "sha512-kwzAjqFpz7rvTs7WGZLy/a5nS5t15QKr3E9FG95MNF0exTl3d29YoAUAe1Mn0mOSrTJ9Z+vYYAcI/QdcsGBP+w==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.12.tgz", + "integrity": "sha512-Y/0dzBD8oFZ04Xq75LKPJvOI2MbVFdwGY6w41l24OxNiNopF7AzdrZGTJ+MoUbU9PALNP8ABhOP6BYZiV528OA==", "cpu": [ "x64" ], @@ -162,9 +146,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.11.tgz", - "integrity": "sha512-L+5NZ/rHrSUrMxjj6YpFYCXp6wHnq8c8SfDTBOX8dO8x+5283/vftb4vvuGIsLS4UwUFXFnLt3XQr44n84E67Q==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.12.tgz", + "integrity": "sha512-fxCS1/zQp+W7Lze+6Sh64RLqWFE57NsU+Y9L30ZKt5Prnt2LXEoa3POSaQpgHLRgwL/WfDW2nkYBRH3fVIrpQg==", "cpu": [ "arm64" ], @@ -178,9 +162,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.11.tgz", - "integrity": "sha512-oVlD9IVewrY0lZzTdb71kNXkjdgMqFq+ohb67YsJb4Rf7o8A9DTlFds1XLCe3joqLMm4M+gvBKD7YnGIdxQ9vA==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.12.tgz", + "integrity": "sha512-keWSEBOxL8q750AzmL4L3DDJzDzmb6DGT3+0HTjbEfu+a2GRS1lnrkm3EEeAepPoz4r62+cOQbjPRP8YGtGfFw==", "cpu": [ "ia32" ], @@ -194,9 +178,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.11.tgz", - "integrity": "sha512-1CexcqUFCis5ypUIMOKllxUBrna09McbftWENgvVXMfA+SP+yPDPAVb8fIvUcdTIwR/yHJwcIucmTB4anww4vg==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.12.tgz", + "integrity": "sha512-+eIvaPVwtVM7puXlCZIS1lSFF0VZ0gAUShKwk/kBZi8xUYQoNEW2RUWSPp+TEdZsMiAxd/zFZ+tGgv83Hxjbjg==", "cpu": [ "x64" ], @@ -1399,90 +1383,83 @@ }, "dependencies": { "@tauri-apps/cli": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.11.tgz", - "integrity": "sha512-B475D7phZrq5sZ3kDABH4g2mEoUIHtnIO+r4ZGAAfsjMbZCwXxR/jlMGTEL+VO3YzjpF7gQe38IzB4vLBbVppw==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.12.tgz", + "integrity": "sha512-tMvcMVIrvNjoPIVO5pZk7lJrHVXw7NBggpJXRAQsD7VkMW9hT1uX3jVZeoPCmQ5KbpXvjoNXe+Ws8nE2NR/8Ow==", "dev": true, "requires": { - "@tauri-apps/cli-darwin-arm64": "1.5.11", - "@tauri-apps/cli-darwin-x64": "1.5.11", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.11", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.11", - "@tauri-apps/cli-linux-arm64-musl": "1.5.11", - "@tauri-apps/cli-linux-x64-gnu": "1.5.11", - "@tauri-apps/cli-linux-x64-musl": "1.5.11", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.11", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.11", - "@tauri-apps/cli-win32-x64-msvc": "1.5.11" + "@tauri-apps/cli-darwin-arm64": "1.5.12", + "@tauri-apps/cli-darwin-x64": "1.5.12", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.12", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.12", + "@tauri-apps/cli-linux-arm64-musl": "1.5.12", + "@tauri-apps/cli-linux-x64-gnu": "1.5.12", + "@tauri-apps/cli-linux-x64-musl": "1.5.12", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.12", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.12", + "@tauri-apps/cli-win32-x64-msvc": "1.5.12" } }, "@tauri-apps/cli-darwin-arm64": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.11.tgz", - "integrity": "sha512-2NLSglDb5VfvTbMtmOKWyD+oaL/e8Z/ZZGovHtUFyUSFRabdXc6cZOlcD1BhFvYkHqm+TqGaz5qtPR5UbqDs8A==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-darwin-x64": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.11.tgz", - "integrity": "sha512-/RQllHiJRH2fJOCudtZlaUIjofkHzP3zZgxi71ZUm7Fy80smU5TDfwpwOvB0wSVh0g/ciDjMArCSTo0MRvL+ag==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.12.tgz", + "integrity": "sha512-ud06E547WE7oDZeN5rH4eeB90Rie0aSCFH0Zb6XyNb6qgg0ZIftM+N3OjVONxk84/g//nr4/x7wW6LOwiwvPHw==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.11.tgz", - "integrity": "sha512-IlBuBPKmMm+a5LLUEK6a21UGr9ZYd6zKuKLq6IGM4tVweQa8Sf2kP2Nqs74dMGIUrLmMs0vuqdURpykQg+z4NQ==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.12.tgz", + "integrity": "sha512-FanE15/c7nz64CcTFe7f+8b7+rFQCb3Ivju+4sxVSPkAOJXHc5no3Y/LxFt85SAOMgPTB2FMuxHUdjvLjd2D1w==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.11.tgz", - "integrity": "sha512-w+k1bNHCU/GbmXshtAhyTwqosThUDmCEFLU4Zkin1vl2fuAtQry2RN7thfcJFepblUGL/J7yh3Q/0+BCjtspKQ==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.12.tgz", + "integrity": "sha512-ETVyIcR4xVGnuhTgTY+kPG5LbAJQobPA8OxSLRY203f0cqYuSPffgyahtS65uPJ9egWIN3fflDKGTE1xcgFNAA==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.11.tgz", - "integrity": "sha512-PN6/dl+OfYQ/qrAy4HRAfksJ2AyWQYn2IA/2Wwpaa7SDRz2+hzwTQkvajuvy0sQ5L2WCG7ymFYRYMbpC6Hk9Pg==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.12.tgz", + "integrity": "sha512-ZhMagbS50dDV9glHrtRg1bkUa7sUDPsZ9bJ0xnd0vr8Smi8RiJ/dgQbF5eQNp4ahzYl+FtLjBkMTZKACrKgusg==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.11.tgz", - "integrity": "sha512-MTVXLi89Nj7Apcvjezw92m7ZqIDKT5SFKZtVPCg6RoLUBTzko/BQoXYIRWmdoz2pgkHDUHgO2OMJ8oKzzddXbw==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.12.tgz", + "integrity": "sha512-H6jXU4AG8g6FZxX+U3M76zigbLvj7bE+wG+xOrS7xCRwkfAEKw0aulymdFfOl44KBZDQQsV5KYA6T6csx3KbIQ==", "dev": true, "optional": true }, "@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.11.tgz", - "integrity": "sha512-kwzAjqFpz7rvTs7WGZLy/a5nS5t15QKr3E9FG95MNF0exTl3d29YoAUAe1Mn0mOSrTJ9Z+vYYAcI/QdcsGBP+w==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.12.tgz", + "integrity": "sha512-Y/0dzBD8oFZ04Xq75LKPJvOI2MbVFdwGY6w41l24OxNiNopF7AzdrZGTJ+MoUbU9PALNP8ABhOP6BYZiV528OA==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.11.tgz", - "integrity": "sha512-L+5NZ/rHrSUrMxjj6YpFYCXp6wHnq8c8SfDTBOX8dO8x+5283/vftb4vvuGIsLS4UwUFXFnLt3XQr44n84E67Q==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.12.tgz", + "integrity": "sha512-fxCS1/zQp+W7Lze+6Sh64RLqWFE57NsU+Y9L30ZKt5Prnt2LXEoa3POSaQpgHLRgwL/WfDW2nkYBRH3fVIrpQg==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.11.tgz", - "integrity": "sha512-oVlD9IVewrY0lZzTdb71kNXkjdgMqFq+ohb67YsJb4Rf7o8A9DTlFds1XLCe3joqLMm4M+gvBKD7YnGIdxQ9vA==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.12.tgz", + "integrity": "sha512-keWSEBOxL8q750AzmL4L3DDJzDzmb6DGT3+0HTjbEfu+a2GRS1lnrkm3EEeAepPoz4r62+cOQbjPRP8YGtGfFw==", "dev": true, "optional": true }, "@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.11.tgz", - "integrity": "sha512-1CexcqUFCis5ypUIMOKllxUBrna09McbftWENgvVXMfA+SP+yPDPAVb8fIvUcdTIwR/yHJwcIucmTB4anww4vg==", + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.12.tgz", + "integrity": "sha512-+eIvaPVwtVM7puXlCZIS1lSFF0VZ0gAUShKwk/kBZi8xUYQoNEW2RUWSPp+TEdZsMiAxd/zFZ+tGgv83Hxjbjg==", "dev": true, "optional": true }, diff --git a/package.json b/package.json index 589feba9..542a3b67 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { - "@tauri-apps/cli": "1.5.11", + "@tauri-apps/cli": "1.5.12", "adm-zip": "0.5.12", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 5500d87d..9130a7fb 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1831,7 +1831,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -3898,9 +3898,9 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f078117725e36d55d29fafcbb4b1e909073807ca328ae8deb8c0b3843aac0fed" +checksum = "047aefcc7721bfb8024a9bc39d4719112262610502de7a224fa62c4570cd78d4" dependencies = [ "anyhow", "base64 0.21.7", @@ -3916,7 +3916,7 @@ dependencies = [ "glib", "glob", "gtk", - "heck 0.4.1", + "heck 0.5.0", "http", "ignore", "indexmap 1.9.3", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index eac44a3d..7a0724cb 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -20,7 +20,7 @@ percent-encoding = "2.3" regex = "1.10.4" clipboard-files = "0.1.1" serde = { version = "1.0", features = ["derive"] } -tauri = { version = "1.6.1", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } +tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From de9b3a4c8ea947d684c0369d973700b9f889068b Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 30 Apr 2024 13:32:15 +0530 Subject: [PATCH 461/864] fix: package-lock was inconsistant in mac platfrom x64 --- package-lock.json | 1045 +++------------------------------------------ 1 file changed, 61 insertions(+), 984 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1c842b08..8e54630a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.5.6", - "lockfileVersion": 2, + "version": "3.6.4", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.5.6", + "version": "3.6.4", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.12", @@ -65,6 +65,22 @@ "node": ">= 10" } }, + "node_modules/@tauri-apps/cli-darwin-x64": { + "version": "1.5.12", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.12.tgz", + "integrity": "sha512-hSz9cuHO4lYora0z2XRFEIblkStT3eJvh/iYmsFfjT3usGBt2fTPMJ4SnL1Uyu64Y59dqyRNBikuBuymAFESjA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { "version": "1.5.12", "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.12.tgz", @@ -272,12 +288,15 @@ "dev": true }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/brace-expansion": { @@ -324,16 +343,10 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -346,6 +359,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -598,6 +614,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.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, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -657,13 +682,16 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.4" } }, "node_modules/human-signals": { @@ -713,12 +741,12 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -946,9 +974,9 @@ } }, "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "dependencies": { "path-key": "^4.0.0" @@ -1123,9 +1151,9 @@ "dev": true }, "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { "is-core-module": "^2.13.0", @@ -1291,9 +1319,9 @@ } }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -1380,956 +1408,5 @@ "decamelize": "^1.2.0" } } - }, - "dependencies": { - "@tauri-apps/cli": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.12.tgz", - "integrity": "sha512-tMvcMVIrvNjoPIVO5pZk7lJrHVXw7NBggpJXRAQsD7VkMW9hT1uX3jVZeoPCmQ5KbpXvjoNXe+Ws8nE2NR/8Ow==", - "dev": true, - "requires": { - "@tauri-apps/cli-darwin-arm64": "1.5.12", - "@tauri-apps/cli-darwin-x64": "1.5.12", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.12", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.12", - "@tauri-apps/cli-linux-arm64-musl": "1.5.12", - "@tauri-apps/cli-linux-x64-gnu": "1.5.12", - "@tauri-apps/cli-linux-x64-musl": "1.5.12", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.12", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.12", - "@tauri-apps/cli-win32-x64-msvc": "1.5.12" - } - }, - "@tauri-apps/cli-darwin-arm64": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.12.tgz", - "integrity": "sha512-ud06E547WE7oDZeN5rH4eeB90Rie0aSCFH0Zb6XyNb6qgg0ZIftM+N3OjVONxk84/g//nr4/x7wW6LOwiwvPHw==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.12.tgz", - "integrity": "sha512-FanE15/c7nz64CcTFe7f+8b7+rFQCb3Ivju+4sxVSPkAOJXHc5no3Y/LxFt85SAOMgPTB2FMuxHUdjvLjd2D1w==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.12.tgz", - "integrity": "sha512-ETVyIcR4xVGnuhTgTY+kPG5LbAJQobPA8OxSLRY203f0cqYuSPffgyahtS65uPJ9egWIN3fflDKGTE1xcgFNAA==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.12.tgz", - "integrity": "sha512-ZhMagbS50dDV9glHrtRg1bkUa7sUDPsZ9bJ0xnd0vr8Smi8RiJ/dgQbF5eQNp4ahzYl+FtLjBkMTZKACrKgusg==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.12.tgz", - "integrity": "sha512-H6jXU4AG8g6FZxX+U3M76zigbLvj7bE+wG+xOrS7xCRwkfAEKw0aulymdFfOl44KBZDQQsV5KYA6T6csx3KbIQ==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.12.tgz", - "integrity": "sha512-Y/0dzBD8oFZ04Xq75LKPJvOI2MbVFdwGY6w41l24OxNiNopF7AzdrZGTJ+MoUbU9PALNP8ABhOP6BYZiV528OA==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.12.tgz", - "integrity": "sha512-fxCS1/zQp+W7Lze+6Sh64RLqWFE57NsU+Y9L30ZKt5Prnt2LXEoa3POSaQpgHLRgwL/WfDW2nkYBRH3fVIrpQg==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.12.tgz", - "integrity": "sha512-keWSEBOxL8q750AzmL4L3DDJzDzmb6DGT3+0HTjbEfu+a2GRS1lnrkm3EEeAepPoz4r62+cOQbjPRP8YGtGfFw==", - "dev": true, - "optional": true - }, - "@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.12.tgz", - "integrity": "sha512-+eIvaPVwtVM7puXlCZIS1lSFF0VZ0gAUShKwk/kBZi8xUYQoNEW2RUWSPp+TEdZsMiAxd/zFZ+tGgv83Hxjbjg==", - "dev": true, - "optional": true - }, - "adm-zip": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.12.tgz", - "integrity": "sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==", - "dev": true - }, - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", - "dev": true, - "requires": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "axios-retry": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.1.0.tgz", - "integrity": "sha512-svdth4H00yhlsjBbjfLQ/sMLkXqeLxhiFC1nE1JtkN/CIssGxqk0UwTEdrVjwA2gr3yJkAulwvDSIm4z4HyPvg==", - "dev": true, - "requires": { - "is-retry-allowed": "^2.2.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chokidar-cli": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chokidar-cli/-/chokidar-cli-3.0.0.tgz", - "integrity": "sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==", - "dev": true, - "requires": { - "chokidar": "^3.5.2", - "lodash.debounce": "^4.0.8", - "lodash.throttle": "^4.1.1", - "yargs": "^13.3.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "optional": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "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, - "requires": { - "is-glob": "^4.0.1" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "has": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", - "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", - "dev": true - }, - "human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, - "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, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "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 - }, - "is-retry-allowed": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", - "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", - "dev": true - }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true - }, - "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - }, - "dependencies": { - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - } - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "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 - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "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, - "requires": { - "resolve": "^1.1.6" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "shx": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", - "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==", - "dev": true, - "requires": { - "minimist": "^1.2.3", - "shelljs": "^0.8.5" - } - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - }, - "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 - }, - "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "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, - "requires": { - "is-number": "^7.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } } } From 5faaaedfe23b98d4f58f891f0f7b786c9befbc92 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 1 May 2024 18:39:34 +0530 Subject: [PATCH 462/864] feat: add get_process_id tauri api --- src-tauri/Cargo.lock | 2 +- src-tauri/src/main.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9130a7fb..28add8e7 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2849,7 +2849,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.5.6" +version = "3.6.4" dependencies = [ "clipboard-files", "fix-path-env", diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index e3c7fe3f..a0d59678 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -82,6 +82,10 @@ fn _get_window_labels(app: tauri::AppHandle) -> Vec { .collect() } +#[tauri::command] +fn get_process_id() -> u32 { + std::process::id() +} #[tauri::command] fn _get_clipboard_files() -> Option> { @@ -336,7 +340,7 @@ fn main() { })) .on_window_event(|event| process_window_event(&event)) .invoke_handler(tauri::generate_handler![ - get_mac_deep_link_requests, + get_mac_deep_link_requests, get_process_id, toggle_devtools, console_log, console_error, _get_commandline_args, get_current_working_dir, _get_window_labels, put_item, get_item, get_all_items, delete_item, From cd80e765dce05485736a30c74039101a732bc9d5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 20:25:40 +0000 Subject: [PATCH 463/864] fix(deps): update rust crate winapi to 0.3.9 --- src-tauri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 7a0724cb..2dba26e1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -21,7 +21,7 @@ regex = "1.10.4" clipboard-files = "0.1.1" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } -winapi = { version = "0.3", features = ["fileapi"] } +winapi = { version = "0.3.9", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From 4ed47f91b45bc6397f520789cbd0d9853f075c76 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 16:48:35 +0000 Subject: [PATCH 464/864] fix(deps): update rust crate serde_json to 1.0.116 --- src-tauri/Cargo.lock | 4 ++-- src-tauri/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 28add8e7..936acfc6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3436,9 +3436,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 2dba26e1..814bac87 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -14,7 +14,7 @@ rust-version = "1.70" tauri-build = { version = "1.5.1", features = [] } [dependencies] -serde_json = "1.0" +serde_json = "1.0.116" once_cell = "1.19.0" percent-encoding = "2.3" regex = "1.10.4" From 724f3d1482a71e1b1fa0583c1bba2f92d62b671a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 16:48:28 +0000 Subject: [PATCH 465/864] fix(deps): update rust crate serde to 1.0.200 --- src-tauri/Cargo.lock | 8 ++++---- src-tauri/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 936acfc6..220db7e8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3416,18 +3416,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 814bac87..a6d37cff 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,7 +19,7 @@ once_cell = "1.19.0" percent-encoding = "2.3" regex = "1.10.4" clipboard-files = "0.1.1" -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3.9", features = ["fileapi"] } tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } From bd7de3b7ee1831c50b7bc15673fe7f2fc47765f8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:11:55 +0000 Subject: [PATCH 466/864] fix(deps): update rust crate percent-encoding to 2.3.1 --- src-tauri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a6d37cff..c2f8c57e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,7 +16,7 @@ tauri-build = { version = "1.5.1", features = [] } [dependencies] serde_json = "1.0.116" once_cell = "1.19.0" -percent-encoding = "2.3" +percent-encoding = "2.3.1" regex = "1.10.4" clipboard-files = "0.1.1" serde = { version = "1.0.200", features = ["derive"] } From ad8603ecac6bb2750919301ebb622fd653bfccae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:11:50 +0000 Subject: [PATCH 467/864] fix(deps): update rust crate objc to 0.2.7 --- src-tauri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c2f8c57e..80731ae5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -32,7 +32,7 @@ gtk = "0.15" webkit2gtk = "0.18" # if tauri build fails, make sure to match this version to what we have in tauri [target.'cfg(target_os = "macos")'.dependencies] -objc = "0.2" +objc = "0.2.7" tauri-plugin-deep-link = "0.1.2" lazy_static = "1.4" From d53e16d0f6fd5b5dd5183754f84987bd7028401b Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 4 May 2024 17:51:32 +0000 Subject: [PATCH 468/864] ci: update phcode version to 3.7.2 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 542a3b67..ac0fc39c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.6.4", + "version": "3.7.2", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "ec66f0ad0e752304047acb3fdacdfba0ea1d5026" + "commit": "da689fd410f987e387f1e28f32690e5a9ae929f6" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 80731ae5..a3286699 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.6.4" +version = "3.7.2" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index b477b1d8..3871d13d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.6.4" + "version": "3.7.2" }, "tauri": { "allowlist": { From 6f7c90e39bef158c252fd0e559f4cab599ffbc31 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 5 May 2024 05:16:43 +0000 Subject: [PATCH 469/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index d908492f..c273028e 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,19 +1,19 @@ { - "version": "3.6.3", - "notes": "Pre-release test\r\nApril release(3.6) of Phoenix Code is now available.\r\n\r\nThis month's upgrade is big! with a lot of features you asked for - PHP/Custom\r\nlive preview servers, advanced CSS/LESS/SCSS/HTML code intelligence and tooling,\r\nUX and app stability improvements.\r\n\r\n## Custom Live Preview Servers\r\n\r\nPreview PHP, React, and other dynamically rendered files with the\r\nnew server settings dialog. Read more at\r\n[Live Preview Settings Docs](https://docs.phcode.dev/docs/Features/live-preview-settings/).\r\n\r\n![Screenshot from 2024-04-12 13-08-34](https://github.com/phcode-dev/phoenix/assets/5336369/69fa0ee4-7262-42af-97d2-26154ec4a3b9)\r\n\r\n#### HTML Code Intelligence\r\n\r\nCSS class hints are now shown within the HTML file's class attribute.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/112ad909-8fd0-4fc4-8042-041ecade9481)\r\n\r\n## Advanced CSS Tooling\r\n\r\nSupport for the latest CSS/LESS/SCSS syntax. Code intelligence and error\r\ndetection for CSS, SCSS, and LESS files.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/9c083bd3-9e34-418d-a1c8-c152393c37b2)\r\n\r\n## Reverse CSS Highlighting\r\n\r\nClicking an element in the live preview now highlights its selector in the\r\nsource CSS file editor.\r\n\r\n## Editor Rulers\r\n\r\nAdd multiple, color-customizable rulers in the editor to better visualize line\r\nlengths. [Read more...](https://docs.phcode.dev/docs/Features/editor-rulers/)\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/71b8b04c-d2ca-47b8-84bb-53cd0fb4593c)\r\n\r\n## Open Live Preview in any Browser\r\n\r\nDirect buttons to open live previews in Chrome, Edge, Safari, and Firefox.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/05f92c99-8a35-45a5-a8ee-75d581e6e96a)\r\n\r\n## Docusaurus Support\r\n\r\nLive preview [docusaurus.io](https://docusaurus.io/) based markdown documentation server.\r\n\r\n## UX Improvements\r\n\r\nIncreased stability and more predictable live preview behavior.\r\n\r\n## Community Contributions\r\n\r\n1. Changes to files and folders made externally are now automatically synced in\r\n the Browser version of Phoenix Code.\r\n ([view change](https://github.com/phcode-dev/phoenix/pull/1566)) - By\r\n [Andrew Young](https://github.com/ayoung5555),\r\n [Faizan Bhagat](https://github.com/faizanbhagat)\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", - "pub_date": "2024-04-27T18:54:57.783Z", + "version": "3.7.2", + "notes": "Adds support for node extensions", + "pub_date": "2024-05-05T04:05:08.711Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBObjdwNXFnVlRBVG16cmYwaDZjcDNrd3cyNG1zWlIvY2p1K2ttZ3ludCtiRFdHV24yclpwRWN1R2pXM3piSnp1TktRdy9oSGVaUlEvd0JPQ3VrWWdzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MjQxMjg2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjYuM194NjQtc2V0dXAubnNpcy56aXAKbC9EOHgraE54SlBKaWxDN3Jla1FNUGVQU3lFZCsxSEgvODhzbU5LQ1JxL1pQV2FqM1JMSko3MVh1K2lWS2VJUTJWcDFKSGcvZ2dSem0vODZLS3ZuQ2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.6.3/Phoenix.Code.Experimental.Build_3.6.3_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlGNnRic0dYQjg2a0I2K2o2TDQ4RjBpbWl2VU5Db3FYOU1HbW9TdzhwQy9EYis3dGM1T3lPZnB1dVVMOExPRU9WMjRYMW1NRHJ6enN0N0J2NSt5NEFzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0ODQ2MjA2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjcuMl94NjQtc2V0dXAubnNpcy56aXAKdCtmQ0RSVWQvVUhWZGczM0o4QjFUbHJIMk9ocUZxZWltYVpBaW8yWTJPd0JqTVNCSWhsbnVXZXEvVFRHd2hEcE9oRzdTeFZtcklaVzNTemlBZTMyQ0E9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.7.2/Phoenix.Code.Experimental.Build_3.7.2_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9IaVNXc3VGaGJzMUd1em5wUjg1dVdWcGh5MnZUdmY2dXdETzFyU2tsTWhZcVRZZlNlcWR5WDJ0MUNpY1o2c05zQnR3VWhoZC9oazhGa09TakE3WkFNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MjQzMzM0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CjVmR3ZTeDJFTDl1Tll0b3o3QUQyOVF4aTFLYUtWSi9WR2JwLzVjQ3BqWGtPRlVLVENTUG4venhUV3VkZFlJSkxDLzJPcUFWS0dJN1ZYYSsvM25sR0R3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.6.3/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnM5OFRnbGZ5djhQS00veFl3SnlObXdzeEljOWFiOUxRSjNZUkQ2QktLTDBsY3FYbmhyM21yVndoZTc2d1BoVVJaMzNNUnd1cFMxV2U2Q09ueWpVWmdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0ODgxMjMwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnRWSzBNNjJHWDJrNnd2bGRMMVNHKzBPcVFId0cwdEd3eHpnRVFCLzhWR3lzS1JSeDFYSUFzQ3BxM0FVZXd6Y2x6SVdTa21YcG02NU9DVEZKalQ4c0JBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.7.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnBDdFIvOXlXQkJNZ2h3L0pEOHEwRU01cEQydWdDZ29IenVjQVhYSUFzb1ZmZGlaWlcvRmtoQitNRWErVkRzcEdxY2tBNEtEbTNYK2ZjQjVVbVVEMndnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MjQ0MDkzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CkVmbXJsVnNiekIrTElVelFtc3Vmdys4bXFLUzJOOW0xODY2SC9IMnYvbmRsTGdDNHZrMjNSVEUzbVhRaG51RDBlcnk5VTcxeDNMZEtVbGNTRFpqUUFBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.6.3/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtKSHJDRVpSSDJNNUV3UGkzTU0wZ1FVUGU5N1Exc3k4Q0M1N3pSc3o0a3NYTVpTYWVxUkZkMUdhcW1HbmN6SXRlNklPUC9WUWN6NG0weFhTZjN5dkFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0ODgxOTAwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmR5RlZDYUY4S1RRajJvYmQ3UnRrRkxoUWJtQ29RZk44TkVBNzZLcER5QVRUeE9IZTVJTGZUc2lKQnNVWDIzRENJSlBjTWRkbEROdU9rVk1ya09nVEJRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.7.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 7dc93150d756e75087d63d71d5422e5d49d9da7c Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 6 May 2024 20:14:08 +0530 Subject: [PATCH 470/864] fix: installation was aborting in fedora --- docs/linux/installer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 89202189..45688890 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -205,7 +205,7 @@ install_dependencies() { ;; fedora|rhel|centos) echo "Detected a Fedora/Red Hat based distribution." - sudo dnf install webkit2gtk3 gtk3 \ + yes | sudo dnf install webkit2gtk3 gtk3 \ gstreamer1-plugins-base gstreamer1-plugins-good ;; arch|manjaro) From d2e37c240e3c41d11c170497084cec94cb8349f6 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 8 May 2024 22:56:42 +0530 Subject: [PATCH 471/864] chore: notification for not supported in Ubuntu 24.04 --- docs/linux/installer.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 45688890..ae3e0685 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -459,6 +459,16 @@ downloadLatestReleaseInfo() { # version and decide whether an upgrade is necessary. # downloadAndInstall(){ + # Check Ubuntu version for compatibility + if [ -f /etc/os-release ]; then + . /etc/os-release + if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then + echo -e "${RED}Ubuntu 24.04 LTS is not currently supported by this installation script.${RESET}" + echo -e "${YELLOW}Please use an earlier version of Ubuntu for the time being. Check back later for updates.${RESET}" + exit 1 + fi + fi + echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') From f874bad00a88dd4062e284f252eee63083bf7f51 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 9 May 2024 21:44:03 +0530 Subject: [PATCH 472/864] chore: inital code for Ubuntu 24.04 --- docs/linux/installer.sh | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index ae3e0685..28e6dc10 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -460,17 +460,25 @@ downloadLatestReleaseInfo() { # downloadAndInstall(){ # Check Ubuntu version for compatibility - if [ -f /etc/os-release ]; then - . /etc/os-release - if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then - echo -e "${RED}Ubuntu 24.04 LTS is not currently supported by this installation script.${RESET}" - echo -e "${YELLOW}Please use an earlier version of Ubuntu for the time being. Check back later for updates.${RESET}" - exit 1 - fi - fi + echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null + if [ -f /etc/os-release ]; then + . /etc/os-release + if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then + local latestFileUrl + latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") + WGET_OPTS=$(configure_wget_options) + + wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { + echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" + } + echo -e "${RED}Ubuntu 24.04 LTS is not currently supported by this installation script.${RESET}" + echo -e "${YELLOW}Please use an earlier version of Ubuntu for the time being. Check back later for updates.${RESET}" + exit 1 + fi + fi CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" From ca1befd6e1610e555817544e8ba4a250a8c036ea Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 9 May 2024 21:48:43 +0530 Subject: [PATCH 473/864] chore: code indendation --- docs/linux/installer.sh | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 28e6dc10..dcbba1cd 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -459,26 +459,25 @@ downloadLatestReleaseInfo() { # version and decide whether an upgrade is necessary. # downloadAndInstall(){ - # Check Ubuntu version for compatibility - echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null - if [ -f /etc/os-release ]; then - . /etc/os-release - if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then - local latestFileUrl - latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") - WGET_OPTS=$(configure_wget_options) - - wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { - echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" - } - echo -e "${RED}Ubuntu 24.04 LTS is not currently supported by this installation script.${RESET}" - echo -e "${YELLOW}Please use an earlier version of Ubuntu for the time being. Check back later for updates.${RESET}" - exit 1 - fi + # Check Ubuntu version for compatibility + if [ -f /etc/os-release ]; then + . /etc/os-release + if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then + local latestFileUrl + latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") + WGET_OPTS=$(configure_wget_options) + + wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { + echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" + } + echo -e "${RED}Ubuntu 24.04 LTS is not currently supported by this installation script.${RESET}" + echo -e "${YELLOW}Please use an earlier version of Ubuntu for the time being. Check back later for updates.${RESET}" + exit 1 fi + fi CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" From 2fc79abefcc4e2e16f689a30d78a4a96414b34e7 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 13 May 2024 16:03:55 +0530 Subject: [PATCH 474/864] chore: update new user survey --- docs/surveys.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/surveys.json b/docs/surveys.json index 5cbeb0bb..28d2977d 100644 --- a/docs/surveys.json +++ b/docs/surveys.json @@ -1,4 +1,4 @@ { - "newUser": "https://s.surveyplanet.com/g837j5k9", + "newUser": "https://s.surveyplanet.com/jssqbld8", "powerUser": "https://s.surveyplanet.com/v3j59a7z" } \ No newline at end of file From 0fac5045fb437458e8a988455f7e32aa6105a72a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 01:28:07 +0000 Subject: [PATCH 475/864] fix(deps): update rust crate serde_json to v1.0.117 --- src-tauri/Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 220db7e8..46df2e83 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2849,7 +2849,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.6.4" +version = "3.7.2" dependencies = [ "clipboard-files", "fix-path-env", @@ -3436,9 +3436,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", From d6ab99d0ccdc3995d0de68f40a400733ac503538 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 16 May 2024 22:46:19 +0530 Subject: [PATCH 476/864] feat: add move_to_trash api --- package-lock.json | 4 ++-- src-tauri/Cargo.lock | 26 ++++++++++++++++++++++++++ src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 9 ++++++++- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8e54630a..fc50c4d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.6.4", + "version": "3.7.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.6.4", + "version": "3.7.2", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.12", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 46df2e83..fe1a4403 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2867,6 +2867,7 @@ dependencies = [ "tauri-plugin-fs-extra", "tauri-plugin-single-instance", "tauri-plugin-window-state", + "trash", "webkit2gtk", "winapi", ] @@ -4478,6 +4479,22 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "trash" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c658458d46d9d5a153a3b5cdd88d8579ad50d4fb85d53961e4526c8fc7c55a57" +dependencies = [ + "chrono", + "libc", + "log", + "objc", + "once_cell", + "scopeguard", + "url", + "windows 0.44.0", +] + [[package]] name = "tree_magic_mini" version = "3.1.4" @@ -5008,6 +5025,15 @@ dependencies = [ "windows_x86_64_msvc 0.39.0", ] +[[package]] +name = "windows" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" +dependencies = [ + "windows-targets 0.42.2", +] + [[package]] name = "windows" version = "0.48.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a3286699..ece95700 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,6 +19,7 @@ once_cell = "1.19.0" percent-encoding = "2.3.1" regex = "1.10.4" clipboard-files = "0.1.1" +trash = "3" serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3.9", features = ["fileapi"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index a0d59678..cae22925 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -33,6 +33,7 @@ use tauri::GlobalWindowEvent; mod init; mod utilities; mod boot_config; +use trash; mod platform; use tauri_plugin_window_state::StateFlags; @@ -74,6 +75,12 @@ fn _rename_path(old_path: &str, new_path: &str) -> Result<(), String> { platform::rename_path(old_path, new_path) } +#[tauri::command] +fn move_to_trash(delete_path: &str) -> Result<(), String> { + trash::delete(delete_path) + .map_err(|e| e.to_string()) +} + #[tauri::command] fn _get_window_labels(app: tauri::AppHandle) -> Vec { app.windows() @@ -344,7 +351,7 @@ fn main() { toggle_devtools, console_log, console_error, _get_commandline_args, get_current_working_dir, _get_window_labels, put_item, get_item, get_all_items, delete_item, - _get_windows_drives, _rename_path, show_in_folder, zoom_window, _get_clipboard_files]) + _get_windows_drives, _rename_path, show_in_folder, move_to_trash, zoom_window, _get_clipboard_files]) .setup(|app| { init::init_app(app); #[cfg(target_os = "linux")] From 4beaeafca69558e8a898db0b2c2d3f8dc4cee094 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 05:54:33 +0000 Subject: [PATCH 477/864] fix(deps): update rust crate trash to v4 --- src-tauri/Cargo.lock | 139 +++++++++++++++++++++++++++++-------------- src-tauri/Cargo.toml | 2 +- 2 files changed, 96 insertions(+), 45 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fe1a4403..a97d590c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -535,7 +535,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -2114,7 +2114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.4", + "windows-targets 0.48.5", ] [[package]] @@ -3865,7 +3865,7 @@ dependencies = [ "unicode-segmentation", "uuid", "windows 0.39.0", - "windows-implement", + "windows-implement 0.39.0", "x11-dl", ] @@ -4481,9 +4481,9 @@ dependencies = [ [[package]] name = "trash" -version = "3.3.1" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c658458d46d9d5a153a3b5cdd88d8579ad50d4fb85d53961e4526c8fc7c55a57" +checksum = "c254b119cf49bdde3dfef21b1dc492dc8026b75566ca24aa77993eccd7cbc1b5" dependencies = [ "chrono", "libc", @@ -4492,7 +4492,7 @@ dependencies = [ "once_cell", "scopeguard", "url", - "windows 0.44.0", + "windows 0.56.0", ] [[package]] @@ -4932,7 +4932,7 @@ dependencies = [ "webview2-com-macros", "webview2-com-sys", "windows 0.39.0", - "windows-implement", + "windows-implement 0.39.0", ] [[package]] @@ -5017,7 +5017,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" dependencies = [ - "windows-implement", + "windows-implement 0.39.0", "windows_aarch64_msvc 0.39.0", "windows_i686_gnu 0.39.0", "windows_i686_msvc 0.39.0", @@ -5025,15 +5025,6 @@ dependencies = [ "windows_x86_64_msvc 0.39.0", ] -[[package]] -name = "windows" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows" version = "0.48.0" @@ -5053,6 +5044,16 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" +dependencies = [ + "windows-core 0.56.0", + "windows-targets 0.52.5", +] + [[package]] name = "windows-bindgen" version = "0.39.0" @@ -5078,7 +5079,19 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-core" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" +dependencies = [ + "windows-implement 0.56.0", + "windows-interface", + "windows-result", + "windows-targets 0.52.5", ] [[package]] @@ -5091,12 +5104,43 @@ dependencies = [ "windows-tokens", ] +[[package]] +name = "windows-implement" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "windows-interface" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "windows-metadata" version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" +[[package]] +name = "windows-result" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-sys" version = "0.42.0" @@ -5136,7 +5180,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -5171,17 +5215,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -5196,7 +5241,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75aa004c988e080ad34aff5739c39d0312f4684699d6d71fc8a198d057b8b9b4" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -5213,9 +5258,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -5243,9 +5288,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -5273,9 +5318,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -5303,9 +5354,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -5333,9 +5384,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -5351,9 +5402,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -5381,9 +5432,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -5478,7 +5529,7 @@ dependencies = [ "webkit2gtk-sys", "webview2-com", "windows 0.39.0", - "windows-implement", + "windows-implement 0.39.0", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ece95700..43f637c2 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,7 +19,7 @@ once_cell = "1.19.0" percent-encoding = "2.3.1" regex = "1.10.4" clipboard-files = "0.1.1" -trash = "3" +trash = "4" serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3.9", features = ["fileapi"] } From 0cfef9dffb3e8a091a8a0bd383b6f13c83723445 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 17 May 2024 12:01:50 +0530 Subject: [PATCH 478/864] ci: use another github token const as mac builds fail frequently --- .github/workflows/desktop-linux-test-pull.yml | 6 +++--- .github/workflows/desktop-mac-m1-test-pull.yml | 4 ++-- .github/workflows/desktop-mac-test-pull.yml | 6 +++--- .github/workflows/desktop-windows-test-pull.yml | 6 +++--- .github/workflows/prod-desktop-tests-on-pull.yml | 16 ++++++++-------- .../workflows/staging-desktop-tests-on-pull.yml | 14 +++++++------- .github/workflows/tauri-build-dev.yml | 14 +++++++------- .github/workflows/tauri-build-prod.yml | 14 +++++++------- .github/workflows/tauri-build-staging.yml | 12 ++++++------ .github/workflows/update-phcode-build.yml | 2 +- 10 files changed, 47 insertions(+), 47 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index 84676cbe..1263a37e 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -29,12 +29,12 @@ jobs: - name: npm install ci deps env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -45,7 +45,7 @@ jobs: - name: build test runner env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/desktop-mac-m1-test-pull.yml b/.github/workflows/desktop-mac-m1-test-pull.yml index f5be6ee8..71bdd08c 100644 --- a/.github/workflows/desktop-mac-m1-test-pull.yml +++ b/.github/workflows/desktop-mac-m1-test-pull.yml @@ -27,7 +27,7 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -38,7 +38,7 @@ jobs: - name: build test runner env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 2edca26c..72a1d9d3 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -22,12 +22,12 @@ jobs: - name: npm install ci deps env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -38,7 +38,7 @@ jobs: - name: build test runner env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index d24e9f96..df048e88 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -22,12 +22,12 @@ jobs: - name: npm install ci deps env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -38,7 +38,7 @@ jobs: - name: build test runner env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index 5f76a8e8..3a6ea408 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -27,12 +27,12 @@ jobs: - name: npm install ci deps env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -95,12 +95,12 @@ jobs: - name: npm install ci deps env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -111,7 +111,7 @@ jobs: - name: build test runner env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run releaseDistTestDebug @@ -165,12 +165,12 @@ jobs: - name: npm install ci deps env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -181,7 +181,7 @@ jobs: - name: build test runner env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index fabd229f..83186ef6 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -27,12 +27,12 @@ jobs: - name: npm install ci deps env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -43,7 +43,7 @@ jobs: - name: build test runner env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run releaseDistTestDebug @@ -90,12 +90,12 @@ jobs: - name: npm install ci deps env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -151,7 +151,7 @@ jobs: - name: npm install ci deps env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test @@ -165,7 +165,7 @@ jobs: - name: build test runner env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index fc0f823c..1e90df44 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -54,7 +54,7 @@ jobs: node-version: 20 - name: install frontend dependencies env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run _ci-cloneAndBuildPhoenix @@ -102,7 +102,7 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: install frontend dependencies env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run _ci-release:dev @@ -213,7 +213,7 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} @@ -238,7 +238,7 @@ jobs: - name: setup env for mac arm (Mac only) env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} if: matrix.platform == 'macos-12' run: | rustup target add aarch64-apple-darwin @@ -247,7 +247,7 @@ jobs: if: matrix.platform == 'macos-12' uses: tauri-apps/tauri-action@v0 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} @@ -297,7 +297,7 @@ jobs: sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run _ci-release:dev @@ -324,7 +324,7 @@ jobs: tag_name: ${{ env.GIT_TAG_NAME }} draft: true env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} publish-release: permissions: diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 2ffa9831..e6c8b923 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -54,7 +54,7 @@ jobs: node-version: 20 - name: install frontend dependencies env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run _ci-cloneAndBuildPhoenix @@ -102,7 +102,7 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: install frontend dependencies env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run _ci-release:prod @@ -214,7 +214,7 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} @@ -239,7 +239,7 @@ jobs: - name: setup env for mac arm (Mac only) env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} if: matrix.platform == 'macos-12' run: | rustup target add aarch64-apple-darwin @@ -248,7 +248,7 @@ jobs: if: matrix.platform == 'macos-12' uses: tauri-apps/tauri-action@v0 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} @@ -297,7 +297,7 @@ jobs: sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run _ci-release:prod @@ -326,7 +326,7 @@ jobs: tag_name: ${{ env.GIT_TAG_NAME }} draft: true env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} publish-release: permissions: diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index a74bd54a..6ec35a13 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -54,7 +54,7 @@ jobs: node-version: 20 - name: install frontend dependencies env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run _ci-cloneAndBuildPhoenix @@ -211,7 +211,7 @@ jobs: - uses: tauri-apps/tauri-action@v0 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} @@ -236,7 +236,7 @@ jobs: - name: setup env for mac arm (Mac only) env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} if: matrix.platform == 'macos-12' run: | rustup target add aarch64-apple-darwin @@ -245,7 +245,7 @@ jobs: if: matrix.platform == 'macos-12' uses: tauri-apps/tauri-action@v0 env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} @@ -294,7 +294,7 @@ jobs: sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run _ci-release:staging @@ -321,7 +321,7 @@ jobs: tag_name: ${{ env.GIT_TAG_NAME }} draft: true env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} publish-release: permissions: diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 5a266cca..3c947f3f 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -24,7 +24,7 @@ jobs: - name: Update phcode and version env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ github.token }} run: | npm ci npm run _ci-update-phcode-build ${{ github.event.client_payload.sha }} From 29be46eb635db5eb06492dcd6a232aa2780c4d59 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 17 May 2024 17:43:15 +0530 Subject: [PATCH 479/864] build: logging if github token is used to download node --- src-build/downloadNodeBinary.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index 1b89ecfb..c722c58c 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -66,9 +66,12 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { }; // Only add the Authorization header if GH_TOKEN is set if (GH_TOKEN) { + console.log("Using GH_TOKEN passed in from github actions."); config.headers = { 'Authorization': `Bearer ${GH_TOKEN}` }; + } else { + console.warn("GH_TOKEN not passed in from github actions, using unauthorized fetch."); } const { data } = await axios(config); From 0bad5f15ed0ed55075060d228e25bd0b7e7284f4 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 18 May 2024 17:19:17 +0530 Subject: [PATCH 480/864] fix: github token not passed in for fetch release details API --- src-build/downloadNodeBinary.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index c722c58c..42a20a30 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -40,8 +40,21 @@ axiosRetry(axios, { async function downloadNodeBinary(platform, arch, maxRetries = 3) { try { + console.log("fetching release details...."); + const url = 'https://api.github.com/repos/phcode-dev/phnode/releases/latest'; - const releaseResponse = await axios.get(url); + const GH_TOKEN = process.env.GH_TOKEN; // Access the environment variable + // Only add the Authorization header if GH_TOKEN is set + let headers = {}; + if (GH_TOKEN) { + console.log("Using GH_TOKEN passed in from github actions."); + headers = { + 'Authorization': `Bearer ${GH_TOKEN}` + }; + } else { + console.warn("GH_TOKEN not passed in from github actions, using unauthorized fetch for .", url); + } + const releaseResponse = await axios.get(url, { headers }); const extension = platform === 'win' ? 'zip' : 'tar.gz'; const regex = new RegExp(`node-v[\\d.]+-${platform}-${arch}\\.${extension}`); const asset = releaseResponse.data.assets.find(a => regex.test(a.name)); @@ -50,6 +63,8 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { throw new Error(`No asset found for platform: ${platform}, arch: ${arch}`); } + console.log("fetching asset ", asset); + const outputPath = path.resolve(__dirname, asset.name); if (fs.existsSync(outputPath)) { console.log(`File already downloaded: ${asset.name}`); @@ -57,7 +72,6 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { } const writer = fs.createWriteStream(outputPath); - const GH_TOKEN = process.env.GH_TOKEN; // Access the environment variable const config = { url: asset.browser_download_url, method: 'GET', @@ -71,7 +85,7 @@ async function downloadNodeBinary(platform, arch, maxRetries = 3) { 'Authorization': `Bearer ${GH_TOKEN}` }; } else { - console.warn("GH_TOKEN not passed in from github actions, using unauthorized fetch."); + console.warn("GH_TOKEN not passed in from github actions, using unauthorized fetch for", config.url); } const { data } = await axios(config); From d2177e11acf13bb73cbe63400837f6625f420eff Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 21 May 2024 21:28:00 +0530 Subject: [PATCH 481/864] feat: support for lubuntu LXQt --- docs/linux/installer.sh | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index dcbba1cd..04dc4434 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -7,7 +7,6 @@ API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" -DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries DESKTOP_ENTRY_NAME="PhoenixCode.desktop" DESKTOP_APP_NAME="Phoenix Code" DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" @@ -199,24 +198,24 @@ install_dependencies() { ubuntu|debian|linuxmint|kali) echo "Detected an Ubuntu/Debian based distribution." sudo apt update - sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ + yes | sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ gstreamer1.0-tools ;; fedora|rhel|centos) - echo "Detected a Fedora/Red Hat based distribution." - yes | sudo dnf install webkit2gtk3 gtk3 \ + echo "Detected a Fedora/Red Hat based distribution." + yes | sudo dnf install webkit2gtk3 gtk3 \ gstreamer1-plugins-base gstreamer1-plugins-good - ;; + ;; arch|manjaro) - echo "Detected an Arch Linux based distribution." - sudo pacman -Syu - sudo pacman -S webkit2gtk gtk3 - ;; + echo "Detected an Arch Linux based distribution." + sudo pacman -Syu + sudo pacman -S webkit2gtk gtk3 + ;; *) - echo "Unsupported distribution. Please manually install the required dependencies." - exit 1 - ;; + echo "Unsupported distribution. Please manually install the required dependencies." + exit 1 + ;; esac } # Verify and Install Dependencies Function @@ -394,11 +393,18 @@ EOF kbuildsycoca5 fi fi + + if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then + if command -v lxqt-config &> /dev/null; then + lxqt-config --clear-cache + fi + fi # Set Phoenix Code as the default application for the MIME types set_default_application echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" } + downloadLatestReleaseInfo() { local release_info_file="$TMP_DIR/latest_release.json" @@ -459,13 +465,12 @@ downloadLatestReleaseInfo() { # version and decide whether an upgrade is necessary. # downloadAndInstall(){ - echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null # Check Ubuntu version for compatibility if [ -f /etc/os-release ]; then . /etc/os-release - if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then + if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then local latestFileUrl latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") WGET_OPTS=$(configure_wget_options) @@ -737,6 +742,12 @@ uninstall() { kbuildsycoca5 fi fi + + if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then + if command -v lxqt-config &> /dev/null; then + lxqt-config --clear-cache + fi + fi else echo -e "${RED}Desktop entry not found. Skipping...${RESET}" fi From a06381532c42d5e487b840c5df91a4c43df2080d Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 21 May 2024 21:31:09 +0530 Subject: [PATCH 482/864] doc: adding code doc --- docs/linux/installer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 04dc4434..adc8e102 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,7 +1,7 @@ #!/bin/bash set -euo pipefail # Exit immediately if a command exits with a non-zero status. # Define common variables -DESKTOP_DIR=$HOME/.local/share/applications +DESKTOP_DIR=$HOME/.local/share/applications # Directory for desktop entries GITHUB_REPO="phcode-dev/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" From b6de4ba4368dbba4cf16b6f785493e68720723f4 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 23 May 2024 17:49:56 +0530 Subject: [PATCH 483/864] fix: lubuntu paner update --- docs/linux/installer.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index adc8e102..c88b1212 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -395,8 +395,8 @@ EOF fi if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then - if command -v lxqt-config &> /dev/null; then - lxqt-config --clear-cache + if command -v xdg-desktop-menu &> /dev/null; then + xdg-desktop-menu forceupdate fi fi # Set Phoenix Code as the default application for the MIME types @@ -744,8 +744,8 @@ uninstall() { fi if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then - if command -v lxqt-config &> /dev/null; then - lxqt-config --clear-cache + if command -v xdg-desktop-menu &> /dev/null; then + xdg-desktop-menu forceupdate fi fi else From eb359d2642d286e1669f6231c353ef75baba3735 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Thu, 23 May 2024 18:15:21 +0530 Subject: [PATCH 484/864] chore: add proper mesaging for lubuntu --- docs/linux/installer.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index c88b1212..e11ac9d2 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -397,6 +397,9 @@ EOF if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then if command -v xdg-desktop-menu &> /dev/null; then xdg-desktop-menu forceupdate + echo -e "${YELLOW}Please log out and log back in to see Phoenix Code in the panel.${RESET}" + else + echo -e "${RED}Failed to update LXQt menu. Please log out and log back in to see Phoenix Code in the panel.${RESET}" fi fi # Set Phoenix Code as the default application for the MIME types From cf4cddae8cc451d430a8780eb10b327864546efe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 23:35:04 +0000 Subject: [PATCH 485/864] chore(deps): update dependency axios-retry to v4.3.0 --- package-lock.json | 9 +++++---- package.json | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index fc50c4d9..5a83b5f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@tauri-apps/cli": "1.5.12", "adm-zip": "0.5.12", "axios": "1.6.8", - "axios-retry": "4.1.0", + "axios-retry": "4.3.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^8.0.0", @@ -270,10 +270,11 @@ } }, "node_modules/axios-retry": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.1.0.tgz", - "integrity": "sha512-svdth4H00yhlsjBbjfLQ/sMLkXqeLxhiFC1nE1JtkN/CIssGxqk0UwTEdrVjwA2gr3yJkAulwvDSIm4z4HyPvg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.3.0.tgz", + "integrity": "sha512-vUAQ3bi02Q++b8aAn3fuM03qRKFLZ6BPcqSVsOpgWeww2jrYFpu9SKb9VuctvxrJuRCWM/voDuuRAD7v3A1G5g==", "dev": true, + "license": "Apache-2.0", "dependencies": { "is-retry-allowed": "^2.2.0" }, diff --git a/package.json b/package.json index ac0fc39c..e285e454 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "shx": "^0.3.4", "tar": "6.2.1", "axios": "1.6.8", - "axios-retry": "4.1.0" + "axios-retry": "4.3.0" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From f7adb8783d64c87cb112197a9f982c0abf5f2fd5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 May 2024 16:45:16 +0000 Subject: [PATCH 486/864] fix(deps): update rust crate tauri to v1.6.7 [security] --- src-tauri/Cargo.lock | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index a97d590c..fd9f273d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2114,7 +2114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -3899,9 +3899,9 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.6.2" +version = "1.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "047aefcc7721bfb8024a9bc39d4719112262610502de7a224fa62c4570cd78d4" +checksum = "67c7177b6be45bbb875aa239578f5adc982a1b3d5ea5b315ccd100aeb0043374" dependencies = [ "anyhow", "base64 0.21.7", @@ -3914,6 +3914,7 @@ dependencies = [ "encoding_rs", "flate2", "futures-util", + "getrandom 0.2.12", "glib", "glob", "gtk", @@ -3981,9 +3982,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1554c5857f65dbc377cefb6b97c8ac77b1cb2a90d30d3448114d5d6b48a77fc" +checksum = "c3a1d90db526a8cdfd54444ad3f34d8d4d58fa5c536463915942393743bd06f8" dependencies = [ "base64 0.21.7", "brotli", @@ -4007,11 +4008,11 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.3" +version = "1.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "277abf361a3a6993ec16bcbb179de0d6518009b851090a01adfea12ac89fa875" +checksum = "6a582d75414250122e4a597b9dd7d3c910a2c77906648fc2ac9353845ff0feec" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "syn 1.0.109", @@ -4077,9 +4078,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2d0652aa2891ff3e9caa2401405257ea29ab8372cce01f186a5825f1bd0e76" +checksum = "cd7ffddf36d450791018e63a3ddf54979b9581d9644c584a5fb5611e6b5f20b4" dependencies = [ "gtk", "http", @@ -4098,9 +4099,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.5" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "067c56fc153b3caf406d7cd6de4486c80d1d66c0f414f39e94cb2f5543f6445f" +checksum = "1989b3b4d611f5428b3414a4abae6fa6df30c7eb8ed33250ca90a5f7e5bb3655" dependencies = [ "arboard", "cocoa", @@ -4119,15 +4120,15 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.5.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75ad0bbb31fccd1f4c56275d0a5c3abdf1f59999f72cb4ef8b79b4ed42082a21" +checksum = "450b17a7102e5d46d4bdabae0d1590fd27953e704e691fc081f06c06d2253b35" dependencies = [ "brotli", "ctor", "dunce", "glob", - "heck 0.4.1", + "heck 0.5.0", "html5ever", "infer", "json-patch", @@ -5496,9 +5497,9 @@ dependencies = [ [[package]] name = "wry" -version = "0.24.7" +version = "0.24.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ad85d0e067359e409fcb88903c3eac817c392e5d638258abfb3da5ad8ba6fc4" +checksum = "00711278ed357350d44c749c286786ecac644e044e4da410d466212152383b45" dependencies = [ "base64 0.13.1", "block", From e4e361d1a82e578cfb669a1c1f89b1c836e2800c Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 24 May 2024 15:32:53 +0530 Subject: [PATCH 487/864] fix: update was failing in ubuntu 24.04 if it was upgraded from 23 --- docs/linux/checkpackage.sh | 0 docs/linux/installer.sh | 35 +++++++++++++++++++---------------- 2 files changed, 19 insertions(+), 16 deletions(-) create mode 100644 docs/linux/checkpackage.sh diff --git a/docs/linux/checkpackage.sh b/docs/linux/checkpackage.sh new file mode 100644 index 00000000..e69de29b diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index e11ac9d2..3bd578f2 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -86,6 +86,23 @@ trap cleanup EXIT # Register the cleanup function to be called on script exit. TMP_DIR=$(mktemp -d) +check_ubuntu_version() { + if [ -f /etc/os-release ]; then + . /etc/os-release + if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then + local latestFileUrl + latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") + WGET_OPTS=$(configure_wget_options) + + wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { + echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" + } + echo -e "${RED}Ubuntu 24.04 LTS is not currently supported by this installation script.${RESET}" + echo -e "${YELLOW}Please use an earlier version of Ubuntu for the time being. Check back later for updates.${RESET}" + exit 1 + fi + fi +} # Create Invocation Script Function # # Purpose: @@ -267,6 +284,8 @@ verify_and_install_dependencies() { echo "Application launch verification successful." return 0 # Exit the function successfully if verification succeeds else + # Check Ubuntu version for compatibility + check_ubuntu_version echo "Initial verification failed. Attempting to install dependencies..." install_dependencies # Function to install required dependencies fi @@ -470,22 +489,6 @@ downloadLatestReleaseInfo() { downloadAndInstall(){ echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null - # Check Ubuntu version for compatibility - if [ -f /etc/os-release ]; then - . /etc/os-release - if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then - local latestFileUrl - latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") - WGET_OPTS=$(configure_wget_options) - - wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { - echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" - } - echo -e "${RED}Ubuntu 24.04 LTS is not currently supported by this installation script.${RESET}" - echo -e "${YELLOW}Please use an earlier version of Ubuntu for the time being. Check back later for updates.${RESET}" - exit 1 - fi - fi CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" From cf175b4528e5942d33b7080ba9c91f2086b9277d Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Fri, 24 May 2024 16:17:04 +0530 Subject: [PATCH 488/864] chore: code clean up --- docs/linux/checkpackage.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/linux/checkpackage.sh diff --git a/docs/linux/checkpackage.sh b/docs/linux/checkpackage.sh deleted file mode 100644 index e69de29b..00000000 From 55adb14915b58352731f554cae0d36c71b4edbaf Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 25 May 2024 13:16:50 +0000 Subject: [PATCH 489/864] ci: update phcode version to 3.7.3 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e285e454..1e8c17a5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.7.2", + "version": "3.7.3", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "da689fd410f987e387f1e28f32690e5a9ae929f6" + "commit": "b5fe1f2f375bd6a4b035d828e36f339966b5e71b" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 43f637c2..41853092 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.7.2" +version = "3.7.3" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 3871d13d..1bed8112 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.7.2" + "version": "3.7.3" }, "tauri": { "allowlist": { From ecf63a7855aeec0236eb53d1fc50b937360c534b Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 26 May 2024 09:47:08 +0000 Subject: [PATCH 490/864] ci: tauri release update notification json --- docs/install.json | 6 +++--- docs/tauri/update-latest-stable-prod.json | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/install.json b/docs/install.json index 14968c43..c4d82568 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,7 +1,7 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_3.6.4_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_3.6.4_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_3.6.4_x64.dmg" + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_3.7.3_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_3.7.3_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_3.7.3_x64.dmg" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 95c70e56..5bf9bcee 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,19 +1,19 @@ { - "version": "3.6.4", - "notes": "April release(3.6) of Phoenix Code is now available.\r\n\r\nThis month's upgrade is big! with a lot of features you asked for - PHP/Custom\r\nlive preview servers, advanced CSS/LESS/SCSS/HTML code intelligence and tooling,\r\nUX and app stability improvements.\r\n\r\n## Custom Live Preview Servers\r\n\r\nPreview PHP, React, and other dynamically rendered files with the\r\nnew server settings dialog. Read more at\r\n[Live Preview Settings Docs](https://docs.phcode.dev/docs/Features/live-preview-settings/).\r\n\r\n![Screenshot from 2024-04-12 13-08-34](https://github.com/phcode-dev/phoenix/assets/5336369/69fa0ee4-7262-42af-97d2-26154ec4a3b9)\r\n\r\n#### HTML Code Intelligence\r\n\r\nCSS class hints are now shown within the HTML file's class attribute.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/112ad909-8fd0-4fc4-8042-041ecade9481)\r\n\r\n## Advanced CSS Tooling\r\n\r\nSupport for the latest CSS/LESS/SCSS syntax. Code intelligence and error\r\ndetection for CSS, SCSS, and LESS files.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/9c083bd3-9e34-418d-a1c8-c152393c37b2)\r\n\r\n## Reverse CSS Highlighting\r\n\r\nClicking an element in the live preview now highlights its selector in the\r\nsource CSS file editor.\r\n![Reverse CSS Highlighting gif](https://github.com/phcode-dev/phoenix/assets/5336369/dcb9a111-60fa-479b-8766-dd3109b2134f)\r\n\r\n## Editor Rulers\r\n\r\nAdd multiple, color-customizable rulers in the editor to better visualize line\r\nlengths. [Read more...](https://docs.phcode.dev/docs/Features/editor-rulers/)\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/71b8b04c-d2ca-47b8-84bb-53cd0fb4593c)\r\n\r\n## Open Live Preview in any Browser\r\n\r\nDirect buttons to open live previews in Chrome, Edge, Safari, and Firefox.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/05f92c99-8a35-45a5-a8ee-75d581e6e96a)\r\n\r\n## Docusaurus Support\r\n\r\nLive preview [docusaurus.io](https://docusaurus.io/) based markdown documentation server.\r\n\r\n## UX Improvements\r\n\r\nIncreased stability and more predictable live preview behavior.\r\n\r\n## Community Contributions\r\n\r\n1. Changes to files and folders made externally are now automatically synced in\r\n the Browser version of Phoenix Code.\r\n ([view change](https://github.com/phcode-dev/phoenix/pull/1566)) - By\r\n [Andrew Young](https://github.com/ayoung5555),\r\n [Faizan Bhagat](https://github.com/faizanbhagat)\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", - "pub_date": "2024-04-29T12:11:31.618Z", + "version": "3.7.3", + "notes": "May release(3.7) of Phoenix Code is now available.\r\n\r\nThis month's release is all about Live previews and the little things that make your work just a bit easier. We've also addressed numerous feature requests and UX bug reports, along with improving app UX and stability.\r\n\r\n#### Live CSS Class and Style Code Hints\r\n\r\nInteractively edit CSS styles and classes using the up/down arrow keys in code hints. This provides an instant boost to your HTML and CSS workflows.\r\n\r\n![classLiveHints](https://github.com/phcode-dev/phoenix/assets/5336369/502c8751-5269-4c34-9178-5ad08f8ad837)\r\n\r\n#### CSS/HTML Code Hints improvements\r\n\r\nImproved relevance of suggestions in CSS and HTML code hints. For E.g., typing `b` in a CSS file will prioritize `background-color`. Typing `between` will bring up relevant CSS property-value combinations like `align-content: space-between;` (see image below), so you don't have to remember which value is under which CSS property.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/2a9f8809-de19-43cf-bdcd-d1a5def2e080)\r\n\r\n#### Move to trash/bin when deleting files\r\n\r\nDeleting files from the files panel in desktop apps will move the file/folder to trash/recycle bin instead of permanently deleting it.\r\n\r\n#### UX Improvements\r\n\r\n* Deleting the `Phoenix Code` folder in user `Documents` directory is now supported in desktop apps.\r\n* Increased stability and app startup experience.\r\n* `Copy Error Message` button is now available in the problems panel.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/95c59e71-5ce8-4697-963e-0fa567062ab0)\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.", + "pub_date": "2024-05-25T13:48:47.470Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnJrMUpFUlFJNUdmeVdhb2VSMFhqemdWRmpUN3l3VnRpSEFyZnYrS2pwenA3bXRzY1FlT0s2LzlRVlJEQ25NMFQxL3lSbE1SMzF5b29zd2xBRFNQS2d3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MzkxMTQ5CWZpbGU6UGhvZW5peCBDb2RlXzMuNi40X3g2NC1zZXR1cC5uc2lzLnppcApaNkpmc1AyYWkvQWZCZXZRVFhqN2oyV1ZXV0l5bk9NTktoU1AxMERiTk8xdnk1U0owZEVBQ09vUUFHTW5HV0NzM1VGM3VmN1o1R3NGVXNEQmgvUjhDQT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_3.6.4_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVnTkFKdmhnQk5VbEZhTDZXa2RRTjVLZUtRbUVHLzZiK2YveU5VVE9Ob0pTaTRJL1dONUJjbjY2S0R6VDdDcmJMejVZYms1em5wb3JkSlhjRERpOFE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE2NjQzOTIyCWZpbGU6UGhvZW5peCBDb2RlXzMuNy4zX3g2NC1zZXR1cC5uc2lzLnppcApTMFF1ZEVtd2h3Y3hvUlYxV0NvVnluUk1GQTB0VnJYSVNDK3lwSG9sc1pHeGUycmRFd0F0dWF4cUt6d08ySXdSN0lCOTBKbW53eTFidVRqaEkxQ0ZDdz09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_3.7.3_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlIV25FQklhTVB1eTFzOXkrZXR0Q1FTbEp3MmNZRFdoMkk4SFZUaUthNjljbjlXZHNGK3ByZHRTRHE3ZVQ4aWM4dFhQRVdNdFdUVnBtVVRrcHlRRVFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MzkxODczCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKWDVlRFcvSGRDZ0psSy96QThjSmk1Tzl1RDB6T2NxbkliZHJONHIycWFwamxCNHJPUWI1SG5LWTRKa0pJandDYTZ5UGpLbG45TE1mazdtV1ltK2Q0QlE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnU5M0xRMjg1S2VnVnBmWlN4eDUzS0dXUWdrSVpuREVrbWlEUjhwNmNSc3pEOHJRS3h0S2dscVBESjRSM29aMit4M2N2ZVB0YTN5MmxhWmNlVzdTYndzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE2NjQ0MDY3CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKT2tqUXEzMTVsNTNsRll2SXVGZXA4SGhVTURSSU5LYmVoZ1ZVTGorZkczL3NxeWJwalZCQjVISnN3YlVoWEx2UzEzRnFKZVd5a2hzaXk2MEdMQTkzQ2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9PUWpBRlcrWFVZWnBRUzhIK3FrMVRhckdLdWpHUkRKUXZJdkVWOXM1V2cwZzVEV1laekQ2K0ZUY2RwUnEyZUxTVWREU3ZFcDZnNk5XaldaMDdJMkE0PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0MzkyNjg2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKa0xtU1JRVVYwc2tiNUMxME85WlpkR3JCUndxY1R5anFZY2p0Q2I2VXVFYmlEN25XcHVaN2tka0F5TmtoK2Q0NDVxRjdzVHpYUWRFYUNuSjdkQjh2RFE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.6.4/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdzYkcrNHZ2QTgyQlJvZHFtNm9qUmJnbnJqYXNqaDFRZjkxSUVBN284UTJkd3h3ai9td09ZR2pFbUFyRkxRZWNpWnpwa3c2dHBkTHpFeTUvUXY2Mmd3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE2NjQ0OTEwCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKWnpBUklmSHYxT2NLaVIxc2IwbXpUZ3ViZGZ5d1ZiMTg5bFhNUzllV01YR1hrb1JCZGt5WG1MNE5wUnJjQUNJN1NLU0F2YjlxL2UraEZYdmJYKy9LRGc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From e4f0600065d02c5ee2e1ec6dddadbcdb0aa88ae8 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 26 May 2024 23:50:48 +0530 Subject: [PATCH 491/864] feat: support for ubuntu 24.04 --- docs/linux/installer.sh | 96 ++++++++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 26 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 3bd578f2..eeb0a21e 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -5,6 +5,8 @@ DESKTOP_DIR=$HOME/.local/share/applications # Directory for desktop entries GITHUB_REPO="phcode-dev/phoenix-desktop" API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" +GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/gtk.tar.xz" +WEBKIT2GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/webkit2gtk-4.0.tar.xz" INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" DESKTOP_ENTRY_NAME="PhoenixCode.desktop" @@ -90,18 +92,10 @@ check_ubuntu_version() { if [ -f /etc/os-release ]; then . /etc/os-release if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then - local latestFileUrl - latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") - WGET_OPTS=$(configure_wget_options) - - wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { - echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" - } - echo -e "${RED}Ubuntu 24.04 LTS is not currently supported by this installation script.${RESET}" - echo -e "${YELLOW}Please use an earlier version of Ubuntu for the time being. Check back later for updates.${RESET}" - exit 1 + return 0 # Ubuntu 24.04 detected fi fi + return 1 # Not Ubuntu 24.04 } # Create Invocation Script Function # @@ -235,6 +229,59 @@ install_dependencies() { ;; esac } + +download_and_install_gtk() { + echo -e "${YELLOW}Downloading GTK from $GTK_URL...${RESET}" + local destination="$TMP_DIR/phoenix-code" + WGET_OPTS=$(configure_wget_options) + + wget $WGET_OPTS "$TMP_DIR/gtk.tar.xz" "$GTK_URL" || { + echo -e "${RED}Failed to download GTK. Please check your internet connection and try again.${RESET}" + exit 1 + } + echo "Extracting GTK..." + tar -xJf "$TMP_DIR/gtk.tar.xz" -C "$destination" || { + echo -e "${RED}Failed to extract GTK. The downloaded file might be corrupt.${RESET}" + exit 1 + } + + echo -e "${YELLOW}Downloading WebKit2GTK from $WEBKIT2GTK_URL...${RESET}" + wget $WGET_OPTS "$TMP_DIR/webkit2gtk-4.0.tar.xz" "$WEBKIT2GTK_URL" || { + echo -e "${RED}Failed to download WebKit2GTK. Please check your internet connection and try again.${RESET}" + exit 1 + } + echo "Extracting WebKit2GTK..." + tar -xJf "$TMP_DIR/webkit2gtk-4.0.tar.xz" -C "$TMP_DIR" || { + echo -e "${RED}Failed to extract WebKit2GTK. The downloaded file might be corrupt.${RESET}" + exit 1 + } + echo "Installing WebKit2GTK..." + sudo cp -r "$TMP_DIR/webkit2gtk-4.0" /usr/lib/x86_64-linux-gnu/ || { + echo -e "${RED}Failed to install WebKit2GTK. Please check the permissions and try again.${RESET}" + exit 1 + } + echo -e "${GREEN}WebKit2GTK installed successfully.${RESET}" +} + + +create_launch_script_with_gtk() { + local binary_path="$1" + local binary_name="phoenix-code" + + local realBin="$binary_path/$binary_name.real" + mv "$binary_path/$binary_name" "$realBin" + echo "Creating a launch script for Phoenix Code with GTK libraries..." + cat > "$binary_path/$binary_name" < Date: Mon, 27 May 2024 00:01:17 +0530 Subject: [PATCH 492/864] chore: code clean up --- docs/linux/installer.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index eeb0a21e..9f803857 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -229,8 +229,9 @@ install_dependencies() { ;; esac } - download_and_install_gtk() { + local GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/gtk.tar.xz" + local WEBKIT2GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/webkit2gtk-4.0.tar.xz" echo -e "${YELLOW}Downloading GTK from $GTK_URL...${RESET}" local destination="$TMP_DIR/phoenix-code" WGET_OPTS=$(configure_wget_options) From 169d20659b161a9f467038d8b8c27a36478cddeb Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 27 May 2024 13:23:42 +0530 Subject: [PATCH 493/864] chore: code clean up and doccumentation --- docs/linux/installer.sh | 138 ++++++++++++++++++++++++++++++++++------ 1 file changed, 120 insertions(+), 18 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 9f803857..16418513 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -88,6 +88,33 @@ trap cleanup EXIT # Register the cleanup function to be called on script exit. TMP_DIR=$(mktemp -d) +# Check Ubuntu Version Function +# +# Purpose: +# This function checks if the current operating system is Ubuntu 24.04. It does this by reading +# the /etc/os-release file, which contains identification data for the operating system. +# +# Behavior: +# 1. The function first checks if the /etc/os-release file exists. +# 2. If the file exists, it sources the file to load the OS identification variables. +# 3. It then checks if the ID variable is set to "ubuntu" and the VERSION_ID variable is set to "24.04". +# 4. If both conditions are met, the function returns 0 (indicating success). +# 5. If the conditions are not met, the function returns 1 (indicating failure). +# +# Usage: +# This function can be called to determine if special handling is needed for Ubuntu 24.04, such as +# installing additional libraries or making compatibility adjustments. +# +# Example: +# if check_ubuntu_version; then +# echo "Ubuntu 24.04 detected." +# else +# echo "Not Ubuntu 24.04." +# fi +# +# Notes: +# - This function assumes that the /etc/os-release file follows the standard format for Linux OS +# identification. check_ubuntu_version() { if [ -f /etc/os-release ]; then . /etc/os-release @@ -230,10 +257,46 @@ install_dependencies() { esac } download_and_install_gtk() { + # Function: create_launch_script_with_gtk + # + # Purpose: + # This function creates a launch script for the Phoenix Code application that sets the required + # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that + # the Phoenix Code application uses the correct GTK libraries, which are included in the + # application's installation directory. + # + # Parameters: + # - binary_path: The path to the directory containing the Phoenix Code binary. + # - binary_name: The name of the Phoenix Code binary file. + # + # Behavior: + # 1. The function renames the original Phoenix Code binary to append ".real" to its name. + # 2. It then creates a new launch script with the original binary name in the same directory. + # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the + # GTK libraries located in the same directory as the binary. + # 4. The launch script executes the original Phoenix Code binary (now renamed) with any + # arguments passed to the script. + # 5. The function sets the appropriate executable permissions on the launch script. + # + # Usage: + # This function should be called after the Phoenix Code binary and its required GTK libraries + # have been installed. It ensures that the application uses the correct libraries when launched. + # + # Example: + # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" + # + # Notes: + # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within + # the same directory as the Phoenix Code binary. + # - The function requires the mv, chmod, and cat commands to be available in the environment. + # - This piece of code should only be executed if the package manager does not distribute + # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. + local GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/gtk.tar.xz" local WEBKIT2GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/webkit2gtk-4.0.tar.xz" + echo -e "${YELLOW}Downloading GTK from $GTK_URL...${RESET}" - local destination="$TMP_DIR/phoenix-code" + local destination="$TMP_DIR/$BINARY_NAME" WGET_OPTS=$(configure_wget_options) wget $WGET_OPTS "$TMP_DIR/gtk.tar.xz" "$GTK_URL" || { @@ -246,28 +309,67 @@ download_and_install_gtk() { exit 1 } - echo -e "${YELLOW}Downloading WebKit2GTK from $WEBKIT2GTK_URL...${RESET}" - wget $WGET_OPTS "$TMP_DIR/webkit2gtk-4.0.tar.xz" "$WEBKIT2GTK_URL" || { - echo -e "${RED}Failed to download WebKit2GTK. Please check your internet connection and try again.${RESET}" - exit 1 - } - echo "Extracting WebKit2GTK..." - tar -xJf "$TMP_DIR/webkit2gtk-4.0.tar.xz" -C "$TMP_DIR" || { - echo -e "${RED}Failed to extract WebKit2GTK. The downloaded file might be corrupt.${RESET}" - exit 1 - } - echo "Installing WebKit2GTK..." - sudo cp -r "$TMP_DIR/webkit2gtk-4.0" /usr/lib/x86_64-linux-gnu/ || { - echo -e "${RED}Failed to install WebKit2GTK. Please check the permissions and try again.${RESET}" - exit 1 - } - echo -e "${GREEN}WebKit2GTK installed successfully.${RESET}" + if [ ! -d "/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0" ]; then + echo -e "${YELLOW}Downloading WebKit2GTK from $WEBKIT2GTK_URL...${RESET}" + wget $WGET_OPTS "$TMP_DIR/webkit2gtk-4.0.tar.xz" "$WEBKIT2GTK_URL" || { + echo -e "${RED}Failed to download WebKit2GTK. Please check your internet connection and try again.${RESET}" + exit 1 + } + echo "Extracting WebKit2GTK..." + tar -xJf "$TMP_DIR/webkit2gtk-4.0.tar.xz" -C "$TMP_DIR" || { + echo -e "${RED}Failed to extract WebKit2GTK. The downloaded file might be corrupt.${RESET}" + exit 1 + } + echo "Installing WebKit2GTK..." + sudo cp -r "$TMP_DIR/webkit2gtk-4.0" /usr/lib/x86_64-linux-gnu/ || { + echo -e "${RED}Failed to install WebKit2GTK. Please check the permissions and try again.${RESET}" + exit 1 + } + echo -e "${GREEN}WebKit2GTK installed successfully.${RESET}" + else + echo -e "${GREEN}WebKit2GTK already installed.${RESET}" + fi } create_launch_script_with_gtk() { + # Function: create_launch_script_with_gtk + # + # Purpose: + # This function creates a launch script for the Phoenix Code application that sets the required + # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that + # the Phoenix Code application uses the correct GTK libraries, which are included in the + # application's installation directory. + # + # Parameters: + # - binary_path: The path to the directory containing the Phoenix Code binary. + # - binary_name: The name of the Phoenix Code binary file. + # + # Behavior: + # 1. The function renames the original Phoenix Code binary to append ".real" to its name. + # 2. It then creates a new launch script with the original binary name in the same directory. + # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the + # GTK libraries located in the same directory as the binary. + # 4. The launch script executes the original Phoenix Code binary (now renamed) with any + # arguments passed to the script. + # 5. The function sets the appropriate executable permissions on the launch script. + # + # Usage: + # This function should be called after the Phoenix Code binary and its required GTK libraries + # have been installed. It ensures that the application uses the correct libraries when launched. + # + # Example: + # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" + # + # Notes: + # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within + # the same directory as the Phoenix Code binary. + # - The function requires the mv, chmod, and cat commands to be available in the environment. + # - This piece of code should only be executed if the package manager does not distribute + # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. + local binary_path="$1" - local binary_name="phoenix-code" + local binary_name="$BINARY_NAME" local realBin="$binary_path/$binary_name.real" mv "$binary_path/$binary_name" "$realBin" From 84bc127772b016650e9a1949090760d7fae0e885 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 24 May 2024 06:02:42 +0000 Subject: [PATCH 494/864] chore(deps): update tauri monorepo --- package-lock.json | 99 ++++++++++++++++++++++++-------------------- package.json | 2 +- src-tauri/Cargo.lock | 17 ++------ 3 files changed, 60 insertions(+), 58 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5a83b5f6..f952bce9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.7.2", "hasInstallScript": true, "devDependencies": { - "@tauri-apps/cli": "1.5.12", + "@tauri-apps/cli": "1.5.14", "adm-zip": "0.5.12", "axios": "1.6.8", "axios-retry": "4.3.0", @@ -22,10 +22,11 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.12.tgz", - "integrity": "sha512-tMvcMVIrvNjoPIVO5pZk7lJrHVXw7NBggpJXRAQsD7VkMW9hT1uX3jVZeoPCmQ5KbpXvjoNXe+Ws8nE2NR/8Ow==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.14.tgz", + "integrity": "sha512-JOSMKymlg116UdEXSj69eg5p1OtZnQkUE0qIGbtNDO1sk3X/KgBN6+oHBW0BzPStp/W0AjBgrMWCqjHPwEpOug==", "dev": true, + "license": "Apache-2.0 OR MIT", "bin": { "tauri": "tauri.js" }, @@ -37,26 +38,27 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.5.12", - "@tauri-apps/cli-darwin-x64": "1.5.12", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.12", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.12", - "@tauri-apps/cli-linux-arm64-musl": "1.5.12", - "@tauri-apps/cli-linux-x64-gnu": "1.5.12", - "@tauri-apps/cli-linux-x64-musl": "1.5.12", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.12", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.12", - "@tauri-apps/cli-win32-x64-msvc": "1.5.12" + "@tauri-apps/cli-darwin-arm64": "1.5.14", + "@tauri-apps/cli-darwin-x64": "1.5.14", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.14", + "@tauri-apps/cli-linux-arm64-gnu": "1.5.14", + "@tauri-apps/cli-linux-arm64-musl": "1.5.14", + "@tauri-apps/cli-linux-x64-gnu": "1.5.14", + "@tauri-apps/cli-linux-x64-musl": "1.5.14", + "@tauri-apps/cli-win32-arm64-msvc": "1.5.14", + "@tauri-apps/cli-win32-ia32-msvc": "1.5.14", + "@tauri-apps/cli-win32-x64-msvc": "1.5.14" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.12.tgz", - "integrity": "sha512-ud06E547WE7oDZeN5rH4eeB90Rie0aSCFH0Zb6XyNb6qgg0ZIftM+N3OjVONxk84/g//nr4/x7wW6LOwiwvPHw==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.14.tgz", + "integrity": "sha512-lxoSOp3KKSqzHJa7iT32dukPGMlfsTuja1xXSgwR8o/fqzpYJY7FY/3ZxesP8HR66FcK+vtqa//HNqeOQ0mHkA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -66,13 +68,14 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.12.tgz", - "integrity": "sha512-hSz9cuHO4lYora0z2XRFEIblkStT3eJvh/iYmsFfjT3usGBt2fTPMJ4SnL1Uyu64Y59dqyRNBikuBuymAFESjA==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.14.tgz", + "integrity": "sha512-EXSwN1n5spfG8FoXuyc90ACtmDJXzaZ1gxyENaq9xEpQoo7j/Q1vb6qXxmr6azKr8zmqY4h08ZFbv3exh93xJg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -82,13 +85,14 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.12.tgz", - "integrity": "sha512-FanE15/c7nz64CcTFe7f+8b7+rFQCb3Ivju+4sxVSPkAOJXHc5no3Y/LxFt85SAOMgPTB2FMuxHUdjvLjd2D1w==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.14.tgz", + "integrity": "sha512-Yb8BH/KYR7Tl+de40sZPfrqbhcU3Jlu+UPIrnXt05sjn48xqIps74Xjz8zzVp0TuHxUp8FmIGtCVhQgsbrsvvg==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -98,13 +102,14 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.12.tgz", - "integrity": "sha512-ETVyIcR4xVGnuhTgTY+kPG5LbAJQobPA8OxSLRY203f0cqYuSPffgyahtS65uPJ9egWIN3fflDKGTE1xcgFNAA==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.14.tgz", + "integrity": "sha512-QrKHP4gRaHiup478rPBZ+BmNd88yze9jMmheoNy9mN1K/aECRmTHO+tWhsxv5moFHZzRhO0QDWxxvTtiaPXaGg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -114,13 +119,14 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.12.tgz", - "integrity": "sha512-ZhMagbS50dDV9glHrtRg1bkUa7sUDPsZ9bJ0xnd0vr8Smi8RiJ/dgQbF5eQNp4ahzYl+FtLjBkMTZKACrKgusg==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.14.tgz", + "integrity": "sha512-Hb1C1VMxmUcyGjW/K/INKF87zzzgLEVRmWZZnQd7M1P4uue4xPyIwUELSdX12Z2jREPgmLW4AXPD0m6wsNu7iw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -130,13 +136,14 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.12.tgz", - "integrity": "sha512-H6jXU4AG8g6FZxX+U3M76zigbLvj7bE+wG+xOrS7xCRwkfAEKw0aulymdFfOl44KBZDQQsV5KYA6T6csx3KbIQ==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.14.tgz", + "integrity": "sha512-kD9v/UwPDuhIgq2TJj/s2/7rqk+vmExVV6xHPKI8vVbIvlNAOZqmx3fpxjej1241vhJ/piGd/m6q6YMWGsL0oQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -146,13 +153,14 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.12.tgz", - "integrity": "sha512-Y/0dzBD8oFZ04Xq75LKPJvOI2MbVFdwGY6w41l24OxNiNopF7AzdrZGTJ+MoUbU9PALNP8ABhOP6BYZiV528OA==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.14.tgz", + "integrity": "sha512-204Drgg9Zx0+THKndqASz4+iPCwqA3gQVF9C0CDIArNXrjPyJjVvW8VP5CHiZYaTNWxlz/ltyxluM6UFWbXNFw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" @@ -162,13 +170,14 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.12.tgz", - "integrity": "sha512-fxCS1/zQp+W7Lze+6Sh64RLqWFE57NsU+Y9L30ZKt5Prnt2LXEoa3POSaQpgHLRgwL/WfDW2nkYBRH3fVIrpQg==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.14.tgz", + "integrity": "sha512-sqPSni2MnWNCm+8YZnLdWCclxfSHaYqKuPFSz8q7Tn1G1m/cA9gyPoC1G0esHftY7bu/ZM5lB4kM3I4U0KlLiA==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -178,13 +187,14 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.12.tgz", - "integrity": "sha512-keWSEBOxL8q750AzmL4L3DDJzDzmb6DGT3+0HTjbEfu+a2GRS1lnrkm3EEeAepPoz4r62+cOQbjPRP8YGtGfFw==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.14.tgz", + "integrity": "sha512-8xN8W0zTs8oFsQmvYLxHFeqhzVI7oTaPK1xQMc5gbpFP45jN41c21aCXfjnvzT+h90EfCHUF9EWj2HTEJSb7Iw==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" @@ -194,13 +204,14 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.12", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.12.tgz", - "integrity": "sha512-+eIvaPVwtVM7puXlCZIS1lSFF0VZ0gAUShKwk/kBZi8xUYQoNEW2RUWSPp+TEdZsMiAxd/zFZ+tGgv83Hxjbjg==", + "version": "1.5.14", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.14.tgz", + "integrity": "sha512-U0slee5tNM2PYECBpPHavLSwkT3szGMZ+qhcikQQbDan84bQdLn/kHWjyXOgLJs4KSve4+KxcrN+AVqj0VyHnw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" diff --git a/package.json b/package.json index 1e8c17a5..587a3c50 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { - "@tauri-apps/cli": "1.5.12", + "@tauri-apps/cli": "1.5.14", "adm-zip": "0.5.12", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index fd9f273d..4952cefd 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1862,7 +1862,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core 0.51.1", ] [[package]] @@ -3963,14 +3963,14 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9914a4715e0b75d9f387a285c7e26b5bbfeb1249ad9f842675a82481565c532" +checksum = "ab30cba12974d0f9b09794f61e72cad6da2142d3ceb81e519321bab86ce53312" dependencies = [ "anyhow", "cargo_toml", "dirs-next", - "heck 0.4.1", + "heck 0.5.0", "json-patch", "semver", "serde", @@ -5074,15 +5074,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.5", -] - [[package]] name = "windows-core" version = "0.56.0" From 703ff1e273ef9242187e70d37a40ffd1e63b5193 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 26 Apr 2024 19:05:00 +0000 Subject: [PATCH 495/864] chore(deps): update dependency macos to v14 --- .github/workflows/desktop-mac-test-pull.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 72a1d9d3..7a124adc 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -9,7 +9,7 @@ concurrency: jobs: test-desktop-mac: - runs-on: macos-12 + runs-on: macos-14 timeout-minutes: 90 steps: - uses: actions/checkout@v4 From adc358018eff3ba505805691e7c2c5cc6cdfbe82 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 27 May 2024 13:33:02 +0530 Subject: [PATCH 496/864] Revert "chore(deps): update dependency macos to v14" This reverts commit 703ff1e273ef9242187e70d37a40ffd1e63b5193. --- .github/workflows/desktop-mac-test-pull.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 7a124adc..72a1d9d3 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -9,7 +9,7 @@ concurrency: jobs: test-desktop-mac: - runs-on: macos-14 + runs-on: macos-12 timeout-minutes: 90 steps: - uses: actions/checkout@v4 From 742bd47d500eb6ed1c779af2ce7530286080ea9c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 08:03:19 +0000 Subject: [PATCH 497/864] fix(deps): update rust crate serde to v1.0.203 --- src-tauri/Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 4952cefd..19cce25b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2849,7 +2849,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.7.2" +version = "3.7.3" dependencies = [ "clipboard-files", "fix-path-env", @@ -3417,18 +3417,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.200" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", From 5d6ce43ae4c8349b5afbf950d323ddf2b9c51232 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 22:07:34 +0000 Subject: [PATCH 498/864] chore(deps): update dependency execa to v9 --- package-lock.json | 192 +++++++++++++++++++++++++++++++--------------- package.json | 2 +- 2 files changed, 132 insertions(+), 62 deletions(-) diff --git a/package-lock.json b/package-lock.json index f952bce9..c6c4f1fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,12 +15,30 @@ "axios-retry": "4.3.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", - "execa": "^8.0.0", + "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.1" } }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "dev": true + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@tauri-apps/cli": { "version": "1.5.14", "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.14.tgz", @@ -488,28 +506,46 @@ "dev": true }, "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.0.0.tgz", + "integrity": "sha512-YqlYPdTp6UMdt0WEM8QKeBR8ORtgxWP7ZB5NB9AMlfGWg32Fg48j6uZdKfhG2o6cNJBIRPF0Ok93R0vY37oBWQ==", "dev": true, "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", + "figures": "^6.1.0", + "get-stream": "^9.0.0", + "human-signals": "^7.0.0", + "is-plain-obj": "^4.1.0", + "is-stream": "^4.0.1", + "npm-run-path": "^5.2.0", + "pretty-ms": "^9.0.0", "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" + "strip-final-newline": "^4.0.0", + "yoctocolors": "^2.0.0" }, "engines": { - "node": ">=16.17" + "node": ">=18" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/figures": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", + "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", + "dev": true, + "dependencies": { + "is-unicode-supported": "^2.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -645,12 +681,16 @@ } }, "node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "dev": true, + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -707,12 +747,12 @@ } }, "node_modules/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-7.0.0.tgz", + "integrity": "sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==", "dev": true, "engines": { - "node": ">=16.17.0" + "node": ">=18.18.0" } }, "node_modules/inflight": { @@ -803,6 +843,18 @@ "node": ">=0.12.0" } }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-retry-allowed": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", @@ -816,12 +868,24 @@ } }, "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", "dev": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-unicode-supported": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "dev": true, + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -870,12 +934,6 @@ "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", "dev": true }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -897,18 +955,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1021,21 +1067,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -1072,6 +1103,18 @@ "node": ">=6" } }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -1117,6 +1160,21 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pretty-ms": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz", + "integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==", + "dev": true, + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -1278,12 +1336,12 @@ } }, "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", + "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", "dev": true, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1419,6 +1477,18 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "node_modules/yoctocolors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.0.0.tgz", + "integrity": "sha512-esbDnt0Z1zI1KgvOZU90hJbL6BkoUbrP9yy7ArNZ6TmxBxydMJTYMf9FZjmwwcA8ZgEQzriQ3hwZ0NYXhlFo8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index 587a3c50..39201bbc 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "adm-zip": "0.5.12", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", - "execa": "^8.0.0", + "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "6.2.1", From e110a4c5938589e3bcf3cdaf1fcde9164c638c96 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 27 May 2024 20:33:38 +0530 Subject: [PATCH 499/864] feat: not working in lubuntu 24.04 --- docs/linux/installer.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 16418513..7af624f7 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -292,8 +292,8 @@ download_and_install_gtk() { # - This piece of code should only be executed if the package manager does not distribute # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. - local GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/gtk.tar.xz" - local WEBKIT2GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/webkit2gtk-4.0.tar.xz" + local GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.1/gtk.tar.xz" + local WEBKIT2GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.1/webkit2gtk-4.0.tar.xz" echo -e "${YELLOW}Downloading GTK from $GTK_URL...${RESET}" local destination="$TMP_DIR/$BINARY_NAME" @@ -371,14 +371,14 @@ create_launch_script_with_gtk() { local binary_path="$1" local binary_name="$BINARY_NAME" - local realBin="$binary_path/$binary_name.real" + local realBin="$binary_path/$binary_name.app" mv "$binary_path/$binary_name" "$realBin" echo "Creating a launch script for Phoenix Code with GTK libraries..." cat > "$binary_path/$binary_name" < Date: Tue, 28 May 2024 00:11:37 +0530 Subject: [PATCH 500/864] feat: adding support for kubutntu 24.04 --- docs/linux/installer.sh | 89 +++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 38 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 7af624f7..fc793154 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -257,43 +257,47 @@ install_dependencies() { esac } download_and_install_gtk() { - # Function: create_launch_script_with_gtk - # - # Purpose: - # This function creates a launch script for the Phoenix Code application that sets the required - # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that - # the Phoenix Code application uses the correct GTK libraries, which are included in the - # application's installation directory. - # - # Parameters: - # - binary_path: The path to the directory containing the Phoenix Code binary. - # - binary_name: The name of the Phoenix Code binary file. - # - # Behavior: - # 1. The function renames the original Phoenix Code binary to append ".real" to its name. - # 2. It then creates a new launch script with the original binary name in the same directory. - # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the - # GTK libraries located in the same directory as the binary. - # 4. The launch script executes the original Phoenix Code binary (now renamed) with any - # arguments passed to the script. - # 5. The function sets the appropriate executable permissions on the launch script. - # - # Usage: - # This function should be called after the Phoenix Code binary and its required GTK libraries - # have been installed. It ensures that the application uses the correct libraries when launched. - # - # Example: - # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" - # - # Notes: - # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within - # the same directory as the Phoenix Code binary. - # - The function requires the mv, chmod, and cat commands to be available in the environment. - # - This piece of code should only be executed if the package manager does not distribute - # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. - - local GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.1/gtk.tar.xz" - local WEBKIT2GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.1/webkit2gtk-4.0.tar.xz" + # Function: create_launch_script_with_gtk + # + # Purpose: + # This function creates a launch script for the Phoenix Code application that sets the required + # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that + # the Phoenix Code application uses the correct GTK libraries, which are included in the + # application's installation directory. + # + # Parameters: + # - binary_path: The path to the directory containing the Phoenix Code binary. + # - binary_name: The name of the Phoenix Code binary file. + # + # Behavior: + # 1. The function renames the original Phoenix Code binary to append ".real" to its name. + # 2. It then creates a new launch script with the original binary name in the same directory. + # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the + # GTK libraries located in the same directory as the binary. + # 4. The launch script executes the original Phoenix Code binary (now renamed) with any + # arguments passed to the script. + # 5. The function sets the appropriate executable permissions on the launch script. + # + # Usage: + # This function should be called after the Phoenix Code binary and its required GTK libraries + # have been installed. It ensures that the application uses the correct libraries when launched. + # + # Example: + # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" + # + # Notes: + # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within + # the same directory as the Phoenix Code binary. + # - The function requires the mv, chmod, and cat commands to be available in the environment. + # - This piece of code should only be executed if the package manager does not distribute + # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. + + local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.2/" + local GTK_FILE="gtk.tar.xz" + local WEBKIT2GTK_FILE="webkit2gtk-4.0.tar.xz" + + local GTK_URL="${URL_PREFIX}${GTK_FILE}" + local WEBKIT2GTK_URL="${URL_PREFIX}${WEBKIT2GTK_FILE}" echo -e "${YELLOW}Downloading GTK from $GTK_URL...${RESET}" local destination="$TMP_DIR/$BINARY_NAME" @@ -311,7 +315,7 @@ download_and_install_gtk() { if [ ! -d "/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0" ]; then echo -e "${YELLOW}Downloading WebKit2GTK from $WEBKIT2GTK_URL...${RESET}" - wget $WGET_OPTS "$TMP_DIR/webkit2gtk-4.0.tar.xz" "$WEBKIT2GTK_URL" || { + wget $WGET_OPTS "$TMP_DIR/webkit2gtk-4.0.tar.xz" "$WEBKIT2GTK_URL" || { echo -e "${RED}Failed to download WebKit2GTK. Please check your internet connection and try again.${RESET}" exit 1 } @@ -320,6 +324,15 @@ download_and_install_gtk() { echo -e "${RED}Failed to extract WebKit2GTK. The downloaded file might be corrupt.${RESET}" exit 1 } + + # Inform the user that the next steps require administrative access + echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." + + # Check if the script can execute sudo commands without interaction + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed with the installation of dependencies." + fi + echo "Installing WebKit2GTK..." sudo cp -r "$TMP_DIR/webkit2gtk-4.0" /usr/lib/x86_64-linux-gnu/ || { echo -e "${RED}Failed to install WebKit2GTK. Please check the permissions and try again.${RESET}" From 107b2ff188606a0d2bd8dec2323a127a0164b88b Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 28 May 2024 00:33:12 +0530 Subject: [PATCH 501/864] chore: code clean up --- docs/linux/installer.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index fc793154..77330cb8 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -308,19 +308,19 @@ download_and_install_gtk() { exit 1 } echo "Extracting GTK..." - tar -xJf "$TMP_DIR/gtk.tar.xz" -C "$destination" || { + tar -xJf "$TMP_DIR/$GTK_FILE" -C "$destination" || { echo -e "${RED}Failed to extract GTK. The downloaded file might be corrupt.${RESET}" exit 1 } if [ ! -d "/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0" ]; then echo -e "${YELLOW}Downloading WebKit2GTK from $WEBKIT2GTK_URL...${RESET}" - wget $WGET_OPTS "$TMP_DIR/webkit2gtk-4.0.tar.xz" "$WEBKIT2GTK_URL" || { + wget $WGET_OPTS "$TMP_DIR/$WEBKIT2GTK_FILE" "$WEBKIT2GTK_URL" || { echo -e "${RED}Failed to download WebKit2GTK. Please check your internet connection and try again.${RESET}" exit 1 } echo "Extracting WebKit2GTK..." - tar -xJf "$TMP_DIR/webkit2gtk-4.0.tar.xz" -C "$TMP_DIR" || { + tar -xJf "$TMP_DIR/$WEBKIT2GTK_FILE" -C "$TMP_DIR" || { echo -e "${RED}Failed to extract WebKit2GTK. The downloaded file might be corrupt.${RESET}" exit 1 } From 0f99b0a6e9ebc85f3e3be1b431e1b78cf7ed7fda Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 29 May 2024 01:26:48 +0530 Subject: [PATCH 502/864] chore:adding check for arch for linux installer --- docs/linux/installer.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 77330cb8..297477c4 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -124,6 +124,7 @@ check_ubuntu_version() { fi return 1 # Not Ubuntu 24.04 } + # Create Invocation Script Function # # Purpose: @@ -607,6 +608,20 @@ downloadLatestReleaseInfo() { grep -Po '"tag_name":\s*"prod-app-v\K[\d.]+(?=")' "$release_info_file" } +# Function to check if the architecture is 64-bit x86 +check_architecture() { + ARCHITECTURE=$(uname -m) + if [ "$ARCHITECTURE" != "x86_64" ]; then + local latestFileUrl + latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") + WGET_OPTS=$(configure_wget_options) + wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { + echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" + } + echo -e "${RED}This script can only be run on 64-bit x86 architecture.${RESET}" + exit 1 + fi +} # Download Latest Release Information Function # # Purpose: @@ -649,6 +664,7 @@ downloadLatestReleaseInfo() { downloadAndInstall(){ echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null + check_architecture CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" From 06ab606e4dbf84886606851c952fac2a9b6cc03b Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 29 May 2024 01:32:03 +0530 Subject: [PATCH 503/864] fix: mac worker failing --- .github/workflows/desktop-mac-m1-test-pull.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/desktop-mac-m1-test-pull.yml b/.github/workflows/desktop-mac-m1-test-pull.yml index 71bdd08c..21e29956 100644 --- a/.github/workflows/desktop-mac-m1-test-pull.yml +++ b/.github/workflows/desktop-mac-m1-test-pull.yml @@ -23,6 +23,8 @@ jobs: uses: dtolnay/rust-toolchain@stable - name: npm install ci deps + env: + GH_TOKEN: ${{ github.token }} run: npm ci - name: Download phoenix and build build phoenix dist-test From e8a51c108430237ff3160cbbb6d865eb45f662e7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 20:31:27 +0000 Subject: [PATCH 504/864] chore(deps): update dependency execa to v9.1.0 --- package-lock.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index c6c4f1fc..b1b573e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.7.2", + "version": "3.7.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.7.2", + "version": "3.7.3", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.14", @@ -506,10 +506,11 @@ "dev": true }, "node_modules/execa": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.0.0.tgz", - "integrity": "sha512-YqlYPdTp6UMdt0WEM8QKeBR8ORtgxWP7ZB5NB9AMlfGWg32Fg48j6uZdKfhG2o6cNJBIRPF0Ok93R0vY37oBWQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.1.0.tgz", + "integrity": "sha512-lSgHc4Elo2m6bUDhc3Hl/VxvUDJdQWI40RZ4KMY9bKRc+hgMOT7II/JjbNDhI8VnMtrCb7U/fhpJIkLORZozWw==", "dev": true, + "license": "MIT", "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.3", From 43bf9a193b75c41454b28366f009108d4796e182 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 29 May 2024 02:43:50 +0530 Subject: [PATCH 505/864] chore: update packages --- package-lock.json | 529 +++++++++++++++++++++++++++----- package.json | 4 +- src-build/downloadNodeBinary.js | 2 +- 3 files changed, 463 insertions(+), 72 deletions(-) diff --git a/package-lock.json b/package-lock.json index b1b573e6..254ef6e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,125 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "6.2.1" + "tar": "7.1.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" } }, "node_modules/@sec-ant/readable-stream": { @@ -415,12 +533,12 @@ } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", "dev": true, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/cliui": { @@ -499,6 +617,12 @@ "node": ">=0.4.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -591,6 +715,22 @@ } } }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -619,30 +759,6 @@ "node": ">=14.14" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -898,6 +1014,24 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/jackspeak": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz", + "integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -935,6 +1069,15 @@ "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", "dev": true }, + "node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -978,49 +1121,40 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", + "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", "dev": true, "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^7.0.4", + "rimraf": "^5.0.5" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" + "node": ">= 18" } }, "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", "dev": true, "bin": { - "mkdirp": "bin/cmd.js" + "mkdirp": "dist/cjs/src/bin.js" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/normalize-path": { @@ -1149,6 +1283,22 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -1238,6 +1388,70 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/rimraf": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", + "integrity": "sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg==", + "dev": true, + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -1324,6 +1538,57 @@ "node": ">=6" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -1336,6 +1601,28 @@ "node": ">=6" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-final-newline": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", @@ -1361,20 +1648,20 @@ } }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.1.0.tgz", + "integrity": "sha512-ENhg4W6BmjYxl8GTaE7/h99f0aXiSWv4kikRZ9n2/JRxypZniE84ILZqimAhxxX7Zb8Px6pFdheW3EeHfhnXQQ==", "dev": true, "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.0", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/to-regex-range": { @@ -1433,6 +1720,107 @@ "node": ">=6" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -1446,10 +1834,13 @@ "dev": true }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "engines": { + "node": ">=18" + } }, "node_modules/yargs": { "version": "13.3.2", diff --git a/package.json b/package.json index 39201bbc..ac2b99ce 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "6.2.1", + "tar": "7.1.0", "axios": "1.6.8", "axios-retry": "4.3.0" }, @@ -56,4 +56,4 @@ "branch": "tauri", "commit": "b5fe1f2f375bd6a4b035d828e36f339966b5e71b" } -} \ No newline at end of file +} diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index 42a20a30..fdc47ab5 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -1,5 +1,5 @@ import * as fs from "fs"; -import tar from "tar"; +import * as tar from "tar"; import * as path from "path"; import AdmZip from 'adm-zip'; import {fileURLToPath} from 'url'; From 27cf24937042054c7ad6089c7bf42eb80b436acc Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 29 May 2024 18:47:14 +0530 Subject: [PATCH 506/864] fix: icon not shown in task manager in ubuntu 24.04 --- docs/linux/installer.sh | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 297477c4..c08b3ba0 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -14,6 +14,12 @@ DESKTOP_APP_NAME="Phoenix Code" DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" SCRIPT_NAME="phcode" # Name of the script to invoke the binary BINARY_NAME="phoenix-code" +# STARTUP_WM_CLASS is set to the binary name and used as the application's class name in the desktop file. +# This class name helps the desktop environment manage application windows. If native libraries are missing +# and the application needs to be launched via a script instead of directly, this variable is updated +# accordingly before the desktop file is created. +STARTUP_WM_CLASS=$BINARY_NAME + declare -a MIME_TYPES=( "text/html" @@ -384,19 +390,20 @@ create_launch_script_with_gtk() { local binary_path="$1" local binary_name="$BINARY_NAME" - - local realBin="$binary_path/$binary_name.app" + local original_bin=$binary_name.app + local realBin="$binary_path/$original_bin" mv "$binary_path/$binary_name" "$realBin" echo "Creating a launch script for Phoenix Code with GTK libraries..." cat > "$binary_path/$binary_name" < Date: Tue, 28 May 2024 22:28:25 +0000 Subject: [PATCH 507/864] chore(deps): update dependency axios to v1.7.2 --- package-lock.json | 9 +++++---- package.json | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 254ef6e3..f95c3e07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.5.14", "adm-zip": "0.5.12", - "axios": "1.6.8", + "axios": "1.7.2", "axios-retry": "4.3.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -406,10 +406,11 @@ "dev": true }, "node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "dev": true, + "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", diff --git a/package.json b/package.json index ac2b99ce..eaeb87cd 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "7.1.0", - "axios": "1.6.8", + "axios": "1.7.2", "axios-retry": "4.3.0" }, "phoenixRepo": { From 8ff2ed4b32900c9d7c1e802d6aaf7b055c806479 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 03:27:38 +0000 Subject: [PATCH 508/864] chore(deps): update dependency tar to v7.2.0 --- package-lock.json | 9 +++++---- package.json | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index f95c3e07..1a6f3a1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.1.0" + "tar": "7.2.0" } }, "node_modules/@isaacs/cliui": { @@ -1649,10 +1649,11 @@ } }, "node_modules/tar": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.1.0.tgz", - "integrity": "sha512-ENhg4W6BmjYxl8GTaE7/h99f0aXiSWv4kikRZ9n2/JRxypZniE84ILZqimAhxxX7Zb8Px6pFdheW3EeHfhnXQQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.2.0.tgz", + "integrity": "sha512-hctwP0Nb4AB60bj8WQgRYaMOuJYRAPMGiQUAotms5igN8ppfQM+IvjQ5HcKu1MaZh2Wy2KWVTe563Yj8dfc14w==", "dev": true, + "license": "ISC", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", diff --git a/package.json b/package.json index eaeb87cd..575ba386 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.1.0", + "tar": "7.2.0", "axios": "1.7.2", "axios-retry": "4.3.0" }, From 2dcacca87bf7c9d2fd0a8314334c5c1f9f29abcc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 12:41:06 +0000 Subject: [PATCH 509/864] chore(deps): update dependency adm-zip to v0.5.13 --- package-lock.json | 11 ++++++----- package.json | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1a6f3a1f..f707fc5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.14", - "adm-zip": "0.5.12", + "adm-zip": "0.5.13", "axios": "1.7.2", "axios-retry": "4.3.0", "chalk": "^5.3.0", @@ -357,12 +357,13 @@ } }, "node_modules/adm-zip": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.12.tgz", - "integrity": "sha512-6TVU49mK6KZb4qG6xWaaM4C7sA/sgUMLy/JYMOzkcp3BvVLpW0fXDFQiIzAuxFCt/2+xD7fNIiPFAoLZPhVNLQ==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.13.tgz", + "integrity": "sha512-4U51tTl9J8UVEcuKGr6zRzY95tWoAa9l+ureGBNmsfleszjZblm5NyEEL/ZQxkhi86co5mZhSvL2T7gkZ6feYQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6.0" + "node": ">=12.0" } }, "node_modules/ansi-regex": { diff --git a/package.json b/package.json index 575ba386..f15a93f4 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ }, "devDependencies": { "@tauri-apps/cli": "1.5.14", - "adm-zip": "0.5.12", + "adm-zip": "0.5.13", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", From 17929a9448c3cec055b4dcaa94c046767aa3ff4e Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 3 Jun 2024 15:16:34 +0000 Subject: [PATCH 510/864] ci: update phcode version to 3.8.0 --- package.json | 6 +++--- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index f15a93f4..9afca259 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.7.3", + "version": "3.8.0", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "b5fe1f2f375bd6a4b035d828e36f339966b5e71b" + "commit": "db9a2f5dfc3c177cc106729396b5acebf7ad4f7a" } -} +} \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 41853092..45a444c3 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.7.3" +version = "3.8.0" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1bed8112..599667ed 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.7.3" + "version": "3.8.0" }, "tauri": { "allowlist": { From 3cbeb3d0a36167f7d41f98b095567014c4481651 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 3 Jun 2024 22:42:15 +0530 Subject: [PATCH 511/864] chore: update deps --- package-lock.json | 4 ++-- src-tauri/Cargo.lock | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f707fc5f..f9adbf7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.7.3", + "version": "3.8.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.7.3", + "version": "3.8.0", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.14", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 19cce25b..f906fa50 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2849,7 +2849,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.7.3" +version = "3.8.0" dependencies = [ "clipboard-files", "fix-path-env", From fdba29f378ab28bbe4b695fd06d51db05dd471f6 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 3 Jun 2024 22:44:53 +0530 Subject: [PATCH 512/864] fix: windown installer generation failure --- .../src/bundle/windows/nsis/installer.nsi | 89 +++++++++++++++---- 1 file changed, 74 insertions(+), 15 deletions(-) diff --git a/src-tauri/src/bundle/windows/nsis/installer.nsi b/src-tauri/src/bundle/windows/nsis/installer.nsi index 12deabfb..480cecb7 100644 --- a/src-tauri/src/bundle/windows/nsis/installer.nsi +++ b/src-tauri/src/bundle/windows/nsis/installer.nsi @@ -11,6 +11,8 @@ Unicode true !include x64.nsh !include WordFunc.nsh !include "StrFunc.nsh" +!include "Win\COM.nsh" +!include "Win\Propkey.nsh" ${StrCase} ${StrLoc} @@ -449,7 +451,7 @@ Section WebView2 !if "${INSTALLWEBVIEW2MODE}" == "downloadBootstrapper" Delete "$TEMP\MicrosoftEdgeWebview2Setup.exe" DetailPrint "$(webview2Downloading)" - nsis_tauri_utils::download "https://go.microsoft.com/fwlink/p/?LinkId=2124703" "$TEMP\MicrosoftEdgeWebview2Setup.exe" + NSISdl::download "https://go.microsoft.com/fwlink/p/?LinkId=2124703" "$TEMP\MicrosoftEdgeWebview2Setup.exe" Pop $0 ${If} $0 == 0 DetailPrint "$(webview2DownloadSuccess)" @@ -1148,12 +1150,12 @@ Section Install CreateDirectory "$INSTDIR\\{{this}}" {{/each}} {{#each resources}} - File /a "/oname={{this.[1]}}" "{{@key}}" + File /a "/oname={{this.[1]}}" "{{unescape-dollar-sign @key}}" {{/each}} ; Copy external binaries {{#each binaries}} - File /a "/oname={{this}}" "{{@key}}" + File /a "/oname={{this}}" "{{unescape-dollar-sign @key}}" {{/each}} ; Create uninstaller @@ -1199,7 +1201,6 @@ Section Install ; Auto close this page for passive mode ${IfThen} $PassiveMode == 1 ${|} SetAutoClose true ${|} - Call SetupPhcode SectionEnd @@ -1212,7 +1213,8 @@ Function .onInstSuccess check_r_flag: ${GetOptions} $CMDLINE "/R" $R0 IfErrors run_done 0 - Exec '"$INSTDIR\${MAINBINARYNAME}.exe"' + ${GetOptions} $CMDLINE "/ARGS" $R0 + Exec '"$INSTDIR\${MAINBINARYNAME}.exe" $R0' run_done: FunctionEnd @@ -1226,6 +1228,35 @@ Function un.onInit !insertmacro MUI_UNGETLANGUAGE FunctionEnd +!macro DeleteAppUserModelId + !insertmacro ComHlpr_CreateInProcInstance ${CLSID_DestinationList} ${IID_ICustomDestinationList} r1 "" + ${If} $1 P<> 0 + ${ICustomDestinationList::DeleteList} $1 '("${BUNDLEID}")' + ${IUnknown::Release} $1 "" + ${EndIf} + !insertmacro ComHlpr_CreateInProcInstance ${CLSID_ApplicationDestinations} ${IID_IApplicationDestinations} r1 "" + ${If} $1 P<> 0 + ${IApplicationDestinations::SetAppID} $1 '("${BUNDLEID}")i.r0' + ${If} $0 >= 0 + ${IApplicationDestinations::RemoveAllDestinations} $1 '' + ${EndIf} + ${IUnknown::Release} $1 "" + ${EndIf} +!macroend + +; From https://stackoverflow.com/a/42816728/16993372 +!macro UnpinShortcut shortcut + !insertmacro ComHlpr_CreateInProcInstance ${CLSID_StartMenuPin} ${IID_IStartMenuPinnedList} r0 "" + ${If} $0 P<> 0 + System::Call 'SHELL32::SHCreateItemFromParsingName(ws, p0, g "${IID_IShellItem}", *p0r1)' "${shortcut}" + ${If} $1 P<> 0 + ${IStartMenuPinnedList::RemoveFromList} $0 '(r1)' + ${IUnknown::Release} $1 "" + ${EndIf} + ${IUnknown::Release} $0 "" + ${EndIf} +!macroend + Function un.CleanPhcode ; NSIS Cleanup Script @@ -1668,15 +1699,17 @@ Section Uninstall ; Delete uninstaller Delete "$INSTDIR\uninstall.exe" - ${If} $DeleteAppDataCheckboxState == 1 - RMDir /R /REBOOTOK "$INSTDIR" - ${Else} - {{#each resources_ancestors}} - RMDir /REBOOTOK "$INSTDIR\\{{this}}" - {{/each}} - RMDir "$INSTDIR" - ${EndIf} + {{#each resources_ancestors}} + RMDir /REBOOTOK "$INSTDIR\\{{this}}" + {{/each}} + RMDir "$INSTDIR" + + !insertmacro DeleteAppUserModelId + !insertmacro UnpinShortcut "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" + !insertmacro UnpinShortcut "$DESKTOP\${MAINBINARYNAME}.lnk" + Call un.CleanPhcode + ; Remove start menu shortcut !insertmacro MUI_STARTMENU_GETFOLDER Application $AppStartMenuFolder Delete "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" RMDir "$SMPROGRAMS\$AppStartMenuFolder" @@ -1717,13 +1750,39 @@ Function SkipIfPassive ${IfThen} $PassiveMode == 1 ${|} Abort ${|} FunctionEnd +!macro SetLnkAppUserModelId shortcut + !insertmacro ComHlpr_CreateInProcInstance ${CLSID_ShellLink} ${IID_IShellLink} r0 "" + ${If} $0 P<> 0 + ${IUnknown::QueryInterface} $0 '("${IID_IPersistFile}",.r1)' + ${If} $1 P<> 0 + ${IPersistFile::Load} $1 '("${shortcut}", ${STGM_READWRITE})' + ${IUnknown::QueryInterface} $0 '("${IID_IPropertyStore}",.r2)' + ${If} $2 P<> 0 + System::Call 'Oleaut32::SysAllocString(w "${BUNDLEID}") i.r3' + System::Call '*${SYSSTRUCT_PROPERTYKEY}(${PKEY_AppUserModel_ID})p.r4' + System::Call '*${SYSSTRUCT_PROPVARIANT}(${VT_BSTR},,&i4 $3)p.r5' + ${IPropertyStore::SetValue} $2 '($4,$5)' + + System::Call 'Oleaut32::SysFreeString($3)' + System::Free $4 + System::Free $5 + ${IPropertyStore::Commit} $2 "" + ${IUnknown::Release} $2 "" + ${IPersistFile::Save} $1 '("${shortcut}",1)' + ${EndIf} + ${IUnknown::Release} $1 "" + ${EndIf} + ${IUnknown::Release} $0 "" + ${EndIf} +!macroend + Function CreateDesktopShortcut CreateShortcut "$DESKTOP\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" - ApplicationID::Set "$DESKTOP\${MAINBINARYNAME}.lnk" "${BUNDLEID}" + !insertmacro SetLnkAppUserModelId "$DESKTOP\${MAINBINARYNAME}.lnk" FunctionEnd Function CreateStartMenuShortcut CreateDirectory "$SMPROGRAMS\$AppStartMenuFolder" CreateShortcut "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "$INSTDIR\${MAINBINARYNAME}.exe" - ApplicationID::Set "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" "${BUNDLEID}" + !insertmacro SetLnkAppUserModelId "$SMPROGRAMS\$AppStartMenuFolder\${MAINBINARYNAME}.lnk" FunctionEnd From 02a6b3ace5a6f087b9946c9151ca6a8c6d6a0402 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 3 Jun 2024 17:35:39 +0000 Subject: [PATCH 513/864] ci: update phcode version to 3.8.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9afca259..5b9de6a4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.8.0", + "version": "3.8.1", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "db9a2f5dfc3c177cc106729396b5acebf7ad4f7a" + "commit": "c73c969d1ffc612f0c51cf9e92386dfefb9ae21d" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 45a444c3..1bda063a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.8.0" +version = "3.8.1" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 599667ed..85fdb31d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.8.0" + "version": "3.8.1" }, "tauri": { "allowlist": { From 9cbdc652049aacba95ef5ebf3ee697389fc3fd2e Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 4 Jun 2024 03:32:33 +0000 Subject: [PATCH 514/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index c273028e..fa0e5dfd 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,19 +1,19 @@ { - "version": "3.7.2", - "notes": "Adds support for node extensions", - "pub_date": "2024-05-05T04:05:08.711Z", + "version": "3.8.1", + "notes": "New non-intrusive updates test release", + "pub_date": "2024-06-03T18:05:54.440Z", "platforms": { - "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlGNnRic0dYQjg2a0I2K2o2TDQ4RjBpbWl2VU5Db3FYOU1HbW9TdzhwQy9EYis3dGM1T3lPZnB1dVVMOExPRU9WMjRYMW1NRHJ6enN0N0J2NSt5NEFzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0ODQ2MjA2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjcuMl94NjQtc2V0dXAubnNpcy56aXAKdCtmQ0RSVWQvVUhWZGczM0o4QjFUbHJIMk9ocUZxZWltYVpBaW8yWTJPd0JqTVNCSWhsbnVXZXEvVFRHd2hEcE9oRzdTeFZtcklaVzNTemlBZTMyQ0E9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.7.2/Phoenix.Code.Experimental.Build_3.7.2_x64-setup.nsis.zip" - }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnM5OFRnbGZ5djhQS00veFl3SnlObXdzeEljOWFiOUxRSjNZUkQ2QktLTDBsY3FYbmhyM21yVndoZTc2d1BoVVJaMzNNUnd1cFMxV2U2Q09ueWpVWmdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0ODgxMjMwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnRWSzBNNjJHWDJrNnd2bGRMMVNHKzBPcVFId0cwdEd3eHpnRVFCLzhWR3lzS1JSeDFYSUFzQ3BxM0FVZXd6Y2x6SVdTa21YcG02NU9DVEZKalQ4c0JBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.7.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9obFBqeWlVRDc3UDNlRVlvbkw1UWs0NW9NTnlQSHI1bExBTHV1OU02T1NiVzd5SnB0bmxDYlFoVzdCUTZwUy9hdWZCZ3hISFNIYjNXNG5IU2ErcHdJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE3NDM3MzM0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnVLbTlXTkNmeTAvOWQvcWhrS1VRUldVVXJXbjVuTmxVL1dDQUlWQTI4NmcwRXltblNqWFJhTEJGbWpRTFJFQjRHM0ZYblZPdjFrQzkrdU1LQVdkbkJ3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + }, + "windows-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlOR1UxcjdqY0hGK3J1VHc4NmQ2ODUyNVo0dmJjQm5YQitTNnNOOTRWaGJPbFNWUmF6QXlncE1QS2VhMGk5dzUrZit1aHFIcHRya09pdXNJV005dEE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE3NDM3NDU3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjguMV94NjQtc2V0dXAubnNpcy56aXAKMzVNdHJTRTlvU1lVRVJKeFJacnFjNUFOY3JPaEJsWUIxb2N3cUxQc016V3pBZFlUN3RSd3l3aDF3NndPSlFZMXNhZWNrZi9mbW93blpLZEJWTlBHQ2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.1/Phoenix.Code.Experimental.Build_3.8.1_x64-setup.nsis.zip" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtKSHJDRVpSSDJNNUV3UGkzTU0wZ1FVUGU5N1Exc3k4Q0M1N3pSc3o0a3NYTVpTYWVxUkZkMUdhcW1HbmN6SXRlNklPUC9WUWN6NG0weFhTZjN5dkFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE0ODgxOTAwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmR5RlZDYUY4S1RRajJvYmQ3UnRrRkxoUWJtQ29RZk44TkVBNzZLcER5QVRUeE9IZTVJTGZUc2lKQnNVWDIzRENJSlBjTWRkbEROdU9rVk1ya09nVEJRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.7.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmg5ZG9UV0JSci9WNEl2WWJTcFJvQ3YwVnU2cTZDR1kzOTNDT012a3BUd1E5Y0lpdWlVbFk1L1czcDQ2Vnl1c2FsQmxtcUxGWFdPa1RqTDMxWDRiRXdZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE3NDM3OTMxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Ck80VkQ2Q3Y4REtSSzZRT0k5bTBHNk81T2pTNGZUdmxIUFpYYXJ1VDdQV1k4WHBwZUVmU3dFOWtzdHRmeWlVQzlVMG9pb250c3cvalFxUFZpMDVjMkJRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 8df6c244dfa30f54854345849a282fae9e753f07 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 22:30:02 +0000 Subject: [PATCH 515/864] fix(deps): update rust crate tauri to v1.6.8 --- src-tauri/Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f906fa50..005c02d8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2849,7 +2849,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.8.0" +version = "3.8.1" dependencies = [ "clipboard-files", "fix-path-env", @@ -3899,9 +3899,9 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.6.7" +version = "1.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c7177b6be45bbb875aa239578f5adc982a1b3d5ea5b315ccd100aeb0043374" +checksum = "77567d2b3b74de4588d544147142d02297f3eaa171a25a065252141d8597a516" dependencies = [ "anyhow", "base64 0.21.7", From 6a145a7c0456c72d2c0f0e7b57050eff071f9378 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 12:02:17 +0000 Subject: [PATCH 516/864] chore(deps): update dependency axios-retry to v4.4.0 --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9adbf7d..d4b16289 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "phoenix-code-ide", - "version": "3.8.0", + "version": "3.8.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.8.0", + "version": "3.8.1", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.14", "adm-zip": "0.5.13", "axios": "1.7.2", - "axios-retry": "4.3.0", + "axios-retry": "4.4.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", @@ -419,9 +419,9 @@ } }, "node_modules/axios-retry": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.3.0.tgz", - "integrity": "sha512-vUAQ3bi02Q++b8aAn3fuM03qRKFLZ6BPcqSVsOpgWeww2jrYFpu9SKb9VuctvxrJuRCWM/voDuuRAD7v3A1G5g==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.4.0.tgz", + "integrity": "sha512-yewTKjzl6jSgc+2M7FCJ3LxRGgL1iiXHcj+E6h6xie6H1mTHr7yqaUroWIvVXG1UKSPwGDXxV05YxtGvrD6Paw==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 5b9de6a4..e3d126f9 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "shx": "^0.3.4", "tar": "7.2.0", "axios": "1.7.2", - "axios-retry": "4.3.0" + "axios-retry": "4.4.0" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From d58b0f3a3ebecb0c54b7371e467b7d737af565fe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 21:33:03 +0000 Subject: [PATCH 517/864] chore(deps): update dependency adm-zip to v0.5.14 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index d4b16289..b4c9a7cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.14", - "adm-zip": "0.5.13", + "adm-zip": "0.5.14", "axios": "1.7.2", "axios-retry": "4.4.0", "chalk": "^5.3.0", @@ -357,9 +357,9 @@ } }, "node_modules/adm-zip": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.13.tgz", - "integrity": "sha512-4U51tTl9J8UVEcuKGr6zRzY95tWoAa9l+ureGBNmsfleszjZblm5NyEEL/ZQxkhi86co5mZhSvL2T7gkZ6feYQ==", + "version": "0.5.14", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.14.tgz", + "integrity": "sha512-DnyqqifT4Jrcvb8USYjp6FHtBpEIz1mnXu6pTRHZ0RL69LbQYiO+0lDFg5+OKA7U29oWSs3a/i8fhn8ZcceIWg==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index e3d126f9..30917b38 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ }, "devDependencies": { "@tauri-apps/cli": "1.5.14", - "adm-zip": "0.5.13", + "adm-zip": "0.5.14", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", From ba343526b76f7f08c641ee5fb2ba7ace175d1de2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 6 Jun 2024 18:49:42 +0000 Subject: [PATCH 518/864] chore(deps): update dependency execa to v9.2.0 --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index b4c9a7cc..286b59e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -632,9 +632,9 @@ "dev": true }, "node_modules/execa": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.1.0.tgz", - "integrity": "sha512-lSgHc4Elo2m6bUDhc3Hl/VxvUDJdQWI40RZ4KMY9bKRc+hgMOT7II/JjbNDhI8VnMtrCb7U/fhpJIkLORZozWw==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.2.0.tgz", + "integrity": "sha512-vpOyYg7UAVKLAWWtRS2gAdgkT7oJbCn0me3gmUmxZih4kd3MF/oo8kNTBTIbkO3yuuF5uB4ZCZfn8BOolITYhg==", "dev": true, "license": "MIT", "dependencies": { @@ -652,7 +652,7 @@ "yoctocolors": "^2.0.0" }, "engines": { - "node": ">=18" + "node": "^18.19.0 || >=20.5.0" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" From 92cd268402d8f079a0c451885d1657283878e36d Mon Sep 17 00:00:00 2001 From: phoenixide Date: Tue, 11 Jun 2024 05:59:58 +0000 Subject: [PATCH 519/864] ci: update phcode version to 3.8.2 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 30917b38..2f03efcf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.8.1", + "version": "3.8.2", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "c73c969d1ffc612f0c51cf9e92386dfefb9ae21d" + "commit": "e3f35695abf634a5416256cb71e3ea2a41efda99" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1bda063a..447735c8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.8.1" +version = "3.8.2" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 85fdb31d..03f465e7 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.8.1" + "version": "3.8.2" }, "tauri": { "allowlist": { From eed6ea633b55256ae9ddc33372c1a94e08b78b62 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 9 Jun 2024 12:46:21 +0000 Subject: [PATCH 520/864] fix(deps): update rust crate regex to v1.10.5 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 005c02d8..2a359bfc 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3162,9 +3162,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", From 3b38cde46fc127b72cf3928a28f79b4f3e9d9620 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 11 Jun 2024 07:39:52 +0000 Subject: [PATCH 521/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index fa0e5dfd..af52c868 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,19 +1,19 @@ { - "version": "3.8.1", - "notes": "New non-intrusive updates test release", - "pub_date": "2024-06-03T18:05:54.440Z", + "version": "3.8.2", + "notes": "Test release with eslint support", + "pub_date": "2024-06-11T06:28:09.503Z", "platforms": { - "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm9obFBqeWlVRDc3UDNlRVlvbkw1UWs0NW9NTnlQSHI1bExBTHV1OU02T1NiVzd5SnB0bmxDYlFoVzdCUTZwUy9hdWZCZ3hISFNIYjNXNG5IU2ErcHdJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE3NDM3MzM0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnVLbTlXTkNmeTAvOWQvcWhrS1VRUldVVXJXbjVuTmxVL1dDQUlWQTI4NmcwRXltblNqWFJhTEJGbWpRTFJFQjRHM0ZYblZPdjFrQzkrdU1LQVdkbkJ3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" - }, "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmlOR1UxcjdqY0hGK3J1VHc4NmQ2ODUyNVo0dmJjQm5YQitTNnNOOTRWaGJPbFNWUmF6QXlncE1QS2VhMGk5dzUrZit1aHFIcHRya09pdXNJV005dEE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE3NDM3NDU3CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjguMV94NjQtc2V0dXAubnNpcy56aXAKMzVNdHJTRTlvU1lVRVJKeFJacnFjNUFOY3JPaEJsWUIxb2N3cUxQc016V3pBZFlUN3RSd3l3aDF3NndPSlFZMXNhZWNrZi9mbW93blpLZEJWTlBHQ2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.1/Phoenix.Code.Experimental.Build_3.8.1_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRuSWwxeXM0ODg0cUxyTVRGTHhtT1hTQkU2dld2K3ZSWWV2aVpta3RzeXBHdUxSU3NDTTZpdUZtQ3ZYRzZMbUxMV1YvT3ErSWpVYjJqMGh1b2lYZ2cwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE4MDg2NTUyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjguMl94NjQtc2V0dXAubnNpcy56aXAKb1lpais1bnIrZnEzZUlMR294ZW5vZnZLTjE5OFlpcTFRQ3hTaFludngrNkFaUlUvWU9lZXgzSjlRTDQyT0NCc0ZXdGl3REIxV0E5dExUS2h3OE9nQ1E9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.2/Phoenix.Code.Experimental.Build_3.8.2_x64-setup.nsis.zip" + }, + "darwin-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmh6TTE2QjZNbEFyZk5BQ0xsSFdHVllpR2tRSjRIM2RwUkhybjk0YUtPOUxOc1VhMUxMUHZlbk91dURnWk0wN2JEWjlsaUpIWUFXSkVKS0NDRzB5MFFzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE4MDg2NjU2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Ck5oZ0tBaEMxOXk4Q0NzSFRnaiszc3lUOHZZQUZnSzJvYmZaRTVtZVZXQzFyWDNzUkpFT1RnZjJFQ0Zzb1ZHTndwVHpKQWt2TUF3SzJDOFEyUmI3OEFnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmg5ZG9UV0JSci9WNEl2WWJTcFJvQ3YwVnU2cTZDR1kzOTNDT012a3BUd1E5Y0lpdWlVbFk1L1czcDQ2Vnl1c2FsQmxtcUxGWFdPa1RqTDMxWDRiRXdZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE3NDM3OTMxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Ck80VkQ2Q3Y4REtSSzZRT0k5bTBHNk81T2pTNGZUdmxIUFpYYXJ1VDdQV1k4WHBwZUVmU3dFOWtzdHRmeWlVQzlVMG9pb250c3cvalFxUFZpMDVjMkJRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtYaEoramFUZ2VIcU1tREdwT1JXWk9wRGIxZG8rYmJueHZZbTlnUVBrVGxxU05aTExSRzFUR3hOK3RvdDVMQ3piQlI2QzBuY3Zoc092OXhtT2xpWEFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE4MDg3MjcwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnJDNjh5SmI0NDR0a2NqWXNmZGo4QmNlZnZWMVRjRFo5OE5rK1pPL01veHdKVXltdCtrYm9sYXI2OStuQlNkODY5MjdVbC9xQklMYjd5eld1bG1KYUNRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 9dc08c6d16316d797fcfe154030944260dcfc4e5 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 14 Jun 2024 06:11:49 +0000 Subject: [PATCH 522/864] ci: update phcode version to 3.8.3 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 2f03efcf..34a34c59 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.8.2", + "version": "3.8.3", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "e3f35695abf634a5416256cb71e3ea2a41efda99" + "commit": "3c1c45b38b2514b8a52211cfe59fff5dc230c5e6" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 447735c8..272d9d6a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.8.2" +version = "3.8.3" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 03f465e7..01724609 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.8.2" + "version": "3.8.3" }, "tauri": { "allowlist": { From 685db8953fa3a4ba5942505c88af1d2da995f856 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 07:51:40 +0000 Subject: [PATCH 523/864] fix(deps): update rust crate trash to v5 --- src-tauri/Cargo.lock | 56 +++++++++++++++++++++++++++++++++++++------- src-tauri/Cargo.toml | 2 +- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2a359bfc..01e543bf 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -363,6 +363,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2 0.5.2", +] + [[package]] name = "blocking" version = "1.5.1" @@ -2481,9 +2490,9 @@ dependencies = [ [[package]] name = "objc-sys" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c71324e4180d0899963fc83d9d241ac39e699609fc1025a850aadac8257459" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" [[package]] name = "objc2" @@ -2492,7 +2501,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" dependencies = [ "objc-sys", - "objc2-encode", + "objc2-encode 3.0.0", +] + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode 4.0.3", ] [[package]] @@ -2501,6 +2520,24 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.5.0", + "block2", + "libc", + "objc2 0.5.2", +] + [[package]] name = "objc_exception" version = "0.1.2" @@ -2849,7 +2886,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.8.1" +version = "3.8.3" dependencies = [ "clipboard-files", "fix-path-env", @@ -4029,7 +4066,7 @@ dependencies = [ "dirs", "interprocess", "log", - "objc2", + "objc2 0.4.1", "once_cell", "tauri-utils", "windows-sys 0.48.0", @@ -4482,17 +4519,18 @@ dependencies = [ [[package]] name = "trash" -version = "4.1.1" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c254b119cf49bdde3dfef21b1dc492dc8026b75566ca24aa77993eccd7cbc1b5" +checksum = "8d8fbfb70b1fad5c0b788f9b2e1bf4d04e5ac6efa828f1ed9ee462c50ff9cf05" dependencies = [ "chrono", "libc", "log", - "objc", + "objc2 0.5.2", + "objc2-foundation", "once_cell", "scopeguard", - "url", + "urlencoding", "windows 0.56.0", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 272d9d6a..9a0dfd2d 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -19,7 +19,7 @@ once_cell = "1.19.0" percent-encoding = "2.3.1" regex = "1.10.4" clipboard-files = "0.1.1" -trash = "4" +trash = "5" serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3.9", features = ["fileapi"] } From 83fe2b486f06bdeef9dc11c3fe0883059b08e398 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 21 Jun 2024 12:48:48 +0530 Subject: [PATCH 524/864] chore: add support for drag and drop overlay window --- src-tauri/tauri.conf.json | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 01724609..5ea33519 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -469,7 +469,16 @@ "label": "healthData", "title": "Health data window", "url": "http://localhost:8000/src/desktop-metrics.html", - "visible": false + "visible": false, + "fileDropEnabled": false + }, + { + "label": "fileDrop", + "title": "Drop To Open Files", + "url": "http://localhost:8000/src/drop-files.html", + "visible": false, + "fileDropEnabled": true, + "decorations": false } ] } From bb94426f12e9af26f0e6a734a137080e12f2fea5 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 21 Jun 2024 13:04:46 +0530 Subject: [PATCH 525/864] build: patch drop-files.html url at build --- src-build/ci-createDistReleaseConfig.js | 2 ++ src-build/createDistBundleReleaseConfig.js | 2 ++ src-build/createDistReleaseConfig.js | 2 ++ src-build/createDistTestReleaseConfig.js | 2 ++ src-build/createSrcReleaseConfig.js | 2 ++ 5 files changed, 10 insertions(+) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index d5fbc9cd..9a39ca37 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -89,8 +89,10 @@ async function ciCreateDistReleaseConfig() { configJson.tauri.windows[0].title = configJson.package.productName; if(os.platform() === 'win32'){ configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; } if(os.platform() === 'darwin'){ // inject macos icons diff --git a/src-build/createDistBundleReleaseConfig.js b/src-build/createDistBundleReleaseConfig.js index 81ff86e8..8b84e252 100644 --- a/src-build/createDistBundleReleaseConfig.js +++ b/src-build/createDistBundleReleaseConfig.js @@ -24,8 +24,10 @@ async function createDistReleaseConfig() { const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; } if(os.platform() === 'darwin'){ // inject macos icons diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js index f94e66c4..2c674386 100644 --- a/src-build/createDistReleaseConfig.js +++ b/src-build/createDistReleaseConfig.js @@ -23,8 +23,10 @@ async function createDistReleaseConfig() { const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; } if(os.platform() === 'darwin'){ // inject macos icons diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index 3693998b..b8dbfcaa 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -25,8 +25,10 @@ async function createDistTestReleaseConfig() { const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; } if(os.platform() === 'darwin'){ // inject macos icons diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js index 64c4b7c7..60128bcb 100644 --- a/src-build/createSrcReleaseConfig.js +++ b/src-build/createSrcReleaseConfig.js @@ -23,8 +23,10 @@ async function createSrcReleaseConfig() { const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; } if(os.platform() === 'darwin'){ // inject macos icons From 591256d8cf219089fcc54cfaa709c7e1f45ed948 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 21 Jun 2024 14:18:50 +0530 Subject: [PATCH 526/864] fix: tauri api not available in release builds drop handler window --- src-tauri/tauri.conf.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 5ea33519..0af866c2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -298,6 +298,7 @@ "windows": [ "main", "updater", + "fileDrop", "phcode-1", "phcode-2", "phcode-3", @@ -370,6 +371,7 @@ "windows": [ "main", "updater", + "fileDrop", "phcode-1", "phcode-2", "phcode-3", From 21846cb85e6961d289b54e10c475b9f73ce41548 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 04:20:19 +0000 Subject: [PATCH 527/864] chore(deps): update dependency tar to v7.4.0 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 286b59e3..a5721b66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.8.1", + "version": "3.8.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.8.1", + "version": "3.8.3", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.14", @@ -18,7 +18,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.2.0" + "tar": "7.4.0" } }, "node_modules/@isaacs/cliui": { @@ -1650,15 +1650,15 @@ } }, "node_modules/tar": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.2.0.tgz", - "integrity": "sha512-hctwP0Nb4AB60bj8WQgRYaMOuJYRAPMGiQUAotms5igN8ppfQM+IvjQ5HcKu1MaZh2Wy2KWVTe563Yj8dfc14w==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.0.tgz", + "integrity": "sha512-XQs0S8fuAkQWuqhDeCdMlJXDX80D7EOVLDPVFkna9yQfzS+PHKgfxcei0jf6/+QAWcjqrnC8uM3fSAnrQl+XYg==", "dev": true, "license": "ISC", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", - "minipass": "^7.1.0", + "minipass": "^7.1.2", "minizlib": "^3.0.1", "mkdirp": "^3.0.1", "yallist": "^5.0.0" diff --git a/package.json b/package.json index 34a34c59..0531e469 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.2.0", + "tar": "7.4.0", "axios": "1.7.2", "axios-retry": "4.4.0" }, From 848e7e42c591e706a18cd32546ba6d0fedf7d061 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 21 Jun 2024 17:41:39 +0530 Subject: [PATCH 528/864] fix: pipeline tests --- src-build/createDistTestReleaseConfig.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index b8dbfcaa..1bdbb77f 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -25,10 +25,10 @@ async function createDistTestReleaseConfig() { const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; - configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; + // for test windows, desktop-metrics.html isn't needed } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; - configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; + // for test windows, desktop-metrics.html isn't needed } if(os.platform() === 'darwin'){ // inject macos icons From a8bd1deedd8f171629899696d63d4def2a94c64a Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 21 Jun 2024 18:19:28 +0530 Subject: [PATCH 529/864] build: remove file drop and metrics hidden windows in desktop test runner --- src-build/createDistTestReleaseConfig.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js index 1bdbb77f..4b449427 100644 --- a/src-build/createDistTestReleaseConfig.js +++ b/src-build/createDistTestReleaseConfig.js @@ -25,11 +25,11 @@ async function createDistTestReleaseConfig() { const phoenixVersion = configJson.package.version; if(os.platform() === 'win32'){ configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; - // for test windows, desktop-metrics.html isn't needed } else { configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; - // for test windows, desktop-metrics.html isn't needed } + // for tests we only need the main window. other windows seems to be breaking tests in github actions. + configJson.tauri.windows = [configJson.tauri.windows[0]]; if(os.platform() === 'darwin'){ // inject macos icons configJson.tauri.bundle.icon = [ From 545a4c957abb9149deb8cba0f91b1d159146e98e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 22 Jun 2024 03:55:55 +0000 Subject: [PATCH 530/864] fix(deps): update rust crate lazy_static to v1.5.0 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 01e543bf..baa008ac 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2106,9 +2106,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" From 68d28dca8dbf09732a342db9b3f97a493083644b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 21 Jun 2024 19:41:36 +0000 Subject: [PATCH 531/864] chore(deps): update dependency execa to v9.3.0 --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a5721b66..c7db2b88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -632,9 +632,9 @@ "dev": true }, "node_modules/execa": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.2.0.tgz", - "integrity": "sha512-vpOyYg7UAVKLAWWtRS2gAdgkT7oJbCn0me3gmUmxZih4kd3MF/oo8kNTBTIbkO3yuuF5uB4ZCZfn8BOolITYhg==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.0.tgz", + "integrity": "sha512-l6JFbqnHEadBoVAVpN5dl2yCyfX28WoBAGaoQcNmLLSedOxTxcn2Qa83s8I/PA5i56vWru2OHOtrwF7Om2vqlg==", "dev": true, "license": "MIT", "dependencies": { From 06636551fe41d64bfa6a29d5c75dfa2b06ae9127 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 22 Jun 2024 17:13:11 +0000 Subject: [PATCH 532/864] ci: update phcode version to 3.8.4 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 0531e469..c3497549 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.8.3", + "version": "3.8.4", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "3c1c45b38b2514b8a52211cfe59fff5dc230c5e6" + "commit": "37a94158070833628caf570f55f378b2f4e177d1" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9a0dfd2d..6f821cbf 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.8.3" +version = "3.8.4" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 0af866c2..211dd05e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.8.3" + "version": "3.8.4" }, "tauri": { "allowlist": { From 40e88c21b53d343b3b74a3a5843f9dd81f2c2db4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 22 Jun 2024 20:24:01 +0000 Subject: [PATCH 533/864] chore(deps): update dependency axios-retry to v4.4.1 --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index c7db2b88..7bbe87fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "phoenix-code-ide", - "version": "3.8.3", + "version": "3.8.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.8.3", + "version": "3.8.4", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.14", "adm-zip": "0.5.14", "axios": "1.7.2", - "axios-retry": "4.4.0", + "axios-retry": "4.4.1", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", @@ -419,9 +419,9 @@ } }, "node_modules/axios-retry": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.4.0.tgz", - "integrity": "sha512-yewTKjzl6jSgc+2M7FCJ3LxRGgL1iiXHcj+E6h6xie6H1mTHr7yqaUroWIvVXG1UKSPwGDXxV05YxtGvrD6Paw==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.4.1.tgz", + "integrity": "sha512-JGzNoglDHtHWIEvvAampB0P7jxQ/sT4COmW0FgSQkVg6o4KqNjNMBI6uFVOq517hkw/OAYYAG08ADtBlV8lvmQ==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index c3497549..f47c8986 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "shx": "^0.3.4", "tar": "7.4.0", "axios": "1.7.2", - "axios-retry": "4.4.0" + "axios-retry": "4.4.1" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From 3916a3f0646f1d2bad86bd68d66bca1f18f2c18e Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 24 Jun 2024 11:11:08 +0000 Subject: [PATCH 534/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index af52c868..3edf50c2 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,19 +1,19 @@ { - "version": "3.8.2", - "notes": "Test release with eslint support", - "pub_date": "2024-06-11T06:28:09.503Z", + "version": "3.8.4", + "notes": "Experimental build. not to be used.", + "pub_date": "2024-06-22T17:40:08.687Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRuSWwxeXM0ODg0cUxyTVRGTHhtT1hTQkU2dld2K3ZSWWV2aVpta3RzeXBHdUxSU3NDTTZpdUZtQ3ZYRzZMbUxMV1YvT3ErSWpVYjJqMGh1b2lYZ2cwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE4MDg2NTUyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjguMl94NjQtc2V0dXAubnNpcy56aXAKb1lpais1bnIrZnEzZUlMR294ZW5vZnZLTjE5OFlpcTFRQ3hTaFludngrNkFaUlUvWU9lZXgzSjlRTDQyT0NCc0ZXdGl3REIxV0E5dExUS2h3OE9nQ1E9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.2/Phoenix.Code.Experimental.Build_3.8.2_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnQyUEprczJ6RUhxcXUrMmJGYVZsai8wNit0aWZDWnMweDdtaGx5ZVpVK2w5MGFsNnNkckZXZ0pNSDJVODU0cWt3d1FlY1h2bWJIZWdZQ3NFZUtHcUFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5MDc3Mjk1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjguNF94NjQtc2V0dXAubnNpcy56aXAKSFZrc0FxWjA1MytjWDZTays3cGJVUkV5TjZtaU5FSzc0aTFPazRFWm5Iaml4VmdSR2lTd0pvd2xRSmV0cy85VDVJOVpqbmdsYzhubEdSK0UrVkxaQmc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.4/Phoenix.Code.Experimental.Build_3.8.4_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmh6TTE2QjZNbEFyZk5BQ0xsSFdHVllpR2tRSjRIM2RwUkhybjk0YUtPOUxOc1VhMUxMUHZlbk91dURnWk0wN2JEWjlsaUpIWUFXSkVKS0NDRzB5MFFzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE4MDg2NjU2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Ck5oZ0tBaEMxOXk4Q0NzSFRnaiszc3lUOHZZQUZnSzJvYmZaRTVtZVZXQzFyWDNzUkpFT1RnZjJFQ0Zzb1ZHTndwVHpKQWt2TUF3SzJDOFEyUmI3OEFnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.2/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1ZdWlBUGFxOEcyVFhqMm11akpvMUVDNXZ2SE96YkdpU0h3UnFLNDNhMnZhSHZObkl2S2k4b2ZHdHMzcVAzWEFvcGdzajFNdWlOOHRsTFJrSUxEQkFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5MDc3NTM2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CkxsaVdzM2N0UFg0ajBZUmhKL3RCb2NjcDVOdmdPQXl2ZzhqOW03R09kZXlEaFVmbDg1eHdVbzdYRy9VQ2Z2T2tIckorM2NmY3l5RE5ZKytsbHh5bUJRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.4/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtYaEoramFUZ2VIcU1tREdwT1JXWk9wRGIxZG8rYmJueHZZbTlnUVBrVGxxU05aTExSRzFUR3hOK3RvdDVMQ3piQlI2QzBuY3Zoc092OXhtT2xpWEFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE4MDg3MjcwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnJDNjh5SmI0NDR0a2NqWXNmZGo4QmNlZnZWMVRjRFo5OE5rK1pPL01veHdKVXltdCtrYm9sYXI2OStuQlNkODY5MjdVbC9xQklMYjd5eld1bG1KYUNRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.2/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZNZ0ZreDFXOEZJbEp1dWdoWkVlKzREK3VrMEZqQ3pWVDdEM3pIUDl5aGZQUXEzVFZvVXQ2V3VNekp6dmFDUGtsRERpS0JDRVlCRnFVVkMxbWV6V1FVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5MDc3OTkzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cmo5OEYzV2hVZTQ0cUVGa3VHL0Vnai9rdmp3S1NCRDVaUDNOSHJPdUlPRHVaWDZlc2R6c3ZjS24zNHRaalVudXZ4MlBGTTlMampWdy9MU2pTa3lvbUFBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.4/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From ece6b7af273333967103b2eec6dddf60f47bf2b2 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 27 Jun 2024 05:30:10 +0000 Subject: [PATCH 535/864] ci: update phcode version to 3.8.5 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index f47c8986..b2f51601 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.8.4", + "version": "3.8.5", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "37a94158070833628caf570f55f378b2f4e177d1" + "commit": "023a834fc66dd45ab3ea17f815697be938af17c9" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6f821cbf..2e80505c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.8.4" +version = "3.8.5" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 211dd05e..68004e67 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.8.4" + "version": "3.8.5" }, "tauri": { "allowlist": { From 5e63843878e8bbf33b35a84466e5b333b5ca34db Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 27 Jun 2024 07:03:33 +0000 Subject: [PATCH 536/864] ci: update phcode version to 3.8.6 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b2f51601..f776ad4a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.8.5", + "version": "3.8.6", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "023a834fc66dd45ab3ea17f815697be938af17c9" + "commit": "646f5b08d93e38930704c6caf2114a6e886caa5f" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 2e80505c..255f9813 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.8.5" +version = "3.8.6" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 68004e67..fa4270a0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.8.5" + "version": "3.8.6" }, "tauri": { "allowlist": { From 4f73f9150fbf9423c2d12de0b1b35e22ee7c869c Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 27 Jun 2024 08:32:19 +0000 Subject: [PATCH 537/864] ci: update phcode version to 3.8.8 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index f776ad4a..14241c87 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.8.6", + "version": "3.8.8", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "646f5b08d93e38930704c6caf2114a6e886caa5f" + "commit": "9b837851db997b680d65ae368c3cfdb44200db2c" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 255f9813..bff5f1e6 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.8.6" +version = "3.8.8" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index fa4270a0..43183fd2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.8.6" + "version": "3.8.8" }, "tauri": { "allowlist": { From 6d81c98199600c4f58e91347fcc8265ab60f2a0e Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 27 Jun 2024 13:22:07 +0000 Subject: [PATCH 538/864] ci: tauri release update notification json --- docs/install.json | 6 +++--- docs/tauri/update-latest-stable-prod.json | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/install.json b/docs/install.json index c4d82568..842da500 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,7 +1,7 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_3.7.3_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_3.7.3_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_3.7.3_x64.dmg" + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_x64.dmg" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 5bf9bcee..6e87f6c5 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,19 +1,19 @@ { - "version": "3.7.3", - "notes": "May release(3.7) of Phoenix Code is now available.\r\n\r\nThis month's release is all about Live previews and the little things that make your work just a bit easier. We've also addressed numerous feature requests and UX bug reports, along with improving app UX and stability.\r\n\r\n#### Live CSS Class and Style Code Hints\r\n\r\nInteractively edit CSS styles and classes using the up/down arrow keys in code hints. This provides an instant boost to your HTML and CSS workflows.\r\n\r\n![classLiveHints](https://github.com/phcode-dev/phoenix/assets/5336369/502c8751-5269-4c34-9178-5ad08f8ad837)\r\n\r\n#### CSS/HTML Code Hints improvements\r\n\r\nImproved relevance of suggestions in CSS and HTML code hints. For E.g., typing `b` in a CSS file will prioritize `background-color`. Typing `between` will bring up relevant CSS property-value combinations like `align-content: space-between;` (see image below), so you don't have to remember which value is under which CSS property.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/2a9f8809-de19-43cf-bdcd-d1a5def2e080)\r\n\r\n#### Move to trash/bin when deleting files\r\n\r\nDeleting files from the files panel in desktop apps will move the file/folder to trash/recycle bin instead of permanently deleting it.\r\n\r\n#### UX Improvements\r\n\r\n* Deleting the `Phoenix Code` folder in user `Documents` directory is now supported in desktop apps.\r\n* Increased stability and app startup experience.\r\n* `Copy Error Message` button is now available in the problems panel.\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/95c59e71-5ce8-4697-963e-0fa567062ab0)\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.", - "pub_date": "2024-05-25T13:48:47.470Z", + "version": "3.8.8", + "notes": "June release(3.8) of Phoenix Code is now available.\r\n\r\nThis month's release is all about `Drag and Drop`, `HTML assistance` and `ESLint`. We've also addressed numerous feature requests and bug reports, along with improving app UX and stability.\r\n\r\n#### Drag and Drop Files and Folders in Desktop Apps - Experimental\r\n\r\nDrag files from Explorer (Windows) or Finder (Mac) and drop them into Phoenix Code to open individual files. Drop a folder to open it as a project.\r\n\r\n> Note: This feature is currently disabled on Linux due to UI issues in some Linux distributions. To enable it, select menu\r\n> `Debug -> Experimental Features -> Drag And Drop Files.`\r\n\r\n> This feature is not available in the browser version @ phcode.dev\r\n\r\n![drag and drop](https://github.com/phcode-dev/phoenix/assets/5336369/ddd96ff7-bc99-46a6-a62d-6f6f5b78438b)\r\n\r\n#### HTML Validation\r\n\r\nWe have added HTML Validator to help you find errors like duplicate IDs, unrecognized tags, and more. [Read more here.](https://docs.phcode.dev/docs/Features/Problems%20Panel/html-lint/)\r\n\r\n![HTML validate](https://github.com/phcode-dev/phoenix/assets/5336369/5bc4a1cc-2429-477c-83ca-91f19dcc0b0f)\r\n\r\n#### ESLint Support\r\n\r\nAll new and simplified ESLint experience that displays all ESLint errors in a file. Fix one or all errors with a single click. To enable, open a project that uses ESLint in Phoenix Code. [Read more here.](https://docs.phcode.dev/docs/Features/Problems%20Panel/ESLint/)\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/eb00691a-a0b4-4c1a-9209-d78fc7db764d)\r\n\r\n#### Notable Changes\r\n\r\n- **Non-Intrusive Automatic Updates:** Updates are now installed in the background with no more distracting dialogs when an update is available.\r\n- **Case-Sensitive File Renaming:** Renaming files to a different case, such as `a.txt` to `A.TXT`, is now supported.\r\n- `File > New Project` is now renamed to `Start Project`.\r\n- Increased stability and app startup experience.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", + "pub_date": "2024-06-27T08:59:05.475Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVnTkFKdmhnQk5VbEZhTDZXa2RRTjVLZUtRbUVHLzZiK2YveU5VVE9Ob0pTaTRJL1dONUJjbjY2S0R6VDdDcmJMejVZYms1em5wb3JkSlhjRERpOFE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE2NjQzOTIyCWZpbGU6UGhvZW5peCBDb2RlXzMuNy4zX3g2NC1zZXR1cC5uc2lzLnppcApTMFF1ZEVtd2h3Y3hvUlYxV0NvVnluUk1GQTB0VnJYSVNDK3lwSG9sc1pHeGUycmRFd0F0dWF4cUt6d08ySXdSN0lCOTBKbW53eTFidVRqaEkxQ0ZDdz09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_3.7.3_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnJ2WlhnNlcrVWdYZE1nSmMvd0F5VEVWTTkyeVk5dWxnV0piRXpXNTc4WVFTVk1RUytxanZPZENDY3FXS1NsejZBd093ZzFXMGRvSFE1STNQMU9pMVFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5NDc4MDI5CWZpbGU6UGhvZW5peCBDb2RlXzMuOC44X3g2NC1zZXR1cC5uc2lzLnppcAppS1NZVUJrUFp3TTk3QjY4UG1TY0RIZ2dqMldEbStvRzBRVnV4MnAxWDlENWFkU1k5N01SYzRTcnpvYVBWa0VydFFvTkNhSlNEWDVuR0IrRnpWSW1DZz09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnU5M0xRMjg1S2VnVnBmWlN4eDUzS0dXUWdrSVpuREVrbWlEUjhwNmNSc3pEOHJRS3h0S2dscVBESjRSM29aMit4M2N2ZVB0YTN5MmxhWmNlVzdTYndzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE2NjQ0MDY3CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKT2tqUXEzMTVsNTNsRll2SXVGZXA4SGhVTURSSU5LYmVoZ1ZVTGorZkczL3NxeWJwalZCQjVISnN3YlVoWEx2UzEzRnFKZVd5a2hzaXk2MEdMQTkzQ2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmt4RTBwTVhEN1BFS0ErSTIrS0pPOVZoL0NlU0VjWU9FMWZHVWR2SXVNZ0NOdFBSRVE2T0pLdXhlamVQclVwa3ZRZkdFRW11T0hyQlQxSTVWVjVKU2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5NDc4MjYzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdEhVbzdmeTVTWTlxcDQ2ZFZ4bTh4QkdHT2syNklxZmtXM0Jqb0JlSGtXb2YvZlo0NjNzL1ZhOG1pWk1qR3dDWFpPdzhNSGlKQ1BMQnFkVlN6Nmh0Q3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdzYkcrNHZ2QTgyQlJvZHFtNm9qUmJnbnJqYXNqaDFRZjkxSUVBN284UTJkd3h3ai9td09ZR2pFbUFyRkxRZWNpWnpwa3c2dHBkTHpFeTUvUXY2Mmd3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE2NjQ0OTEwCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKWnpBUklmSHYxT2NLaVIxc2IwbXpUZ3ViZGZ5d1ZiMTg5bFhNUzllV01YR1hrb1JCZGt5WG1MNE5wUnJjQUNJN1NLU0F2YjlxL2UraEZYdmJYKy9LRGc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.7.3/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmo3S0ZIT0I4ak00YUhjdHpvVHdraE5peTRIRnVFN214Umhpb3BKTFZRb1ErM0pVSDdhbDF6L3dXTXFXVkZaNXIxSlFDdHVocHhiNDRXamZkYmN4amdRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5NDc4NzI4CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKazhodjlLaHQvNXM1ZnEyODBnamIxYVhsc0FqT0EwSEpnOFprT3RuYnBhNEMzV2xVMDVYa2xtRW9pc2NocnJLV2tjMEJiYmJNclRvSmVCeVI2cVNwQWc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 27e2925e83f0b41650c9c624dbf8cf95fd8d8998 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 29 Jun 2024 09:26:00 +0530 Subject: [PATCH 539/864] update survey urls --- docs/surveys.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/surveys.json b/docs/surveys.json index 28d2977d..77aabe2e 100644 --- a/docs/surveys.json +++ b/docs/surveys.json @@ -1,4 +1,8 @@ { "newUser": "https://s.surveyplanet.com/jssqbld8", - "powerUser": "https://s.surveyplanet.com/v3j59a7z" + "powerUser": "https://s.surveyplanet.com/v3j59a7z", + "browser": { + "newUser": "https://s.surveyplanet.com/5lrpp9ud", + "powerUser": "https://s.surveyplanet.com/wtohpj8x" + } } \ No newline at end of file From 2971b8bc1c1d5648763847c8193b06b9db888b5a Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 1 Jul 2024 10:28:56 +0530 Subject: [PATCH 540/864] chore: website notification json --- docs/siteNotifications/en.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/siteNotifications/en.json diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json new file mode 100644 index 00000000..52ce3e24 --- /dev/null +++ b/docs/siteNotifications/en.json @@ -0,0 +1,14 @@ +{ + "all": {}, + "mac": { + "titleHTML": "Critical Update Available", + "messageHTML": "Having trouble starting Phoenix Code on macOS? Download the app to resolve these issues!" + }, + "linux": { + "titleHTML": "Critical Update Available", + "messageHTML": "Having trouble starting Phoenix Code on Linux? Download the app to resolve these issues!" + }, + "win": {}, + "android": {}, + "ios": {} +} \ No newline at end of file From 81e6f2d2e6cdbb0891a7f2e13cc807ac01a115f8 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 1 Jul 2024 11:12:02 +0530 Subject: [PATCH 541/864] phrasing website notification --- docs/siteNotifications/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json index 52ce3e24..d620e846 100644 --- a/docs/siteNotifications/en.json +++ b/docs/siteNotifications/en.json @@ -2,11 +2,11 @@ "all": {}, "mac": { "titleHTML": "Critical Update Available", - "messageHTML": "Having trouble starting Phoenix Code on macOS? Download the app to resolve these issues!" + "messageHTML": "Having trouble starting Phoenix Code on macOS? Download now to resolve these issues!" }, "linux": { "titleHTML": "Critical Update Available", - "messageHTML": "Having trouble starting Phoenix Code on Linux? Download the app to resolve these issues!" + "messageHTML": "Having trouble starting Phoenix Code on Linux? Download now to resolve these issues!" }, "win": {}, "android": {}, From c10773f981635d6368a2425bb1a830ea67c4e34e Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 1 Jul 2024 15:16:32 +0530 Subject: [PATCH 542/864] update website notification --- docs/siteNotifications/en.json | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json index d620e846..14e1f028 100644 --- a/docs/siteNotifications/en.json +++ b/docs/siteNotifications/en.json @@ -2,13 +2,24 @@ "all": {}, "mac": { "titleHTML": "Critical Update Available", - "messageHTML": "Having trouble starting Phoenix Code on macOS? Download now to resolve these issues!" + "messageHTML": "Having trouble starting Phoenix Code on macOS? Download the latest release here to resolve the issue!", + "severity": "critical", + "dismissable": true }, "linux": { "titleHTML": "Critical Update Available", - "messageHTML": "Having trouble starting Phoenix Code on Linux? Download now to resolve these issues!" + "messageHTML": "Having trouble starting Phoenix Code on Linux? Download the latest release here to resolve the issue!", + "severity": "critical", + "dismissable": true }, "win": {}, "android": {}, - "ios": {} + "ios": {}, + "schema": { + "titleHTML": "an html text to show as title", + "messageHTML": "an html text to show error message", + "severity": "critical | warning | info", + "type": "1 | 2 | 3 - a number, not string, different styles of the message", + dismissable: "true | false - boolean, not string" + } } \ No newline at end of file From 2fba9c3fb571c6ec37c1367e7c39a2febf9c1e0e Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 1 Jul 2024 15:22:00 +0530 Subject: [PATCH 543/864] json error --- docs/siteNotifications/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json index 14e1f028..4b3b4ac4 100644 --- a/docs/siteNotifications/en.json +++ b/docs/siteNotifications/en.json @@ -20,6 +20,6 @@ "messageHTML": "an html text to show error message", "severity": "critical | warning | info", "type": "1 | 2 | 3 - a number, not string, different styles of the message", - dismissable: "true | false - boolean, not string" + "dismissable": "true | false - boolean, not string" } } \ No newline at end of file From 4eba0009cfa68cdf8e129488ce05c14a64453627 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:33:05 +0000 Subject: [PATCH 544/864] fix(deps): update rust crate serde_json to v1.0.120 --- src-tauri/Cargo.lock | 6 +++--- src-tauri/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index baa008ac..6dfa41d1 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2886,7 +2886,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.8.3" +version = "3.8.4" dependencies = [ "clipboard-files", "fix-path-env", @@ -3474,9 +3474,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index bff5f1e6..6f821cbf 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.8.8" +version = "3.8.4" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" From 4599ca6954838a56973da001f163444ae81ec036 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 2 Jul 2024 21:21:54 +0530 Subject: [PATCH 545/864] fix: installation was broken in fedora --- docs/linux/installer.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index c08b3ba0..e8bd4230 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -251,6 +251,8 @@ install_dependencies() { echo "Detected a Fedora/Red Hat based distribution." yes | sudo dnf install webkit2gtk3 gtk3 \ gstreamer1-plugins-base gstreamer1-plugins-good + yes | sudo dnf upgrade webkit2gtk3 gtk3 \ + gstreamer1 gstreamer1-plugins-base gstreamer1-plugins-good ;; arch|manjaro) echo "Detected an Arch Linux based distribution." From a70e1459bd42e9b1cf75f4eaf28ca60c3a720457 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 6 Jul 2024 23:12:57 +0000 Subject: [PATCH 546/864] fix(deps): update rust crate serde to v1.0.204 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 6dfa41d1..dca5f5e6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3454,18 +3454,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", From cf2092ba8eaf23c026bc1f32b8eafde8c00a7d07 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 14 Jul 2024 16:38:40 +0530 Subject: [PATCH 547/864] chore: update phcode site feature json --- docs/siteNotifications/en.json | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json index 4b3b4ac4..c78e3766 100644 --- a/docs/siteNotifications/en.json +++ b/docs/siteNotifications/en.json @@ -21,5 +21,25 @@ "severity": "critical | warning | info", "type": "1 | 2 | 3 - a number, not string, different styles of the message", "dismissable": "true | false - boolean, not string" - } + }, + "features": [ + { + "title": "Live Preview", + "subtitle": "See your HTML and CSS code changes instantly, without page reloads! Use powerful UI tools like the colour editor to tweak background and text colours, adjust font sizes and border-radius with number dials, or explore page layouts with live code hints.", + "titleIconSrc": "assets/images/preview_o.png", + "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/live_preview.mp4" + }, + { + "title": "Code Intelligence for the Web", + "subtitle": "Write HTML, CSS, and JavaScript faster with on-the-fly code completion and catch errors before they become problems. We're always adding better smarts to our code intelligence, making Phoenix Code sharper with every release.", + "titleIconSrc": "assets/images/intelligence.png", + "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/error_detect.mp4" + }, + { + "title": "Lightning-Fast Search", + "subtitle": "Find exactly what you need across your entire project with Instant search. We've fine-tuned the UX to help you pinpoint your query faster: search within specific file types, exclude files and folders, or use regular expressions for complex queries.", + "titleIconSrc": "assets/images/flash.gif", + "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/find_in_files.mp4" + } + ] } \ No newline at end of file From d3f27c3e740ac6423090c0b254d542241f52c5dc Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 14 Jul 2024 17:36:04 +0530 Subject: [PATCH 548/864] feat: add readmore hyperlink to phcode.io --- docs/siteNotifications/en.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json index c78e3766..884cd9cb 100644 --- a/docs/siteNotifications/en.json +++ b/docs/siteNotifications/en.json @@ -25,19 +25,19 @@ "features": [ { "title": "Live Preview", - "subtitle": "See your HTML and CSS code changes instantly, without page reloads! Use powerful UI tools like the colour editor to tweak background and text colours, adjust font sizes and border-radius with number dials, or explore page layouts with live code hints.", + "subtitle": "See your HTML and CSS code changes instantly, without page reloads! Use powerful UI tools like the colour editor to tweak background and text colours, adjust font sizes and border-radius with number dials, or explore page layouts with live code hints. Read more...", "titleIconSrc": "assets/images/preview_o.png", "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/live_preview.mp4" }, { "title": "Code Intelligence for the Web", - "subtitle": "Write HTML, CSS, and JavaScript faster with on-the-fly code completion and catch errors before they become problems. We're always adding better smarts to our code intelligence, making Phoenix Code sharper with every release.", + "subtitle": "Write HTML, CSS, and JavaScript faster with on-the-fly code completion and catch errors before they become problems. We're always adding better smarts to our code intelligence, making Phoenix Code sharper with every release. Read more...", "titleIconSrc": "assets/images/intelligence.png", "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/error_detect.mp4" }, { "title": "Lightning-Fast Search", - "subtitle": "Find exactly what you need across your entire project with Instant search. We've fine-tuned the UX to help you pinpoint your query faster: search within specific file types, exclude files and folders, or use regular expressions for complex queries.", + "subtitle": "Find exactly what you need across your entire project with Instant search. We've fine-tuned the UX to help you pinpoint your query faster: search within specific file types, exclude files and folders, or use regular expressions for complex queries. Read more...", "titleIconSrc": "assets/images/flash.gif", "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/find_in_files.mp4" } From 66475c3842f1ee539627bcd8e1afd4e4c19c688a Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 14 Jul 2024 20:19:50 +0530 Subject: [PATCH 549/864] chore: remove crah fix notification as we have seen most macs recover and brackets push in progress --- docs/siteNotifications/en.json | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json index 884cd9cb..2749b38d 100644 --- a/docs/siteNotifications/en.json +++ b/docs/siteNotifications/en.json @@ -1,17 +1,7 @@ { "all": {}, - "mac": { - "titleHTML": "Critical Update Available", - "messageHTML": "Having trouble starting Phoenix Code on macOS? Download the latest release here to resolve the issue!", - "severity": "critical", - "dismissable": true - }, - "linux": { - "titleHTML": "Critical Update Available", - "messageHTML": "Having trouble starting Phoenix Code on Linux? Download the latest release here to resolve the issue!", - "severity": "critical", - "dismissable": true - }, + "mac": {}, + "linux": {}, "win": {}, "android": {}, "ios": {}, From 171acfe0d43b674101307236e2ab422c87e7dd35 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 15 Jul 2024 11:39:47 +0000 Subject: [PATCH 550/864] ci: update phcode version to 3.9.0 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 14241c87..a0e98cd1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.8.8", + "version": "3.9.0", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "9b837851db997b680d65ae368c3cfdb44200db2c" + "commit": "6105db879aa3f2fe4aa79b5aa0f96eb5384b15b1" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6f821cbf..9ae20361 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.8.4" +version = "3.9.0" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 43183fd2..1b4a349f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.8.8" + "version": "3.9.0" }, "tauri": { "allowlist": { From 1bff195aec7d16c2461a4bd3a75ef889301e1797 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 15 Jul 2024 17:54:10 +0530 Subject: [PATCH 551/864] chore: update certificate thumprint --- src-tauri/tauri.conf.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1b4a349f..b5b976fd 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -205,7 +205,7 @@ "updater" ], "windows": { - "certificateThumbprint": "AB7D19C00251C1E412594A28DC79D201AAEF50D0", + "certificateThumbprint": "09c46b557f16fcdd49b2706c9858e82018cba219", "digestAlgorithm": "sha256", "timestampUrl": "http://timestamp.globalsign.com/tsa/advanced", "nsis": { From b3cf7e9007b3b7fdca5fc66e4eff496caa34b5d6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 20:13:13 +0000 Subject: [PATCH 552/864] chore(deps): update dependency tar to v7.4.1 --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7bbe87fb..454a2f74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.8.4", + "version": "3.9.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.8.4", + "version": "3.9.0", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.14", @@ -18,7 +18,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.4.0" + "tar": "7.4.1" } }, "node_modules/@isaacs/cliui": { @@ -1650,9 +1650,9 @@ } }, "node_modules/tar": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.0.tgz", - "integrity": "sha512-XQs0S8fuAkQWuqhDeCdMlJXDX80D7EOVLDPVFkna9yQfzS+PHKgfxcei0jf6/+QAWcjqrnC8uM3fSAnrQl+XYg==", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.1.tgz", + "integrity": "sha512-dDJzpQf7Nud96mCs3wtw+XUiWGpi9WHxytSusrg0lYlj/Kr11DnB5hfw5bNDQNzx52JJ2Vy+7l8AFivp6H7ETA==", "dev": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index a0e98cd1..87b518d8 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.4.0", + "tar": "7.4.1", "axios": "1.7.2", "axios-retry": "4.4.1" }, From 6759ef276c0143c6ec3b788a0db8f2b464455e13 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:37:53 +0000 Subject: [PATCH 553/864] chore(deps): update dependency axios-retry to v4.4.2 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 454a2f74..0b804bfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@tauri-apps/cli": "1.5.14", "adm-zip": "0.5.14", "axios": "1.7.2", - "axios-retry": "4.4.1", + "axios-retry": "4.4.2", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", @@ -419,9 +419,9 @@ } }, "node_modules/axios-retry": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.4.1.tgz", - "integrity": "sha512-JGzNoglDHtHWIEvvAampB0P7jxQ/sT4COmW0FgSQkVg6o4KqNjNMBI6uFVOq517hkw/OAYYAG08ADtBlV8lvmQ==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.4.2.tgz", + "integrity": "sha512-2fjo9uDNBQjX8+GMEGOFG5TrLMZ3QijjeRYcgBI2MhrsabnvcIAfLxxIhG7+CCD68vPEQY3IM2llV70ZsrqPvA==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 87b518d8..8adee373 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "shx": "^0.3.4", "tar": "7.4.1", "axios": "1.7.2", - "axios-retry": "4.4.1" + "axios-retry": "4.4.2" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From 34f39c075f5ff7c1d4b5600ca11aaaac6d9362ef Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 23 Jul 2024 20:49:07 +0530 Subject: [PATCH 554/864] feat: app crash reporting in rust layer and redirect to support page on crash --- src-tauri/Cargo.lock | 525 ++++++++++++++++++++++++++++++++++-------- src-tauri/Cargo.toml | 3 + src-tauri/src/main.rs | 48 ++++ 3 files changed, 476 insertions(+), 100 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index dca5f5e6..4ee85a4e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ "clipboard-win 5.3.0", "core-graphics 0.23.1", "image", - "log", + "log 0.4.21", "objc", "objc-foundation", "objc_id", @@ -139,10 +139,10 @@ checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ "async-lock 2.8.0", "autocfg", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "futures-lite 1.13.0", - "log", + "log 0.4.21", "parking", "polling 2.8.0", "rustix 0.37.27", @@ -158,7 +158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" dependencies = [ "async-lock 3.3.0", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "futures-io", "futures-lite 2.3.0", @@ -200,7 +200,7 @@ dependencies = [ "async-lock 2.8.0", "async-signal", "blocking", - "cfg-if", + "cfg-if 1.0.0", "event-listener 3.1.0", "futures-lite 1.13.0", "rustix 0.38.32", @@ -227,7 +227,7 @@ dependencies = [ "async-io 2.3.2", "async-lock 2.8.0", "atomic-waker", - "cfg-if", + "cfg-if 1.0.0", "futures-core", "futures-io", "rustix 0.38.32", @@ -291,7 +291,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi 0.1.19", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -308,13 +308,23 @@ checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" +dependencies = [ + "byteorder", + "safemem", +] + [[package]] name = "base64" version = "0.13.1" @@ -419,6 +429,20 @@ dependencies = [ "serde", ] +[[package]] +name = "bugsnag" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20015af8027d22db67e2c84f8b9f2c31b1efa0ec554d8b210c77acb7065d69bf" +dependencies = [ + "backtrace", + "hyper 0.10.16", + "serde", + "serde_derive", + "serde_json", + "sys-info", +] + [[package]] name = "bumpalo" version = "3.15.4" @@ -522,6 +546,12 @@ dependencies = [ "target-lexicon", ] +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -593,7 +623,7 @@ checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" dependencies = [ "error-code 2.3.1", "str-buf", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -734,7 +764,7 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -818,14 +848,38 @@ dependencies = [ "syn 2.0.55", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core 0.13.4", + "darling_macro 0.13.4", +] + [[package]] name = "darling" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.8", + "darling_macro 0.20.8", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -842,13 +896,24 @@ dependencies = [ "syn 2.0.55", ] +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core 0.13.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core", + "darling_core 0.20.8", "quote", "syn 2.0.55", ] @@ -898,6 +963,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dialog" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736bab36d647d14c985725a57a4110a1182c6852104536cd42f1c97e96d29bf0" +dependencies = [ + "dirs 2.0.2", + "rpassword", +] + [[package]] name = "digest" version = "0.10.7" @@ -908,13 +983,23 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +dependencies = [ + "cfg-if 0.1.10", + "dirs-sys 0.3.7", +] + [[package]] name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", ] [[package]] @@ -923,10 +1008,21 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi 0.3.9", +] + [[package]] name = "dirs-sys" version = "0.4.1" @@ -947,7 +1043,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1018,7 +1114,7 @@ version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1173,7 +1269,7 @@ version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "windows-sys 0.52.0", @@ -1258,7 +1354,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "percent-encoding", + "percent-encoding 2.3.1", ] [[package]] @@ -1474,7 +1570,7 @@ checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" dependencies = [ "cc", "libc", - "log", + "log 0.4.21", "rustversion", "windows 0.48.0", ] @@ -1486,7 +1582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -1505,7 +1601,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] @@ -1516,7 +1612,7 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi 0.11.0+wasi-snapshot-preview1", ] @@ -1554,7 +1650,7 @@ dependencies = [ "gobject-sys", "libc", "system-deps 6.2.2", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1616,7 +1712,7 @@ checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "log", + "log 0.4.21", "regex-automata 0.4.6", "regex-syntax 0.8.2", ] @@ -1775,7 +1871,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" dependencies = [ - "log", + "log 0.4.21", "mac", "markup5ever", "proc-macro2", @@ -1823,6 +1919,25 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "hyper" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" +dependencies = [ + "base64 0.9.3", + "httparse", + "language-tags", + "log 0.3.9", + "mime 0.2.6", + "num_cpus", + "time 0.1.45", + "traitobject", + "typeable", + "unicase", + "url 1.7.2", +] + [[package]] name = "hyper" version = "0.14.28" @@ -1854,7 +1969,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.28", "native-tls", "tokio", "tokio-native-tls", @@ -1899,6 +2014,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "0.5.0" @@ -1917,7 +2043,7 @@ checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ "crossbeam-deque", "globset", - "log", + "log 0.4.21", "memchr", "regex-automata 0.4.6", "same-file", @@ -1976,7 +2102,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -1985,11 +2111,11 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81f2533f3be42fffe3b5e63b71aeca416c1c3bc33e4e27be018521e76b1f38fb" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "rustc_version", "to_method", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2044,6 +2170,20 @@ dependencies = [ "system-deps 5.0.0", ] +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log 0.4.21", + "thiserror", + "walkdir", +] + [[package]] name = "jni" version = "0.20.0" @@ -2053,7 +2193,7 @@ dependencies = [ "cesu8", "combine", "jni-sys", - "log", + "log 0.4.21", "thiserror", "walkdir", ] @@ -2091,6 +2231,16 @@ dependencies = [ "treediff", ] +[[package]] +name = "kernel32-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "kuchikiki" version = "0.8.2" @@ -2104,6 +2254,12 @@ dependencies = [ "selectors", ] +[[package]] +name = "language-tags" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" + [[package]] name = "lazy_static" version = "1.5.0" @@ -2122,7 +2278,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-targets 0.52.5", ] @@ -2165,6 +2321,15 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.21", +] + [[package]] name = "log" version = "0.4.21" @@ -2177,7 +2342,7 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "generator", "scoped-tls", "serde", @@ -2202,7 +2367,7 @@ dependencies = [ "dirs-next", "objc-foundation", "objc_id", - "time", + "time 0.3.34", ] [[package]] @@ -2220,7 +2385,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" dependencies = [ - "log", + "log 0.4.21", "phf 0.10.1", "phf_codegen 0.10.0", "string_cache", @@ -2267,6 +2432,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +dependencies = [ + "log 0.3.9", +] + [[package]] name = "mime" version = "0.3.17" @@ -2314,7 +2488,7 @@ checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", - "log", + "log 0.4.21", "openssl", "openssl-probe", "openssl-sys", @@ -2343,6 +2517,34 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" +[[package]] +name = "ndk-glue" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f" +dependencies = [ + "lazy_static", + "libc", + "log 0.4.21", + "ndk", + "ndk-context", + "ndk-macro", + "ndk-sys", +] + +[[package]] +name = "ndk-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" +dependencies = [ + "darling 0.13.4", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ndk-sys" version = "0.3.0" @@ -2365,7 +2567,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "libc", "memoffset 0.7.1", ] @@ -2377,7 +2579,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.5.0", - "cfg-if", + "cfg-if 1.0.0", "cfg_aliases", "libc", ] @@ -2404,7 +2606,7 @@ version = "4.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "827c5edfa80235ded4ab3fe8e9dc619b4f866ef16fe9b1c6b8a7f8692c0f2226" dependencies = [ - "log", + "log 0.4.21", "mac-notification-sys", "serde", "tauri-winrt-notification", @@ -2418,7 +2620,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2588,7 +2790,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ "bitflags 2.5.0", - "cfg-if", + "cfg-if 1.0.0", "foreign-types 0.3.2", "libc", "once_cell", @@ -2647,7 +2849,7 @@ version = "3.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" dependencies = [ - "log", + "log 0.4.21", "serde", "windows-sys 0.52.0", ] @@ -2721,7 +2923,7 @@ version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "redox_syscall", "smallvec", @@ -2734,6 +2936,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -2886,15 +3094,17 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.8.4" +version = "3.9.0" dependencies = [ + "bugsnag", "clipboard-files", + "dialog", "fix-path-env", "gtk", "lazy_static", "objc", "once_cell", - "percent-encoding", + "percent-encoding 2.3.1", "regex", "serde", "serde_json", @@ -2905,8 +3115,9 @@ dependencies = [ "tauri-plugin-single-instance", "tauri-plugin-window-state", "trash", + "webbrowser", "webkit2gtk", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2949,7 +3160,7 @@ dependencies = [ "line-wrap", "quick-xml 0.31.0", "serde", - "time", + "time 0.3.34", ] [[package]] @@ -2973,10 +3184,10 @@ checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", "bitflags 1.3.2", - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "libc", - "log", + "log 0.4.21", "pin-project-lite", "windows-sys 0.48.0", ] @@ -2987,7 +3198,7 @@ version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "concurrent-queue", "hermit-abi 0.3.9", "pin-project-lite", @@ -3034,7 +3245,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -3045,7 +3256,7 @@ checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", - "version_check", + "version_check 0.9.4", ] [[package]] @@ -3255,15 +3466,15 @@ dependencies = [ "h2", "http", "http-body", - "hyper", + "hyper 0.14.28", "hyper-tls", "ipnet", "js-sys", - "log", - "mime", + "log 0.4.21", + "mime 0.3.17", "native-tls", "once_cell", - "percent-encoding", + "percent-encoding 2.3.1", "pin-project-lite", "rustls-pemfile", "serde", @@ -3275,7 +3486,7 @@ dependencies = [ "tokio-native-tls", "tokio-util", "tower-service", - "url", + "url 2.5.0", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", @@ -3296,7 +3507,7 @@ dependencies = [ "gtk-sys", "js-sys", "lazy_static", - "log", + "log 0.4.21", "objc", "objc-foundation", "objc_id", @@ -3307,6 +3518,17 @@ dependencies = [ "windows 0.37.0", ] +[[package]] +name = "rpassword" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37473170aedbe66ffa3ad3726939ba677d83c646ad4fd99e5b4bc38712f45ec" +dependencies = [ + "kernel32-sys", + "libc", + "winapi 0.2.8", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -3370,6 +3592,12 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + [[package]] name = "same-file" version = "1.0.6" @@ -3433,7 +3661,7 @@ dependencies = [ "cssparser", "derive_more", "fxhash", - "log", + "log 0.4.21", "matches", "phf 0.8.0", "phf_codegen 0.8.0", @@ -3531,7 +3759,7 @@ dependencies = [ "serde_derive", "serde_json", "serde_with_macros", - "time", + "time 0.3.34", ] [[package]] @@ -3540,7 +3768,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" dependencies = [ - "darling", + "darling 0.20.8", "proc-macro2", "quote", "syn 2.0.55", @@ -3584,7 +3812,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -3595,7 +3823,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "cpufeatures", "digest", ] @@ -3616,7 +3844,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3662,7 +3890,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -3799,6 +4027,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sys-info" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58283a48c9212afcade2069f8bbf7ded6a7bdbf4888d2defba72244c8e5f423c" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "sys-locale" version = "0.2.4" @@ -3884,10 +4122,10 @@ dependencies = [ "gtk", "image", "instant", - "jni", + "jni 0.20.0", "lazy_static", "libc", - "log", + "log 0.4.21", "ndk", "ndk-context", "ndk-sys", @@ -3967,7 +4205,7 @@ dependencies = [ "open", "os_info", "os_pipe", - "percent-encoding", + "percent-encoding 2.3.1", "rand 0.8.5", "raw-window-handle", "regex", @@ -3988,9 +4226,9 @@ dependencies = [ "tauri-utils", "tempfile", "thiserror", - "time", + "time 0.3.34", "tokio", - "url", + "url 2.5.0", "uuid", "webkit2gtk", "webview2-com", @@ -4038,7 +4276,7 @@ dependencies = [ "sha2", "tauri-utils", "thiserror", - "time", + "time 0.3.34", "uuid", "walkdir", ] @@ -4063,9 +4301,9 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4536f5f6602e8fdfaa7b3b185076c2a0704f8eb7015f4e58461eb483ec3ed1f8" dependencies = [ - "dirs", + "dirs 5.0.1", "interprocess", - "log", + "log 0.4.21", "objc2 0.4.1", "once_cell", "tauri-utils", @@ -4078,7 +4316,7 @@ name = "tauri-plugin-fs-extra" version = "0.0.0" source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edbbcfed8f8c057a15e02318e0ddcaab132" dependencies = [ - "log", + "log 0.4.21", "serde", "serde_json", "tauri", @@ -4090,7 +4328,7 @@ name = "tauri-plugin-single-instance" version = "0.0.0" source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edbbcfed8f8c057a15e02318e0ddcaab132" dependencies = [ - "log", + "log 0.4.21", "serde", "serde_json", "tauri", @@ -4106,7 +4344,7 @@ source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edb dependencies = [ "bincode", "bitflags 2.5.0", - "log", + "log 0.4.21", "serde", "serde_json", "tauri", @@ -4128,7 +4366,7 @@ dependencies = [ "serde_json", "tauri-utils", "thiserror", - "url", + "url 2.5.0", "uuid", "webview2-com", "windows 0.39.0", @@ -4143,7 +4381,7 @@ dependencies = [ "arboard", "cocoa", "gtk", - "percent-encoding", + "percent-encoding 2.3.1", "rand 0.8.5", "raw-window-handle", "tauri-runtime", @@ -4170,7 +4408,7 @@ dependencies = [ "infer", "json-patch", "kuchikiki", - "log", + "log 0.4.21", "memchr", "phf 0.11.2", "proc-macro2", @@ -4180,7 +4418,7 @@ dependencies = [ "serde_json", "serde_with", "thiserror", - "url", + "url 2.5.0", "walkdir", "windows-version", ] @@ -4211,7 +4449,7 @@ version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "fastrand 2.0.2", "rustix 0.38.32", "windows-sys 0.52.0", @@ -4275,7 +4513,7 @@ version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] @@ -4290,6 +4528,17 @@ dependencies = [ "weezl", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", +] + [[package]] name = "time" version = "0.3.34" @@ -4494,7 +4743,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "log", + "log 0.4.21", "once_cell", "tracing-core", ] @@ -4517,6 +4766,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "traitobject" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" + [[package]] name = "trash" version = "5.0.0" @@ -4525,7 +4780,7 @@ checksum = "8d8fbfb70b1fad5c0b788f9b2e1bf4d04e5ac6efa828f1ed9ee462c50ff9cf05" dependencies = [ "chrono", "libc", - "log", + "log 0.4.21", "objc2 0.5.2", "objc2-foundation", "once_cell", @@ -4563,6 +4818,12 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "typeable" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" + [[package]] name = "typenum" version = "1.17.0" @@ -4577,7 +4838,16 @@ checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ "memoffset 0.9.0", "tempfile", - "winapi", + "winapi 0.3.9", +] + +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +dependencies = [ + "version_check 0.1.5", ] [[package]] @@ -4607,6 +4877,17 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +dependencies = [ + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", +] + [[package]] name = "url" version = "2.5.0" @@ -4614,8 +4895,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna", - "percent-encoding", + "idna 0.5.0", + "percent-encoding 2.3.1", "serde", ] @@ -4670,6 +4951,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + [[package]] name = "version_check" version = "0.9.4" @@ -4747,6 +5034,12 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4759,7 +5052,7 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] @@ -4770,7 +5063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", - "log", + "log 0.4.21", "once_cell", "proc-macro2", "quote", @@ -4784,7 +5077,7 @@ version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "js-sys", "wasm-bindgen", "web-sys", @@ -4901,7 +5194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" dependencies = [ "dlib", - "log", + "log 0.4.21", "pkg-config", ] @@ -4915,6 +5208,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a3cffdb686fbb24d9fb8f03a213803277ed2300f11026a3afe1f108dc021b" +dependencies = [ + "jni 0.19.0", + "ndk-glue", + "url 2.5.0", + "web-sys", + "widestring", + "winapi 0.3.9", +] + [[package]] name = "webkit2gtk" version = "0.18.2" @@ -5006,6 +5313,18 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +[[package]] +name = "widestring" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" + +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -5016,6 +5335,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -5028,7 +5353,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -5490,7 +5815,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-sys 0.48.0", ] @@ -5500,7 +5825,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "windows-sys 0.48.0", ] @@ -5512,7 +5837,7 @@ checksum = "12b41773911497b18ca8553c3daaf8ec9fe9819caf93d451d3055f69de028adb" dependencies = [ "derive-new", "libc", - "log", + "log 0.4.21", "nix 0.28.0", "os_pipe", "tempfile", @@ -5544,7 +5869,7 @@ dependencies = [ "http", "kuchikiki", "libc", - "log", + "log 0.4.21", "objc", "objc_id", "once_cell", @@ -5554,7 +5879,7 @@ dependencies = [ "soup2", "tao", "thiserror", - "url", + "url 2.5.0", "webkit2gtk", "webkit2gtk-sys", "webview2-com", @@ -5618,7 +5943,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21e5a325c3cb8398ad6cf859c1135b25dd29e186679cf2da7581d9679f63b38e" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -5655,7 +5980,7 @@ dependencies = [ "static_assertions", "tracing", "uds_windows", - "winapi", + "winapi 0.3.9", "xdg-home", "zbus_macros", "zbus_names", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9ae20361..956a9ce3 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -20,6 +20,9 @@ percent-encoding = "2.3.1" regex = "1.10.4" clipboard-files = "0.1.1" trash = "5" +dialog = "0.3.0" +bugsnag = "=0.2.1" +webbrowser = "0.7" serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3.9", features = ["fileapi"] } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index cae22925..57d3d01e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,6 +3,8 @@ all(not(debug_assertions), target_os = "windows"), windows_subsystem = "windows" )] use std::env; +use std::panic; +use bugsnag; use tauri::{Manager}; use std::path::PathBuf; @@ -25,6 +27,7 @@ extern crate webkit2gtk; extern crate objc; use clipboard_files; +use dialog::DialogBox; use regex::Regex; extern crate percent_encoding; @@ -266,6 +269,51 @@ fn get_mac_deep_link_requests() -> Vec { fn main() { let args: Vec = env::args().collect(); + + panic::set_hook(Box::new(|panic_info| { + let panic_message = panic_info.payload().downcast_ref::<&str>().unwrap_or(&"No specific error message available"); + eprintln!("Application panicked: {:?}", panic_message); + + let mut api = bugsnag::Bugsnag::new("4dc115247125339aa551f3b11a5bee6b", env!("CARGO_MANIFEST_DIR")); + let args: Vec = env::args().collect(); + let executable_name = if !args.is_empty() { + // Get the executable name from the full path + let path = &args[0]; + path.split(std::path::MAIN_SEPARATOR) + .last() + .unwrap_or("unknown_executable") + .to_string() + } else { + "unknown_executable".to_string() + }; + api.set_app_info(Some(env!("CARGO_PKG_VERSION")), + Some(&executable_name), + Some("rust")); + + // Construct the error message with the panic message included + let error_message = format!( + "The app crashed unexpectedly with error: \n\n'{}'. \n\nWould you like to send an anonymised error report to help us fix the problem?", + panic_message + ); + + let choice = dialog::Question::new(&error_message) + .title("Oops! Phoenix Code Crashed :(") + .show() + .expect("Could not display dialog box"); + + // take user to support page. maybe we will have some notifications pinned there if its a large scale outage + let support_url = "https://github.com/orgs/phcode-dev/discussions"; + if webbrowser::open(support_url).is_ok() { + println!("Opened support_url {} in the default browser.", support_url); + } else { + println!("Failed to open support_url {}.", support_url); + } + + if choice == dialog::Choice::Yes { + let _ = bugsnag::panic::handle(&api, panic_info, None); + } + })); + if args.contains(&"--runVerify".to_string()) { // Mainly used by linux installer to see if the app loaded successfully with all libs std::process::exit(0); From fa30e81d05346aec42b037a5bf12000203729ffe Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 24 Jul 2024 11:56:52 +0530 Subject: [PATCH 555/864] fix: remove bugsnag crate as its not suported in windows and cross platform dialog --- src-tauri/Cargo.lock | 361 +++++++++++++++++------------------------- src-tauri/Cargo.toml | 7 +- src-tauri/src/main.rs | 55 ++++--- 3 files changed, 184 insertions(+), 239 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 4ee85a4e..405bfdfb 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ "clipboard-win 5.3.0", "core-graphics 0.23.1", "image", - "log 0.4.21", + "log", "objc", "objc-foundation", "objc_id", @@ -82,6 +82,12 @@ dependencies = [ "x11rb", ] +[[package]] +name = "ascii" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" + [[package]] name = "async-broadcast" version = "0.5.1" @@ -142,7 +148,7 @@ dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "futures-lite 1.13.0", - "log 0.4.21", + "log", "parking", "polling 2.8.0", "rustix 0.37.27", @@ -315,16 +321,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - [[package]] name = "base64" version = "0.13.1" @@ -429,20 +425,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bugsnag" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20015af8027d22db67e2c84f8b9f2c31b1efa0ec554d8b210c77acb7065d69bf" -dependencies = [ - "backtrace", - "hyper 0.10.16", - "serde", - "serde_derive", - "serde_json", - "sys-info", -] - [[package]] name = "bumpalo" version = "3.15.4" @@ -651,6 +633,22 @@ dependencies = [ "objc", ] +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics 0.23.1", + "foreign-types 0.5.0", + "libc", + "objc", +] + [[package]] name = "cocoa-foundation" version = "0.1.2" @@ -1088,6 +1086,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "embed-resource" version = "2.4.2" @@ -1354,7 +1358,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "percent-encoding 2.3.1", + "percent-encoding", ] [[package]] @@ -1570,7 +1574,7 @@ checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" dependencies = [ "cc", "libc", - "log 0.4.21", + "log", "rustversion", "windows 0.48.0", ] @@ -1582,7 +1586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", - "version_check 0.9.4", + "version_check", ] [[package]] @@ -1712,7 +1716,7 @@ checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "log 0.4.21", + "log", "regex-automata 0.4.6", "regex-syntax 0.8.2", ] @@ -1871,7 +1875,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" dependencies = [ - "log 0.4.21", + "log", "mac", "markup5ever", "proc-macro2", @@ -1919,25 +1923,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "hyper" -version = "0.10.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -dependencies = [ - "base64 0.9.3", - "httparse", - "language-tags", - "log 0.3.9", - "mime 0.2.6", - "num_cpus", - "time 0.1.45", - "traitobject", - "typeable", - "unicase", - "url 1.7.2", -] - [[package]] name = "hyper" version = "0.14.28" @@ -1969,7 +1954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.28", + "hyper", "native-tls", "tokio", "tokio-native-tls", @@ -2014,17 +1999,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "0.5.0" @@ -2043,7 +2017,7 @@ checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ "crossbeam-deque", "globset", - "log 0.4.21", + "log", "memchr", "regex-automata 0.4.6", "same-file", @@ -2135,6 +2109,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.8" @@ -2179,7 +2162,7 @@ dependencies = [ "cesu8", "combine", "jni-sys", - "log 0.4.21", + "log", "thiserror", "walkdir", ] @@ -2193,7 +2176,7 @@ dependencies = [ "cesu8", "combine", "jni-sys", - "log 0.4.21", + "log", "thiserror", "walkdir", ] @@ -2254,12 +2237,6 @@ dependencies = [ "selectors", ] -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - [[package]] name = "lazy_static" version = "1.5.0" @@ -2321,15 +2298,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.21", -] - [[package]] name = "log" version = "0.4.21" @@ -2367,7 +2335,7 @@ dependencies = [ "dirs-next", "objc-foundation", "objc_id", - "time 0.3.34", + "time", ] [[package]] @@ -2385,7 +2353,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" dependencies = [ - "log 0.4.21", + "log", "phf 0.10.1", "phf_codegen 0.10.0", "string_cache", @@ -2432,15 +2400,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", -] - [[package]] name = "mime" version = "0.3.17" @@ -2480,6 +2439,29 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "native-dialog" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84e7038885d2aeab236bd60da9e159a5967b47cde3292da3b15ff1bec27c039f" +dependencies = [ + "ascii", + "block", + "cocoa 0.25.0", + "core-foundation", + "dirs-next", + "objc", + "objc-foundation", + "objc_id", + "once_cell", + "raw-window-handle", + "thiserror", + "versions", + "wfd", + "which", + "winapi 0.3.9", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -2488,7 +2470,7 @@ checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", - "log 0.4.21", + "log", "openssl", "openssl-probe", "openssl-sys", @@ -2525,7 +2507,7 @@ checksum = "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f" dependencies = [ "lazy_static", "libc", - "log 0.4.21", + "log", "ndk", "ndk-context", "ndk-macro", @@ -2606,7 +2588,7 @@ version = "4.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "827c5edfa80235ded4ab3fe8e9dc619b4f866ef16fe9b1c6b8a7f8692c0f2226" dependencies = [ - "log 0.4.21", + "log", "mac-notification-sys", "serde", "tauri-winrt-notification", @@ -2849,7 +2831,7 @@ version = "3.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" dependencies = [ - "log 0.4.21", + "log", "serde", "windows-sys 0.52.0", ] @@ -2936,12 +2918,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "percent-encoding" version = "2.3.1" @@ -3096,15 +3072,15 @@ dependencies = [ name = "phoenix-code-ide" version = "3.9.0" dependencies = [ - "bugsnag", "clipboard-files", "dialog", "fix-path-env", "gtk", "lazy_static", + "native-dialog", "objc", "once_cell", - "percent-encoding 2.3.1", + "percent-encoding", "regex", "serde", "serde_json", @@ -3160,7 +3136,7 @@ dependencies = [ "line-wrap", "quick-xml 0.31.0", "serde", - "time 0.3.34", + "time", ] [[package]] @@ -3187,7 +3163,7 @@ dependencies = [ "cfg-if 1.0.0", "concurrent-queue", "libc", - "log 0.4.21", + "log", "pin-project-lite", "windows-sys 0.48.0", ] @@ -3245,7 +3221,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "version_check 0.9.4", + "version_check", ] [[package]] @@ -3256,7 +3232,7 @@ checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", "quote", - "version_check 0.9.4", + "version_check", ] [[package]] @@ -3466,15 +3442,15 @@ dependencies = [ "h2", "http", "http-body", - "hyper 0.14.28", + "hyper", "hyper-tls", "ipnet", "js-sys", - "log 0.4.21", - "mime 0.3.17", + "log", + "mime", "native-tls", "once_cell", - "percent-encoding 2.3.1", + "percent-encoding", "pin-project-lite", "rustls-pemfile", "serde", @@ -3486,7 +3462,7 @@ dependencies = [ "tokio-native-tls", "tokio-util", "tower-service", - "url 2.5.0", + "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", @@ -3507,7 +3483,7 @@ dependencies = [ "gtk-sys", "js-sys", "lazy_static", - "log 0.4.21", + "log", "objc", "objc-foundation", "objc_id", @@ -3592,12 +3568,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - [[package]] name = "same-file" version = "1.0.6" @@ -3661,7 +3631,7 @@ dependencies = [ "cssparser", "derive_more", "fxhash", - "log 0.4.21", + "log", "matches", "phf 0.8.0", "phf_codegen 0.8.0", @@ -3759,7 +3729,7 @@ dependencies = [ "serde_derive", "serde_json", "serde_with_macros", - "time 0.3.34", + "time", ] [[package]] @@ -4027,16 +3997,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "sys-info" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58283a48c9212afcade2069f8bbf7ded6a7bdbf4888d2defba72244c8e5f423c" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "sys-locale" version = "0.2.4" @@ -4106,7 +4066,7 @@ dependencies = [ "bitflags 1.3.2", "cairo-rs", "cc", - "cocoa", + "cocoa 0.24.1", "core-foundation", "core-graphics 0.22.3", "crossbeam-channel", @@ -4125,7 +4085,7 @@ dependencies = [ "jni 0.20.0", "lazy_static", "libc", - "log 0.4.21", + "log", "ndk", "ndk-context", "ndk-sys", @@ -4182,7 +4142,7 @@ dependencies = [ "base64 0.21.7", "bytes", "clap", - "cocoa", + "cocoa 0.24.1", "dirs-next", "dunce", "embed_plist", @@ -4205,7 +4165,7 @@ dependencies = [ "open", "os_info", "os_pipe", - "percent-encoding 2.3.1", + "percent-encoding", "rand 0.8.5", "raw-window-handle", "regex", @@ -4226,9 +4186,9 @@ dependencies = [ "tauri-utils", "tempfile", "thiserror", - "time 0.3.34", + "time", "tokio", - "url 2.5.0", + "url", "uuid", "webkit2gtk", "webview2-com", @@ -4276,7 +4236,7 @@ dependencies = [ "sha2", "tauri-utils", "thiserror", - "time 0.3.34", + "time", "uuid", "walkdir", ] @@ -4303,7 +4263,7 @@ checksum = "4536f5f6602e8fdfaa7b3b185076c2a0704f8eb7015f4e58461eb483ec3ed1f8" dependencies = [ "dirs 5.0.1", "interprocess", - "log 0.4.21", + "log", "objc2 0.4.1", "once_cell", "tauri-utils", @@ -4316,7 +4276,7 @@ name = "tauri-plugin-fs-extra" version = "0.0.0" source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edbbcfed8f8c057a15e02318e0ddcaab132" dependencies = [ - "log 0.4.21", + "log", "serde", "serde_json", "tauri", @@ -4328,7 +4288,7 @@ name = "tauri-plugin-single-instance" version = "0.0.0" source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edbbcfed8f8c057a15e02318e0ddcaab132" dependencies = [ - "log 0.4.21", + "log", "serde", "serde_json", "tauri", @@ -4344,7 +4304,7 @@ source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edb dependencies = [ "bincode", "bitflags 2.5.0", - "log 0.4.21", + "log", "serde", "serde_json", "tauri", @@ -4366,7 +4326,7 @@ dependencies = [ "serde_json", "tauri-utils", "thiserror", - "url 2.5.0", + "url", "uuid", "webview2-com", "windows 0.39.0", @@ -4379,9 +4339,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1989b3b4d611f5428b3414a4abae6fa6df30c7eb8ed33250ca90a5f7e5bb3655" dependencies = [ "arboard", - "cocoa", + "cocoa 0.24.1", "gtk", - "percent-encoding 2.3.1", + "percent-encoding", "rand 0.8.5", "raw-window-handle", "tauri-runtime", @@ -4408,7 +4368,7 @@ dependencies = [ "infer", "json-patch", "kuchikiki", - "log 0.4.21", + "log", "memchr", "phf 0.11.2", "proc-macro2", @@ -4418,7 +4378,7 @@ dependencies = [ "serde_json", "serde_with", "thiserror", - "url 2.5.0", + "url", "walkdir", "windows-version", ] @@ -4528,17 +4488,6 @@ dependencies = [ "weezl", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", -] - [[package]] name = "time" version = "0.3.34" @@ -4743,7 +4692,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "log 0.4.21", + "log", "once_cell", "tracing-core", ] @@ -4766,12 +4715,6 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" - [[package]] name = "trash" version = "5.0.0" @@ -4780,7 +4723,7 @@ checksum = "8d8fbfb70b1fad5c0b788f9b2e1bf4d04e5ac6efa828f1ed9ee462c50ff9cf05" dependencies = [ "chrono", "libc", - "log 0.4.21", + "log", "objc2 0.5.2", "objc2-foundation", "once_cell", @@ -4818,12 +4761,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" - [[package]] name = "typenum" version = "1.17.0" @@ -4841,15 +4778,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -dependencies = [ - "version_check 0.1.5", -] - [[package]] name = "unicode-bidi" version = "0.3.15" @@ -4877,17 +4805,6 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] - [[package]] name = "url" version = "2.5.0" @@ -4895,8 +4812,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.5.0", - "percent-encoding 2.3.1", + "idna", + "percent-encoding", "serde", ] @@ -4953,15 +4870,19 @@ checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" -version = "0.1.5" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] -name = "version_check" -version = "0.9.4" +name = "versions" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "c73a36bc44e3039f51fbee93e39f41225f6b17b380eb70cc2aab942df06b34dd" +dependencies = [ + "itertools", + "nom", +] [[package]] name = "vswhom" @@ -5034,12 +4955,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -5063,7 +4978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", - "log 0.4.21", + "log", "once_cell", "proc-macro2", "quote", @@ -5194,7 +5109,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" dependencies = [ "dlib", - "log 0.4.21", + "log", "pkg-config", ] @@ -5216,7 +5131,7 @@ checksum = "fc6a3cffdb686fbb24d9fb8f03a213803277ed2300f11026a3afe1f108dc021b" dependencies = [ "jni 0.19.0", "ndk-glue", - "url 2.5.0", + "url", "web-sys", "widestring", "winapi 0.3.9", @@ -5313,6 +5228,28 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +[[package]] +name = "wfd" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e713040b67aae5bf1a0ae3e1ebba8cc29ab2b90da9aa1bff6e09031a8a41d7a8" +dependencies = [ + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.32", +] + [[package]] name = "widestring" version = "0.5.1" @@ -5837,7 +5774,7 @@ checksum = "12b41773911497b18ca8553c3daaf8ec9fe9819caf93d451d3055f69de028adb" dependencies = [ "derive-new", "libc", - "log 0.4.21", + "log", "nix 0.28.0", "os_pipe", "tempfile", @@ -5857,7 +5794,7 @@ checksum = "00711278ed357350d44c749c286786ecac644e044e4da410d466212152383b45" dependencies = [ "base64 0.13.1", "block", - "cocoa", + "cocoa 0.24.1", "core-graphics 0.22.3", "crossbeam-channel", "dunce", @@ -5869,7 +5806,7 @@ dependencies = [ "http", "kuchikiki", "libc", - "log 0.4.21", + "log", "objc", "objc_id", "once_cell", @@ -5879,7 +5816,7 @@ dependencies = [ "soup2", "tao", "thiserror", - "url 2.5.0", + "url", "webkit2gtk", "webkit2gtk-sys", "webview2-com", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 956a9ce3..c5333213 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -20,8 +20,6 @@ percent-encoding = "2.3.1" regex = "1.10.4" clipboard-files = "0.1.1" trash = "5" -dialog = "0.3.0" -bugsnag = "=0.2.1" webbrowser = "0.7" serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } @@ -31,14 +29,19 @@ tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-works tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } +[target.'cfg(target_os = "windows")'.dependencies] +native-dialog = "0.7.0" + [target.'cfg(target_os = "linux")'.dependencies] gtk = "0.15" webkit2gtk = "0.18" # if tauri build fails, make sure to match this version to what we have in tauri +dialog = "0.3.0" [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2.7" tauri-plugin-deep-link = "0.1.2" lazy_static = "1.4" +dialog = "0.3.0" [features] # by default Tauri runs in production mode diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 57d3d01e..736d718b 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,7 +4,6 @@ windows_subsystem = "windows" )] use std::env; use std::panic; -use bugsnag; use tauri::{Manager}; use std::path::PathBuf; @@ -27,8 +26,13 @@ extern crate webkit2gtk; extern crate objc; use clipboard_files; + +#[cfg(any(target_os = "macos", target_os = "linux"))] use dialog::DialogBox; +#[cfg(target_os = "windows")] +use native_dialog::{MessageDialog, MessageType}; + use regex::Regex; extern crate percent_encoding; use tauri::http::ResponseBuilder; @@ -274,32 +278,33 @@ fn main() { let panic_message = panic_info.payload().downcast_ref::<&str>().unwrap_or(&"No specific error message available"); eprintln!("Application panicked: {:?}", panic_message); - let mut api = bugsnag::Bugsnag::new("4dc115247125339aa551f3b11a5bee6b", env!("CARGO_MANIFEST_DIR")); - let args: Vec = env::args().collect(); - let executable_name = if !args.is_empty() { - // Get the executable name from the full path - let path = &args[0]; - path.split(std::path::MAIN_SEPARATOR) - .last() - .unwrap_or("unknown_executable") - .to_string() - } else { - "unknown_executable".to_string() - }; - api.set_app_info(Some(env!("CARGO_PKG_VERSION")), - Some(&executable_name), - Some("rust")); - // Construct the error message with the panic message included let error_message = format!( - "The app crashed unexpectedly with error: \n\n'{}'. \n\nWould you like to send an anonymised error report to help us fix the problem?", + "The app crashed unexpectedly with error: \n\n'{}'\n\nOpening support page. Would you like to send an anonymised error report to help us fix the problem?", panic_message ); - let choice = dialog::Question::new(&error_message) - .title("Oops! Phoenix Code Crashed :(") - .show() - .expect("Could not display dialog box"); + let mut should_log_to_bugsnag = false; + #[cfg(any(target_os = "macos", target_os = "linux"))] + { + let choice = dialog::Question::new(&error_message) + .title("Oops! Phoenix Code Crashed :(") + .show() + .expect("Could not display dialog box"); + if choice == dialog::Choice::Yes { + should_log_to_bugsnag = true; + } + } + + #[cfg(target_os = "windows")] + { + should_log_to_bugsnag = MessageDialog::new() + .set_type(MessageType::Error) + .set_title("Oops! Phoenix Code Crashed :(") + .set_text(&error_message) + .show_confirm() + .unwrap(); + } // take user to support page. maybe we will have some notifications pinned there if its a large scale outage let support_url = "https://github.com/orgs/phcode-dev/discussions"; @@ -308,9 +313,9 @@ fn main() { } else { println!("Failed to open support_url {}.", support_url); } - - if choice == dialog::Choice::Yes { - let _ = bugsnag::panic::handle(&api, panic_info, None); + if should_log_to_bugsnag { + // let _ = bugsnag::panic::handle(&api, panic_info, None); + println!("Log to bugsnag impl pending!"); } })); From b4fb115b8f36e0038bd9539d401d65e3df612d46 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 24 Jul 2024 12:14:13 +0530 Subject: [PATCH 556/864] fix: app crash error report dialog not coming in mac --- src-tauri/Cargo.toml | 2 +- src-tauri/src/main.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c5333213..fb643e2c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -41,7 +41,7 @@ dialog = "0.3.0" objc = "0.2.7" tauri-plugin-deep-link = "0.1.2" lazy_static = "1.4" -dialog = "0.3.0" +native-dialog = "0.7.0" [features] # by default Tauri runs in production mode diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 736d718b..e6d40cd9 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -27,10 +27,10 @@ extern crate objc; use clipboard_files; -#[cfg(any(target_os = "macos", target_os = "linux"))] +#[cfg(target_os = "linux")] use dialog::DialogBox; -#[cfg(target_os = "windows")] +#[cfg(any(target_os = "macos", target_os = "windows"))] use native_dialog::{MessageDialog, MessageType}; use regex::Regex; @@ -285,7 +285,7 @@ fn main() { ); let mut should_log_to_bugsnag = false; - #[cfg(any(target_os = "macos", target_os = "linux"))] + #[cfg(target_os = "linux")] { let choice = dialog::Question::new(&error_message) .title("Oops! Phoenix Code Crashed :(") @@ -296,7 +296,7 @@ fn main() { } } - #[cfg(target_os = "windows")] + #[cfg(any(target_os = "macos", target_os = "windows"))] { should_log_to_bugsnag = MessageDialog::new() .set_type(MessageType::Error) From 8163e4326ce6a9d8020e139fe87b8c893fbd19b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jul 2024 13:54:11 +0000 Subject: [PATCH 557/864] build(deps): bump webbrowser from 0.7.1 to 0.8.3 in /src-tauri Bumps [webbrowser](https://github.com/amodm/webbrowser-rs) from 0.7.1 to 0.8.3. - [Release notes](https://github.com/amodm/webbrowser-rs/releases) - [Changelog](https://github.com/amodm/webbrowser-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/amodm/webbrowser-rs/compare/v0.7.1...v0.8.3) --- updated-dependencies: - dependency-name: webbrowser dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 109 +++++++++---------------------------------- src-tauri/Cargo.toml | 2 +- 2 files changed, 24 insertions(+), 87 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 405bfdfb..d8e8284c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -846,38 +846,14 @@ dependencies = [ "syn 2.0.55", ] -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - [[package]] name = "darling" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" dependencies = [ - "darling_core 0.20.8", - "darling_macro 0.20.8", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", + "darling_core", + "darling_macro", ] [[package]] @@ -894,24 +870,13 @@ dependencies = [ "syn 2.0.55", ] -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn 1.0.109", -] - [[package]] name = "darling_macro" version = "0.20.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ - "darling_core 0.20.8", + "darling_core", "quote", "syn 2.0.55", ] @@ -991,6 +956,15 @@ dependencies = [ "dirs-sys 0.3.7", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys 0.3.7", +] + [[package]] name = "dirs" version = "5.0.1" @@ -2153,20 +2127,6 @@ dependencies = [ "system-deps 5.0.0", ] -[[package]] -name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - [[package]] name = "jni" version = "0.20.0" @@ -2499,34 +2459,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" -[[package]] -name = "ndk-glue" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0c4a7b83860226e6b4183edac21851f05d5a51756e97a1144b7f5a6b63e65f" -dependencies = [ - "lazy_static", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-macro", - "ndk-sys", -] - -[[package]] -name = "ndk-macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" -dependencies = [ - "darling 0.13.4", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "ndk-sys" version = "0.3.0" @@ -3738,7 +3670,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" dependencies = [ - "darling 0.20.8", + "darling", "proc-macro2", "quote", "syn 2.0.55", @@ -4082,7 +4014,7 @@ dependencies = [ "gtk", "image", "instant", - "jni 0.20.0", + "jni", "lazy_static", "libc", "log", @@ -5125,12 +5057,17 @@ dependencies = [ [[package]] name = "webbrowser" -version = "0.7.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a3cffdb686fbb24d9fb8f03a213803277ed2300f11026a3afe1f108dc021b" +checksum = "aa61ff77f695a94d9c8558e0bb5c362a8fd1f27c74663770fbc633acbafedbb6" dependencies = [ - "jni 0.19.0", - "ndk-glue", + "core-foundation", + "dirs 4.0.0", + "jni", + "log", + "ndk-context", + "objc", + "raw-window-handle", "url", "web-sys", "widestring", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index fb643e2c..55319db5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -20,7 +20,7 @@ percent-encoding = "2.3.1" regex = "1.10.4" clipboard-files = "0.1.1" trash = "5" -webbrowser = "0.7" +webbrowser = "0.8" serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3.9", features = ["fileapi"] } From 193ea666461d43bcdf6fb04f5337adb53d74b58f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 24 Jul 2024 19:47:13 +0000 Subject: [PATCH 558/864] fix(deps): update rust crate webbrowser to v0.8.15 --- src-tauri/Cargo.lock | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d8e8284c..15413c32 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -956,15 +956,6 @@ dependencies = [ "dirs-sys 0.3.7", ] -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys 0.3.7", -] - [[package]] name = "dirs" version = "5.0.1" @@ -2141,6 +2132,22 @@ dependencies = [ "walkdir", ] +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if 1.0.0", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "jni-sys" version = "0.3.0" @@ -4014,7 +4021,7 @@ dependencies = [ "gtk", "image", "instant", - "jni", + "jni 0.20.0", "lazy_static", "libc", "log", @@ -5057,21 +5064,19 @@ dependencies = [ [[package]] name = "webbrowser" -version = "0.8.3" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa61ff77f695a94d9c8558e0bb5c362a8fd1f27c74663770fbc633acbafedbb6" +checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" dependencies = [ "core-foundation", - "dirs 4.0.0", - "jni", + "home", + "jni 0.21.1", "log", "ndk-context", "objc", "raw-window-handle", "url", "web-sys", - "widestring", - "winapi 0.3.9", ] [[package]] @@ -5187,12 +5192,6 @@ dependencies = [ "rustix 0.38.32", ] -[[package]] -name = "widestring" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" - [[package]] name = "winapi" version = "0.2.8" From 6d5974901b7807fa134ce41a97cea57c3da1f851 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:42:58 +0000 Subject: [PATCH 559/864] chore(deps): update dependency tar to v7.4.2 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0b804bfb..01fdfd2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.4.1" + "tar": "7.4.2" } }, "node_modules/@isaacs/cliui": { @@ -1650,9 +1650,9 @@ } }, "node_modules/tar": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.1.tgz", - "integrity": "sha512-dDJzpQf7Nud96mCs3wtw+XUiWGpi9WHxytSusrg0lYlj/Kr11DnB5hfw5bNDQNzx52JJ2Vy+7l8AFivp6H7ETA==", + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.2.tgz", + "integrity": "sha512-pP4ToLATHpXOrbxOZudW6rnfyPWJZoyERNrpTpQEtW6LkvpXw+WDnpj2GBQX9tyQ6teUyPESyyiOCFgp6HnGdw==", "dev": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 8adee373..9c26292d 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.4.1", + "tar": "7.4.2", "axios": "1.7.2", "axios-retry": "4.4.2" }, From 6325519748c53f703608ac393e972322d9015089 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 01:43:59 +0000 Subject: [PATCH 560/864] fix(deps): update rust crate webbrowser to v1 --- src-tauri/Cargo.lock | 9 +++++---- src-tauri/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 15413c32..54da6e3d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -5064,17 +5064,18 @@ dependencies = [ [[package]] name = "webbrowser" -version = "0.8.15" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" +checksum = "425ba64c1e13b1c6e8c5d2541c8fac10022ca584f33da781db01b5756aef1f4e" dependencies = [ + "block2", "core-foundation", "home", "jni 0.21.1", "log", "ndk-context", - "objc", - "raw-window-handle", + "objc2 0.5.2", + "objc2-foundation", "url", "web-sys", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 55319db5..7e3cd333 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -20,7 +20,7 @@ percent-encoding = "2.3.1" regex = "1.10.4" clipboard-files = "0.1.1" trash = "5" -webbrowser = "0.8" +webbrowser = "1.0" serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3.9", features = ["fileapi"] } From 11d1a4f94318a6ba7c22a757bea4d67e8577264c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jul 2024 18:13:06 +0000 Subject: [PATCH 561/864] build(deps): bump openssl from 0.10.64 to 0.10.66 in /src-tauri Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.64 to 0.10.66. - [Release notes](https://github.com/sfackler/rust-openssl/releases) - [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.64...openssl-v0.10.66) --- updated-dependencies: - dependency-name: openssl dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 54da6e3d..01067a28 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2706,9 +2706,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ "bitflags 2.5.0", "cfg-if 1.0.0", @@ -2738,9 +2738,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.101" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", From 256025b5a4fd4de4588443ff67a53205bdac6bfc Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 26 Jul 2024 11:55:28 +0530 Subject: [PATCH 562/864] chore: release build symbols for bugsnag crash reports --- src-tauri/Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 7e3cd333..6228b43f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -50,3 +50,7 @@ default = ["custom-protocol"] # this feature is used used for production builds where `devPath` points to the filesystem # DO NOT remove this custom-protocol = ["tauri/custom-protocol"] + +[profile.release] +debug = "line-tables-only" +split-debuginfo = "unpacked" From d7c62a531eb03745cf76f798b2268f6fcf513aca Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 26 Jul 2024 12:04:01 +0530 Subject: [PATCH 563/864] fix: dep build fail https://users.rust-lang.org/t/time-crate-compilation-error/111789 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 01067a28..785cf679 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4429,9 +4429,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa 1.0.10", @@ -4450,9 +4450,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", From a2fe288be43978525aba8551cb6c079401f0ff37 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 26 Jul 2024 08:02:34 +0000 Subject: [PATCH 564/864] chore(deps): update dependency tar to v7.4.3 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 01fdfd2e..57e273a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,7 +18,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.4.2" + "tar": "7.4.3" } }, "node_modules/@isaacs/cliui": { @@ -1650,9 +1650,9 @@ } }, "node_modules/tar": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.2.tgz", - "integrity": "sha512-pP4ToLATHpXOrbxOZudW6rnfyPWJZoyERNrpTpQEtW6LkvpXw+WDnpj2GBQX9tyQ6teUyPESyyiOCFgp6HnGdw==", + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", "dev": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 9c26292d..39249685 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "execa": "^9.0.0", "fs-extra": "11.2.0", "shx": "^0.3.4", - "tar": "7.4.2", + "tar": "7.4.3", "axios": "1.7.2", "axios-retry": "4.4.2" }, From 6d1ac2aaf95140c6db0e6dafa084dbd638131e75 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 28 Jul 2024 23:37:05 +0530 Subject: [PATCH 565/864] feat: bugsnag logger impl in rust --- src-tauri/Cargo.lock | 25 ++--- src-tauri/Cargo.toml | 1 + src-tauri/src/bugsnag.rs | 204 +++++++++++++++++++++++++++++++++++++++ src-tauri/src/main.rs | 4 +- 4 files changed, 220 insertions(+), 14 deletions(-) create mode 100644 src-tauri/src/bugsnag.rs diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 785cf679..45d29617 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -308,9 +308,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -488,9 +488,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.90" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" [[package]] name = "cesu8" @@ -1588,9 +1588,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "gio" @@ -2681,9 +2681,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] @@ -3011,6 +3011,7 @@ dependencies = [ name = "phoenix-code-ide" version = "3.9.0" dependencies = [ + "backtrace", "clipboard-files", "dialog", "fix-path-env", @@ -3446,9 +3447,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6228b43f..b44bc3d6 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -21,6 +21,7 @@ regex = "1.10.4" clipboard-files = "0.1.1" trash = "5" webbrowser = "1.0" +backtrace = "0.3.73" serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } winapi = { version = "0.3.9", features = ["fileapi"] } diff --git a/src-tauri/src/bugsnag.rs b/src-tauri/src/bugsnag.rs new file mode 100644 index 00000000..072d9688 --- /dev/null +++ b/src-tauri/src/bugsnag.rs @@ -0,0 +1,204 @@ +use serde::{Serialize, Deserialize}; +use backtrace::{self, Symbol}; +use std::path::Path; +use std::panic::PanicInfo; +use serde_json::to_string_pretty; +use std::collections::HashMap; + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct JsonFrame { + file: String, + line_number: u32, + column_number: u32, + method: String, + in_project: bool, + code: HashMap, +} + + + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct BugsnagEvent { + exceptions: Vec, + breadcrumbs: Vec<()>, + request: HashMap, + threads: Vec<()>, + context: String, + grouping_hash: String, + unhandled: bool, + severity: String, + severity_reason: BugsnagSeverityReason, + project_packages: Vec<()>, + user: HashMap, + app: BugsnagApp, + device: BugsnagDevice, + session: HashMap, + feature_flags: Vec<()>, + meta_data: HashMap, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct BugsnagException { + error_class: String, + message: String, + stacktrace: Vec, + #[serde(rename = "type")] // Specific field that conflicts with a Rust keyword + error_type: String, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct BugsnagSeverityReason { + reason_type: String, + attributes: HashMap, + unhandled_overridden: bool, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct BugsnagApp { + id: String, + version: String, + release_stage: String, + binary_arch: String, + running_on_rosetta: bool, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct BugsnagDevice { + os_name: String, + os_version: String, + time: String, + cpu_abi: Vec, + runtime_versions: HashMap, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct BugsnagNotification { + api_key: String, + payload_version: String, + notifier: BugsnagNotifier, + events: Vec, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct BugsnagNotifier { + name: String, + version: String, + url: String, + dependencies: Vec<()>, +} + +// The function `from_symbol` now returns a JSON string +pub fn from_symbol(trace: &Symbol) -> JsonFrame +{ + let file = trace + .filename() + .unwrap_or_else(|| Path::new("")) + .to_str() + .unwrap_or(""); + let file = if file.is_empty() { "unknown".to_string() } else { file.to_string() }; + + let linenumber = trace.lineno().unwrap_or(0); + let columnnumber = trace.colno().unwrap_or(0); + let method = trace.name() + .map(|name| name.to_string()) + .unwrap_or_else(|| "unknown".to_string()); + + // Example hardcoded code snippet, this part should be dynamically populated based on your context + let mut code_snippet = std::collections::HashMap::new(); + // code_snippet.insert(1, "def a".to_string()); // add here is there are code snippets to show + + JsonFrame { + file: file.to_string(), + line_number: linenumber, + column_number: columnnumber, + method: method.clone(), + in_project: file.starts_with(env!("CARGO_MANIFEST_DIR")), + code: code_snippet, + } +} + +pub fn handle(info: &PanicInfo){ + let message = if let Some(data) = info.payload().downcast_ref::() { + data.to_owned() + } else if let Some(data) = info.payload().downcast_ref::<&str>() { + (*data).to_owned() + } else { + format!("Error: {:?}", info.payload()) + }; + + let mut result: Vec = Vec::new(); + backtrace::trace(|frame| { + backtrace::resolve(frame.ip(), |symbol| { + result.push(from_symbol(&symbol)) + }); + true + }); + let event = BugsnagEvent { + exceptions: vec![ + BugsnagException { + error_class: "Rust_Panic".to_string(), + message: message.to_string(), + stacktrace: result, + error_type: "rust".to_string(), + } + ], + breadcrumbs: vec![], + request: HashMap::new(), + threads: vec![], + context: "rustPanicHandler".to_string(), + grouping_hash: "bugsnag.rs".to_string(), + unhandled: true, + severity: "error".to_string(), + severity_reason: BugsnagSeverityReason { + reason_type: "unhandledError".to_string(), + attributes: HashMap::new(), + unhandled_overridden: false, + }, + project_packages: vec![], + user: HashMap::new(), + app: BugsnagApp { + id: "phcode.io".to_string(), + version: "1.1.3".to_string(), + release_stage: "staging".to_string(), + binary_arch: "x86_64".to_string(), + running_on_rosetta: true, + }, + device: BugsnagDevice { + os_name: "android".to_string(), + os_version: "8.0.1".to_string(), + time: "2018-08-07T10:16:34.564Z".to_string(), + cpu_abi: vec!["x86_64".to_string()], + runtime_versions: HashMap::new(), + }, + session: HashMap::new(), + feature_flags: vec![], + meta_data: HashMap::new(), + }; + + let notification = BugsnagNotification { + api_key: "4dc115247125339aa551f3b11a5bee6b".to_string(), + payload_version: "5".to_string(), + notifier: BugsnagNotifier { + name: "Bugsnag Ruby".to_string(), + version: "1.0.11".to_string(), + url: "https://github.com/bugsnag/bugsnag-ruby".to_string(), + dependencies: vec![], + }, + events: vec![event], + }; + + // Serialize and print the notification object + if let Ok(json_string) = to_string_pretty(¬ification) { + println!("Complete Bugsnag notification JSON:\n{}", json_string); + } else { + println!("Failed to serialize Bugsnag notification."); + } +} \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index e6d40cd9..f2e52c96 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -38,6 +38,7 @@ extern crate percent_encoding; use tauri::http::ResponseBuilder; use tauri::GlobalWindowEvent; mod init; +mod bugsnag; mod utilities; mod boot_config; use trash; @@ -314,8 +315,7 @@ fn main() { println!("Failed to open support_url {}.", support_url); } if should_log_to_bugsnag { - // let _ = bugsnag::panic::handle(&api, panic_info, None); - println!("Log to bugsnag impl pending!"); + bugsnag::handle(panic_info); } })); From 55c5fe22faa269d06a39eaff5adf7121e727881f Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 28 Jul 2024 23:38:10 +0530 Subject: [PATCH 566/864] update bugsnag doc url --- src-tauri/src/bugsnag.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src-tauri/src/bugsnag.rs b/src-tauri/src/bugsnag.rs index 072d9688..dff1cba7 100644 --- a/src-tauri/src/bugsnag.rs +++ b/src-tauri/src/bugsnag.rs @@ -1,3 +1,5 @@ +// https://bugsnagerrorreportingapi.docs.apiary.io/#reference/0/minidump + use serde::{Serialize, Deserialize}; use backtrace::{self, Symbol}; use std::path::Path; From c4bb7954e884eb38f778ebcbedef34dccf1d8d9f Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Jul 2024 00:05:35 +0530 Subject: [PATCH 567/864] send crash event to bugsnag with reqwest and tokio thread --- src-tauri/Cargo.lock | 16 +++++++++++ src-tauri/Cargo.toml | 2 ++ src-tauri/src/bugsnag.rs | 57 ++++++++++++++++++++++++++++++++-------- src-tauri/src/main.rs | 7 ++++- 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 45d29617..96bd684e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3022,6 +3022,7 @@ dependencies = [ "once_cell", "percent-encoding", "regex", + "reqwest", "serde", "serde_json", "tauri", @@ -3030,6 +3031,7 @@ dependencies = [ "tauri-plugin-fs-extra", "tauri-plugin-single-instance", "tauri-plugin-window-state", + "tokio", "trash", "webbrowser", "webkit2gtk", @@ -4491,11 +4493,25 @@ dependencies = [ "libc", "mio", "num_cpus", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2 0.5.6", + "tokio-macros", "windows-sys 0.48.0", ] +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b44bc3d6..1a7b7df2 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -14,6 +14,8 @@ rust-version = "1.70" tauri-build = { version = "1.5.1", features = [] } [dependencies] +reqwest = { version = "0.11", features = ["json"] } +tokio = { version = "1.0", features = ["full"] } serde_json = "1.0.116" once_cell = "1.19.0" percent-encoding = "2.3.1" diff --git a/src-tauri/src/bugsnag.rs b/src-tauri/src/bugsnag.rs index dff1cba7..b4a46d97 100644 --- a/src-tauri/src/bugsnag.rs +++ b/src-tauri/src/bugsnag.rs @@ -3,9 +3,10 @@ use serde::{Serialize, Deserialize}; use backtrace::{self, Symbol}; use std::path::Path; -use std::panic::PanicInfo; use serde_json::to_string_pretty; use std::collections::HashMap; +use reqwest::header::{HeaderMap, CONTENT_TYPE}; +use tokio::runtime::Runtime; #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -114,7 +115,7 @@ pub fn from_symbol(trace: &Symbol) -> JsonFrame .unwrap_or_else(|| "unknown".to_string()); // Example hardcoded code snippet, this part should be dynamically populated based on your context - let mut code_snippet = std::collections::HashMap::new(); + let code_snippet = std::collections::HashMap::new(); // code_snippet.insert(1, "def a".to_string()); // add here is there are code snippets to show JsonFrame { @@ -127,15 +128,37 @@ pub fn from_symbol(trace: &Symbol) -> JsonFrame } } -pub fn handle(info: &PanicInfo){ - let message = if let Some(data) = info.payload().downcast_ref::() { - data.to_owned() - } else if let Some(data) = info.payload().downcast_ref::<&str>() { - (*data).to_owned() +async fn send_bugsnag_notification(notification: BugsnagNotification) -> Result<(), reqwest::Error> { + let client = reqwest::Client::new(); + let headers = construct_headers(); + + let response = client.post("https://notify.bugsnag.com/") + .headers(headers) + .json(¬ification) + .send() + .await?; + + if response.status().is_success() { + println!("Status: {}", response.status()); + if let Ok(resp_body) = response.text().await { + println!("Response: {}", resp_body); + } } else { - format!("Error: {:?}", info.payload()) - }; + eprintln!("Failed to send notification: {}", response.status()); + } + + Ok(()) +} + +fn construct_headers() -> HeaderMap { + let mut headers = HeaderMap::new(); + headers.insert(CONTENT_TYPE, "application/json".parse().unwrap()); + headers.insert("Bugsnag-Api-Key", "4dc115247125339aa551f3b11a5bee6b".parse().unwrap()); + headers.insert("Bugsnag-Payload-Version", "5".parse().unwrap()); + headers +} +pub fn handle(message: &String){ let mut result: Vec = Vec::new(); backtrace::trace(|frame| { backtrace::resolve(frame.ip(), |symbol| { @@ -171,7 +194,7 @@ pub fn handle(info: &PanicInfo){ version: "1.1.3".to_string(), release_stage: "staging".to_string(), binary_arch: "x86_64".to_string(), - running_on_rosetta: true, + running_on_rosetta: false, }, device: BugsnagDevice { os_name: "android".to_string(), @@ -199,8 +222,20 @@ pub fn handle(info: &PanicInfo){ // Serialize and print the notification object if let Ok(json_string) = to_string_pretty(¬ification) { - println!("Complete Bugsnag notification JSON:\n{}", json_string); + println!("Complete Bugsnag error report JSON:\n{}", json_string); } else { println!("Failed to serialize Bugsnag notification."); } + // Spawning a new thread to handle the asynchronous task + let handle = std::thread::spawn(move || { + // Creating a new Tokio runtime + let rt = Runtime::new().unwrap(); + rt.block_on(async { + if let Err(e) = send_bugsnag_notification(notification).await { + eprintln!("Failed to send notification to Bugsnag: {}", e); + } + }); + }); + // Wait for the thread to finish + handle.join().unwrap(); } \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index f2e52c96..66565930 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -315,7 +315,12 @@ fn main() { println!("Failed to open support_url {}.", support_url); } if should_log_to_bugsnag { - bugsnag::handle(panic_info); + let message = if let Some(s) = panic_info.payload().downcast_ref::<&str>() { + s.to_string() + } else { + "Unknown panic message".to_string() + }; + bugsnag::handle(&message); } })); From 1c1560e1f19682cf009cf92120d8c3110cbb551c Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Jul 2024 00:20:14 +0530 Subject: [PATCH 568/864] update bugsnag crash report metadata --- src-tauri/src/bugsnag.rs | 2 +- src-tauri/src/main.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/bugsnag.rs b/src-tauri/src/bugsnag.rs index b4a46d97..e4dc8fc5 100644 --- a/src-tauri/src/bugsnag.rs +++ b/src-tauri/src/bugsnag.rs @@ -178,7 +178,7 @@ pub fn handle(message: &String){ breadcrumbs: vec![], request: HashMap::new(), threads: vec![], - context: "rustPanicHandler".to_string(), + context: message.to_string(), grouping_hash: "bugsnag.rs".to_string(), unhandled: true, severity: "error".to_string(), diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 66565930..da2b65d7 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -314,7 +314,8 @@ fn main() { } else { println!("Failed to open support_url {}.", support_url); } - if should_log_to_bugsnag { + let args: Vec = env::args().collect(); + if should_log_to_bugsnag && !args.contains(&"--runVerify".to_string()) { let message = if let Some(s) = panic_info.payload().downcast_ref::<&str>() { s.to_string() } else { From d87f52c6f0aedd8144e44224a11983b9129a0d3d Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Jul 2024 11:52:08 +0530 Subject: [PATCH 569/864] system info like os name and version in bugsnag crash reports --- src-tauri/Cargo.lock | 25 +++++++++++- src-tauri/Cargo.toml | 2 + src-tauri/src/bugsnag.rs | 85 ++++++++++++++++++++++++++++++++++------ 3 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 96bd684e..f611813c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -554,8 +554,10 @@ checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-targets 0.52.5", ] @@ -1936,7 +1938,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.51.1", + "windows-core 0.52.0", ] [[package]] @@ -3012,6 +3014,7 @@ name = "phoenix-code-ide" version = "3.9.0" dependencies = [ "backtrace", + "chrono", "clipboard-files", "dialog", "fix-path-env", @@ -3025,6 +3028,7 @@ dependencies = [ "reqwest", "serde", "serde_json", + "sys-info", "tauri", "tauri-build", "tauri-plugin-deep-link", @@ -3939,6 +3943,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sys-info" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "sys-locale" version = "0.2.4" @@ -5328,6 +5342,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-core" version = "0.56.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1a7b7df2..a4cbeeb1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,6 +16,8 @@ tauri-build = { version = "1.5.1", features = [] } [dependencies] reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1.0", features = ["full"] } +sys-info = "0.9.1" +chrono = "0.4" serde_json = "1.0.116" once_cell = "1.19.0" percent-encoding = "2.3.1" diff --git a/src-tauri/src/bugsnag.rs b/src-tauri/src/bugsnag.rs index e4dc8fc5..2ab61bd0 100644 --- a/src-tauri/src/bugsnag.rs +++ b/src-tauri/src/bugsnag.rs @@ -7,6 +7,12 @@ use serde_json::to_string_pretty; use std::collections::HashMap; use reqwest::header::{HeaderMap, CONTENT_TYPE}; use tokio::runtime::Runtime; +extern crate sys_info; +extern crate chrono; +use chrono::prelude::*; +use std::fs::File; +use std::io::{self, BufRead, BufReader}; +use std::env; #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -19,8 +25,6 @@ struct JsonFrame { code: HashMap, } - - #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct BugsnagEvent { @@ -158,6 +162,58 @@ fn construct_headers() -> HeaderMap { headers } +fn get_current_time() -> String { + // Get the current UTC time + let now = Utc::now(); + + // Format the time to a string in ISO 8601 format with milliseconds + now.to_rfc3339_opts(SecondsFormat::Millis, true) +} + +fn get_linux_flavor() -> io::Result { + let os_release_file = File::open("/etc/os-release")?; + let reader = BufReader::new(os_release_file); + + // Parse the os-release file to find the PRETTY_NAME + for line in reader.lines() { + let line = line?; + if line.starts_with("PRETTY_NAME") { + // Typically the line looks like `PRETTY_NAME="Ubuntu 20.04 LTS"` + return Ok(line.split('=').nth(1).unwrap_or("\"Unknown\"").trim_matches('"').to_string()); + } + } + + Ok("Unknown Linux Flavor".to_string()) +} + +fn get_sysinfo() -> (String, String, String, String) { + let os_type = sys_info::os_type().unwrap_or_else(|_| "Unknown OS".to_string()); + let mut os_release = sys_info::os_release().unwrap_or_else(|_| "Unknown Version".to_string()); + + #[cfg(target_os = "linux")] + { + // Get the Linux flavor like ubuntu/fedora/arch etc.. too as part of version in Linux + if let Ok(flavor) = get_linux_flavor() { + os_release = format!("{} {}", flavor, os_release); + } + } + + + // Get the machine architecture using the standard library + let arch = std::env::consts::ARCH.to_string(); + + // Get the name of the current executable + let exe_path = env::args().next().unwrap_or_else(|| "Unknown Executable".to_string()); + let exe_name = Path::new(&exe_path) + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or("Unknown Executable") + .to_string(); + + (os_type, os_release, arch, exe_name) +} + + pub fn handle(message: &String){ let mut result: Vec = Vec::new(); backtrace::trace(|frame| { @@ -166,6 +222,9 @@ pub fn handle(message: &String){ }); true }); + let (os_type, os_version, arch, exe_name) = get_sysinfo(); + let app_version = env!("CARGO_PKG_VERSION"); + let current_time = get_current_time(); let event = BugsnagEvent { exceptions: vec![ BugsnagException { @@ -191,15 +250,15 @@ pub fn handle(message: &String){ user: HashMap::new(), app: BugsnagApp { id: "phcode.io".to_string(), - version: "1.1.3".to_string(), - release_stage: "staging".to_string(), - binary_arch: "x86_64".to_string(), + version: app_version.to_string(), + release_stage: exe_name.to_string(), + binary_arch: arch.to_string(), running_on_rosetta: false, }, device: BugsnagDevice { - os_name: "android".to_string(), - os_version: "8.0.1".to_string(), - time: "2018-08-07T10:16:34.564Z".to_string(), + os_name: os_type.to_string(), + os_version: os_version.to_string(), + time: current_time.to_string(), cpu_abi: vec!["x86_64".to_string()], runtime_versions: HashMap::new(), }, @@ -226,8 +285,8 @@ pub fn handle(message: &String){ } else { println!("Failed to serialize Bugsnag notification."); } - // Spawning a new thread to handle the asynchronous task - let handle = std::thread::spawn(move || { + // Spawning a new thread to handle the asynchronous task + let handle = std::thread::spawn(move || { // Creating a new Tokio runtime let rt = Runtime::new().unwrap(); rt.block_on(async { @@ -235,7 +294,7 @@ pub fn handle(message: &String){ eprintln!("Failed to send notification to Bugsnag: {}", e); } }); - }); - // Wait for the thread to finish - handle.join().unwrap(); + }); + // Wait for the thread to finish + handle.join().unwrap(); } \ No newline at end of file From 7b756860f0cdf60edd3a5a7e4af346435547ffef Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Jul 2024 12:24:49 +0530 Subject: [PATCH 570/864] chore: fully anonymize paths in crash reporting in bugsnag to privacy --- src-tauri/src/bugsnag.rs | 47 +++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src-tauri/src/bugsnag.rs b/src-tauri/src/bugsnag.rs index 2ab61bd0..27498e86 100644 --- a/src-tauri/src/bugsnag.rs +++ b/src-tauri/src/bugsnag.rs @@ -102,16 +102,47 @@ struct BugsnagNotifier { dependencies: Vec<()>, } +/// Redacts paths that are not recognized as well-known system paths. +fn redact_path_for_privacy(path: &str) -> String { + let known_paths = [ + // Linux common paths + "/usr", "/lib", "/var", "/etc", "/bin", "/sbin", "/dev", "/opt", "/boot", "/sys", "/proc", + "/run", "/tmp", "/root", + + // macOS common paths + "/Applications", "/System", "/Library", "/private", "/opt", "/sbin", + "/usr/local", + + // Windows common paths + "C:\\Windows", "C:\\Windows\\System32", "C:\\Program Files", "C:\\Program Files (x86)", + "C:\\ProgramData", + ]; + let path_obj = Path::new(path); + + if known_paths.iter().any(|&p| path.starts_with(p)) { + path.to_string() + } else { + format!("{} (path redacted for privacy)", path_obj.file_name().unwrap_or_default().to_str().unwrap_or("Unknown")) + } +} + // The function `from_symbol` now returns a JSON string pub fn from_symbol(trace: &Symbol) -> JsonFrame { - let file = trace - .filename() - .unwrap_or_else(|| Path::new("")) - .to_str() - .unwrap_or(""); - let file = if file.is_empty() { "unknown".to_string() } else { file.to_string() }; - + let manifest_dir = env!("CARGO_MANIFEST_DIR"); + let path = trace.filename() + .and_then(|p| p.to_str()) // Convert Path to &str as soon as possible + .unwrap_or(""); // Deal with None cases early, providing a default &str + + let file = if path.starts_with(manifest_dir) { + Path::new(path) + .strip_prefix(manifest_dir) + .map(|p| p.to_str().unwrap_or("/pathRedacted/Unknown")) + .unwrap_or("/pathRedacted/Unknown") // Use .unwrap_or here + .to_string() + } else { + redact_path_for_privacy(path) + }; let linenumber = trace.lineno().unwrap_or(0); let columnnumber = trace.colno().unwrap_or(0); let method = trace.name() @@ -127,7 +158,7 @@ pub fn from_symbol(trace: &Symbol) -> JsonFrame line_number: linenumber, column_number: columnnumber, method: method.clone(), - in_project: file.starts_with(env!("CARGO_MANIFEST_DIR")), + in_project: path.starts_with(manifest_dir), code: code_snippet, } } From 3da6b2e6cedaaf798965c6fdf0e8a1bc2138657a Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Jul 2024 13:09:14 +0530 Subject: [PATCH 571/864] chore: more to osinfo crate instead of sysinfo as it gived user friendly os names --- src-tauri/Cargo.lock | 12 +----------- src-tauri/Cargo.toml | 2 +- src-tauri/src/bugsnag.rs | 23 +++++------------------ 3 files changed, 7 insertions(+), 30 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f611813c..969ffbce 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3023,12 +3023,12 @@ dependencies = [ "native-dialog", "objc", "once_cell", + "os_info", "percent-encoding", "regex", "reqwest", "serde", "serde_json", - "sys-info", "tauri", "tauri-build", "tauri-plugin-deep-link", @@ -3943,16 +3943,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "sys-info" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "sys-locale" version = "0.2.4" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a4cbeeb1..f1b1a580 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -16,7 +16,7 @@ tauri-build = { version = "1.5.1", features = [] } [dependencies] reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1.0", features = ["full"] } -sys-info = "0.9.1" +os_info = "3" chrono = "0.4" serde_json = "1.0.116" once_cell = "1.19.0" diff --git a/src-tauri/src/bugsnag.rs b/src-tauri/src/bugsnag.rs index 27498e86..59310ddc 100644 --- a/src-tauri/src/bugsnag.rs +++ b/src-tauri/src/bugsnag.rs @@ -7,7 +7,6 @@ use serde_json::to_string_pretty; use std::collections::HashMap; use reqwest::header::{HeaderMap, CONTENT_TYPE}; use tokio::runtime::Runtime; -extern crate sys_info; extern crate chrono; use chrono::prelude::*; use std::fs::File; @@ -218,22 +217,11 @@ fn get_linux_flavor() -> io::Result { } fn get_sysinfo() -> (String, String, String, String) { - let os_type = sys_info::os_type().unwrap_or_else(|_| "Unknown OS".to_string()); - let mut os_release = sys_info::os_release().unwrap_or_else(|_| "Unknown Version".to_string()); - - #[cfg(target_os = "linux")] - { - // Get the Linux flavor like ubuntu/fedora/arch etc.. too as part of version in Linux - if let Ok(flavor) = get_linux_flavor() { - os_release = format!("{} {}", flavor, os_release); - } - } - + let info = os_info::get(); + let os_type = info.os_type().to_string(); + let os_release = info.version().to_string(); - // Get the machine architecture using the standard library - let arch = std::env::consts::ARCH.to_string(); - - // Get the name of the current executable + let arch = info.architecture().unwrap_or("unknown").to_string(); let exe_path = env::args().next().unwrap_or_else(|| "Unknown Executable".to_string()); let exe_name = Path::new(&exe_path) .file_name() @@ -244,7 +232,6 @@ fn get_sysinfo() -> (String, String, String, String) { (os_type, os_release, arch, exe_name) } - pub fn handle(message: &String){ let mut result: Vec = Vec::new(); backtrace::trace(|frame| { @@ -290,7 +277,7 @@ pub fn handle(message: &String){ os_name: os_type.to_string(), os_version: os_version.to_string(), time: current_time.to_string(), - cpu_abi: vec!["x86_64".to_string()], + cpu_abi: vec![arch.to_string()], runtime_versions: HashMap::new(), }, session: HashMap::new(), From f21d587f1d257fa32164315fc36a4d75a1bb2859 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Jul 2024 13:19:58 +0530 Subject: [PATCH 572/864] refactor: remove unused vars and compiler warnings --- src-tauri/src/bugsnag.rs | 20 +------------------- src-tauri/src/main.rs | 4 +++- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/src-tauri/src/bugsnag.rs b/src-tauri/src/bugsnag.rs index 59310ddc..6ea0e875 100644 --- a/src-tauri/src/bugsnag.rs +++ b/src-tauri/src/bugsnag.rs @@ -9,13 +9,11 @@ use reqwest::header::{HeaderMap, CONTENT_TYPE}; use tokio::runtime::Runtime; extern crate chrono; use chrono::prelude::*; -use std::fs::File; -use std::io::{self, BufRead, BufReader}; use std::env; #[derive(Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -struct JsonFrame { +pub struct JsonFrame { file: String, line_number: u32, column_number: u32, @@ -200,22 +198,6 @@ fn get_current_time() -> String { now.to_rfc3339_opts(SecondsFormat::Millis, true) } -fn get_linux_flavor() -> io::Result { - let os_release_file = File::open("/etc/os-release")?; - let reader = BufReader::new(os_release_file); - - // Parse the os-release file to find the PRETTY_NAME - for line in reader.lines() { - let line = line?; - if line.starts_with("PRETTY_NAME") { - // Typically the line looks like `PRETTY_NAME="Ubuntu 20.04 LTS"` - return Ok(line.split('=').nth(1).unwrap_or("\"Unknown\"").trim_matches('"').to_string()); - } - } - - Ok("Unknown Linux Flavor".to_string()) -} - fn get_sysinfo() -> (String, String, String, String) { let info = os_info::get(); let os_type = info.os_type().to_string(); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index da2b65d7..1d1a91a9 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -285,7 +285,7 @@ fn main() { panic_message ); - let mut should_log_to_bugsnag = false; + let should_log_to_bugsnag; #[cfg(target_os = "linux")] { let choice = dialog::Question::new(&error_message) @@ -294,6 +294,8 @@ fn main() { .expect("Could not display dialog box"); if choice == dialog::Choice::Yes { should_log_to_bugsnag = true; + } else { + should_log_to_bugsnag = false; } } From a57d5e914d8ea826fdae3b83f68488dd45087f45 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:58:40 +0000 Subject: [PATCH 573/864] fix(deps): update rust crate tokio to v1.39.2 --- src-tauri/Cargo.lock | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 969ffbce..9e0bc290 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1907,7 +1907,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -2399,13 +2399,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ + "hermit-abi 0.3.9", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2561,16 +2562,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - [[package]] name = "num_enum" version = "0.5.11" @@ -4488,28 +4479,27 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" [[package]] name = "tokio" -version = "1.36.0" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2 0.5.6", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", From 931434dc4a49638499a5e975e5e3cb8c69991673 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 13:35:28 +0000 Subject: [PATCH 574/864] fix(deps): update rust crate chrono to v0.4.38 --- src-tauri/Cargo.lock | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9e0bc290..d2d0f0fe 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -548,9 +548,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1938,7 +1938,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core 0.51.1", ] [[package]] @@ -2225,7 +2225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] @@ -5322,15 +5322,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.5", -] - [[package]] name = "windows-core" version = "0.56.0" From d4d689ad7d9fbef6706d891d855065d4330a872c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 28 Jul 2024 23:18:29 +0000 Subject: [PATCH 575/864] fix(deps): update rust crate serde_json to v1.0.121 --- src-tauri/Cargo.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d2d0f0fe..dbd89996 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3609,12 +3609,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", + "memchr", "ryu", "serde", ] From 74f99f7be3e5c33e61330bcc859a64d7f0f1eedd Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 30 Jul 2024 02:10:41 +0530 Subject: [PATCH 576/864] fix: support for linux mint 22 --- docs/linux/installer.sh | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index e8bd4230..73554809 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -97,40 +97,43 @@ TMP_DIR=$(mktemp -d) # Check Ubuntu Version Function # # Purpose: -# This function checks if the current operating system is Ubuntu 24.04. It does this by reading +# This function checks if the current operating system is Ubuntu 24.04 or Linux Mint 22. It does this by reading # the /etc/os-release file, which contains identification data for the operating system. # # Behavior: # 1. The function first checks if the /etc/os-release file exists. # 2. If the file exists, it sources the file to load the OS identification variables. -# 3. It then checks if the ID variable is set to "ubuntu" and the VERSION_ID variable is set to "24.04". -# 4. If both conditions are met, the function returns 0 (indicating success). -# 5. If the conditions are not met, the function returns 1 (indicating failure). +# 3. It then checks if the ID variable is set to "ubuntu" and the VERSION_ID variable is set to "24.04", +# or if the ID variable is set to "linuxmint" and the VERSION_ID variable is set to "22". +# 4. If either set of conditions is met, the function returns 0 (indicating success). +# 5. If neither set of conditions is met, the function returns 1 (indicating failure). # # Usage: -# This function can be called to determine if special handling is needed for Ubuntu 24.04, such as +# This function can be called to determine if special handling is needed for Ubuntu 24.04 or Linux Mint 22, such as # installing additional libraries or making compatibility adjustments. # # Example: # if check_ubuntu_version; then -# echo "Ubuntu 24.04 detected." +# echo "Ubuntu 24.04 or Linux Mint 22 detected." # else -# echo "Not Ubuntu 24.04." +# echo "Neither Ubuntu 24.04 nor Linux Mint 22." # fi # # Notes: # - This function assumes that the /etc/os-release file follows the standard format for Linux OS # identification. + check_ubuntu_version() { if [ -f /etc/os-release ]; then . /etc/os-release - if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]]; then - return 0 # Ubuntu 24.04 detected + if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]] || [[ "$ID" = "linuxmint" && "$VERSION_ID" = "22" ]]; then + return 0 # Ubuntu 24.04 or Linux Mint 22 detected fi fi - return 1 # Not Ubuntu 24.04 + return 1 # Neither Ubuntu 24.04 nor Linux Mint 22 } + # Create Invocation Script Function # # Purpose: From 9666112183afa4d42e7e2f2718e8a93410e98659 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 31 Jul 2024 15:15:27 +0530 Subject: [PATCH 577/864] fix:added support for kali linux --- docs/linux/installer.sh | 44 ++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 73554809..8ac10ed3 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -94,46 +94,50 @@ trap cleanup EXIT # Register the cleanup function to be called on script exit. TMP_DIR=$(mktemp -d) -# Check Ubuntu Version Function +# Check OS Version Function # # Purpose: -# This function checks if the current operating system is Ubuntu 24.04 or Linux Mint 22. It does this by reading -# the /etc/os-release file, which contains identification data for the operating system. +# This function checks if the current operating system is Ubuntu 24.04, Linux Mint 22, or Kali Linux 2024.2 or newer. +# It reads the /etc/os-release file, which contains identification data for the operating system. # # Behavior: # 1. The function first checks if the /etc/os-release file exists. # 2. If the file exists, it sources the file to load the OS identification variables. -# 3. It then checks if the ID variable is set to "ubuntu" and the VERSION_ID variable is set to "24.04", -# or if the ID variable is set to "linuxmint" and the VERSION_ID variable is set to "22". -# 4. If either set of conditions is met, the function returns 0 (indicating success). -# 5. If neither set of conditions is met, the function returns 1 (indicating failure). +# 3. It then checks if: +# - The ID variable is set to "ubuntu" and the VERSION_ID variable is "24.04", +# - The ID variable is "linuxmint" and the VERSION_ID is "22", +# - The ID variable is "kali" and the VERSION_ID is "2024.2" or newer. +# 4. If any of these conditions are met, the function returns 0 (indicating success). +# 5. If none of these conditions are met, the function returns 1 (indicating failure). # # Usage: -# This function can be called to determine if special handling is needed for Ubuntu 24.04 or Linux Mint 22, such as -# installing additional libraries or making compatibility adjustments. +# This function can be called to determine if special handling is needed for these specific versions of +# Ubuntu, Linux Mint, or Kali Linux, such as installing additional libraries or making compatibility adjustments. # # Example: -# if check_ubuntu_version; then -# echo "Ubuntu 24.04 or Linux Mint 22 detected." +# if check_os_version; then +# echo "Supported OS version detected." # else -# echo "Neither Ubuntu 24.04 nor Linux Mint 22." +# echo "Unsupported OS version." # fi # # Notes: # - This function assumes that the /etc/os-release file follows the standard format for Linux OS -# identification. +# identification and that the distribution's identifiers are consistent with those specified in the script. -check_ubuntu_version() { + +check_os_version() { if [ -f /etc/os-release ]; then . /etc/os-release - if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]] || [[ "$ID" = "linuxmint" && "$VERSION_ID" = "22" ]]; then - return 0 # Ubuntu 24.04 or Linux Mint 22 detected + if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]] || + [[ "$ID" = "linuxmint" && "$VERSION_ID" = "22" ]] || + ([[ "$ID" = "kali" ]] && [[ "$VERSION_ID" > "2024.2" ]] || [[ "$VERSION_ID" == "2024.2" ]]); then + return 0 # Ubuntu 24.04, Linux Mint 22, or Kali Linux 2024.2 or newer detected fi fi - return 1 # Neither Ubuntu 24.04 nor Linux Mint 22 + return 1 # None of the specified versions detected } - # Create Invocation Script Function # # Purpose: @@ -304,7 +308,7 @@ download_and_install_gtk() { # - This piece of code should only be executed if the package manager does not distribute # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. - local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.2/" + local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.3/" local GTK_FILE="gtk.tar.xz" local WEBKIT2GTK_FILE="webkit2gtk-4.0.tar.xz" @@ -456,7 +460,7 @@ verify_and_install_dependencies() { echo "Application launch verification successful." return 0 else - if check_ubuntu_version; then + if check_os_version; then echo -e "${YELLOW}Ubuntu 24.04 detected. Attempting to download and install GTK and WebKit2GTK...${RESET}" download_and_install_gtk create_launch_script_with_gtk "$TMP_DIR/phoenix-code" From d75cfec0a6ce5d6c509c9fd1d752a36415f59b1b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 22:39:06 +0000 Subject: [PATCH 578/864] fix(deps): update rust crate serde_json to v1.0.122 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index dbd89996..d52928c9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3609,9 +3609,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.121" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" +checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", From 9c0041d248c103fe645fb8a009bd3e5f704e4826 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:29:56 +0000 Subject: [PATCH 579/864] chore(deps): update dependency axios to v1.7.3 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 57e273a5..a9d46963 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.5.14", "adm-zip": "0.5.14", - "axios": "1.7.2", + "axios": "1.7.3", "axios-retry": "4.4.2", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -407,9 +407,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", - "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz", + "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 39249685..ce999c36 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "7.4.3", - "axios": "1.7.2", + "axios": "1.7.3", "axios-retry": "4.4.2" }, "phoenixRepo": { From 9745ad2b37ce8b256e5438376aa93a1333194bed Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 17:06:30 +0000 Subject: [PATCH 580/864] fix(deps): update rust crate regex to v1.10.6 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d52928c9..bc900c7a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3323,9 +3323,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", From b9bc64c2f4360b089a3340a34f37e41863291595 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:43:58 +0000 Subject: [PATCH 581/864] chore(deps): update dependency adm-zip to v0.5.15 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index a9d46963..3feb0a16 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.5.14", - "adm-zip": "0.5.14", + "adm-zip": "0.5.15", "axios": "1.7.3", "axios-retry": "4.4.2", "chalk": "^5.3.0", @@ -357,9 +357,9 @@ } }, "node_modules/adm-zip": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.14.tgz", - "integrity": "sha512-DnyqqifT4Jrcvb8USYjp6FHtBpEIz1mnXu6pTRHZ0RL69LbQYiO+0lDFg5+OKA7U29oWSs3a/i8fhn8ZcceIWg==", + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.15.tgz", + "integrity": "sha512-jYPWSeOA8EFoZnucrKCNihqBjoEGQSU4HKgHYQgKNEQ0pQF9a/DYuo/+fAxY76k4qe75LUlLWpAM1QWcBMTOKw==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index ce999c36..f1a9b135 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ }, "devDependencies": { "@tauri-apps/cli": "1.5.14", - "adm-zip": "0.5.14", + "adm-zip": "0.5.15", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", From 85fc6328d5bd38f63da6f18b862f7d018a8a96fb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 03:22:57 +0000 Subject: [PATCH 582/864] fix(deps): update rust crate serde to v1.0.205 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index bc900c7a..76ecb58b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3589,18 +3589,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.205" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.205" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" dependencies = [ "proc-macro2", "quote", From 00329c25aa6f7c445975af078f84f0d19bf93768 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:40:08 +0000 Subject: [PATCH 583/864] chore(deps): update dependency axios-retry to v4.5.0 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3feb0a16..86ceee31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@tauri-apps/cli": "1.5.14", "adm-zip": "0.5.15", "axios": "1.7.3", - "axios-retry": "4.4.2", + "axios-retry": "4.5.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", @@ -419,9 +419,9 @@ } }, "node_modules/axios-retry": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.4.2.tgz", - "integrity": "sha512-2fjo9uDNBQjX8+GMEGOFG5TrLMZ3QijjeRYcgBI2MhrsabnvcIAfLxxIhG7+CCD68vPEQY3IM2llV70ZsrqPvA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", + "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", "dev": true, "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index f1a9b135..1a6bd6e7 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "shx": "^0.3.4", "tar": "7.4.3", "axios": "1.7.3", - "axios-retry": "4.4.2" + "axios-retry": "4.5.0" }, "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", From 188f5a8c3de615059232095e6c0483266fe5c02b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:41:09 +0000 Subject: [PATCH 584/864] fix(deps): update rust crate reqwest to 0.12 --- src-tauri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f1b1a580..bab5e8dd 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -14,7 +14,7 @@ rust-version = "1.70" tauri-build = { version = "1.5.1", features = [] } [dependencies] -reqwest = { version = "0.11", features = ["json"] } +reqwest = { version = "0.12", features = ["json"] } tokio = { version = "1.0", features = ["full"] } os_info = "3" chrono = "0.4" From dbf27a118ef3af739ddb6f6e94674deee75acdc1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 11 Aug 2024 08:09:43 +0000 Subject: [PATCH 585/864] fix(deps): update rust crate serde to v1.0.206 --- src-tauri/Cargo.lock | 360 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 336 insertions(+), 24 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 76ecb58b..0eb122dc 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -333,6 +333,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bincode" version = "1.3.3" @@ -1765,7 +1771,26 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.12", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", "indexmap 2.2.6", "slab", "tokio", @@ -1861,6 +1886,17 @@ dependencies = [ "itoa 1.0.10", ] +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.10", +] + [[package]] name = "http-body" version = "0.4.6" @@ -1868,7 +1904,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -1900,20 +1959,57 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", - "http", - "http-body", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", "httparse", "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.6", "tokio", "tower-service", "tracing", "want", ] +[[package]] +name = "hyper" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.1", + "httparse", + "itoa 1.0.10", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.4.1", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -1921,12 +2017,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.28", "native-tls", "tokio", "tokio-native-tls", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.4.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "hyper 1.4.1", + "pin-project-lite", + "socket2 0.5.6", + "tokio", + "tower", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.60" @@ -2225,7 +2357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -3017,7 +3149,7 @@ dependencies = [ "os_info", "percent-encoding", "regex", - "reqwest", + "reqwest 0.12.5", "serde", "serde_json", "tauri", @@ -3033,6 +3165,26 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3376,11 +3528,11 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-tls", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "hyper 0.14.28", + "hyper-tls 0.5.0", "ipnet", "js-sys", "log", @@ -3389,11 +3541,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-native-tls", @@ -3407,6 +3559,49 @@ dependencies = [ "winreg 0.50.0", ] +[[package]] +name = "reqwest" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-rustls", + "hyper-tls 0.6.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.1.3", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.52.0", +] + [[package]] name = "rfd" version = "0.10.0" @@ -3431,6 +3626,21 @@ dependencies = [ "windows 0.37.0", ] +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if 1.0.0", + "getrandom 0.2.12", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rpassword" version = "2.1.0" @@ -3484,6 +3694,19 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.23.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "1.0.4" @@ -3493,6 +3716,33 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" + +[[package]] +name = "rustls-webpki" +version = "0.102.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -3589,18 +3839,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.205" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" +checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.205" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" +checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" dependencies = [ "proc-macro2", "quote", @@ -3839,6 +4089,12 @@ dependencies = [ "system-deps 5.0.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -3907,6 +4163,12 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -3935,6 +4197,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "sys-locale" version = "0.2.4" @@ -4092,7 +4360,7 @@ dependencies = [ "glob", "gtk", "heck 0.5.0", - "http", + "http 0.2.12", "ignore", "indexmap 1.9.3", "minisign-verify", @@ -4107,7 +4375,7 @@ dependencies = [ "rand 0.8.5", "raw-window-handle", "regex", - "reqwest", + "reqwest 0.11.27", "rfd", "semver", "serde", @@ -4256,7 +4524,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd7ffddf36d450791018e63a3ddf54979b9581d9644c584a5fb5611e6b5f20b4" dependencies = [ "gtk", - "http", + "http 0.2.12", "http-range", "rand 0.8.5", "raw-window-handle", @@ -4517,6 +4785,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.10" @@ -4599,6 +4878,27 @@ dependencies = [ "winnow 0.6.5", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -4756,6 +5056,12 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5752,7 +6058,7 @@ dependencies = [ "glib", "gtk", "html5ever", - "http", + "http 0.2.12", "kuchikiki", "libc", "log", @@ -5898,6 +6204,12 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + [[package]] name = "zip" version = "0.6.6" From f2c6e7a0ef46a34cd4548f91aa4a75152c7be216 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 08:35:02 +0000 Subject: [PATCH 586/864] fix(deps): update rust crate serde_json to v1.0.124 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0eb122dc..e8403086 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3859,9 +3859,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", From 819e276a7a6d16c3e52d1ba7a1707f2abdec2661 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 15:28:54 +0000 Subject: [PATCH 587/864] fix(deps): update rust crate trash to v5.1.0 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e8403086..7fe242ca 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4968,9 +4968,9 @@ dependencies = [ [[package]] name = "trash" -version = "5.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d8fbfb70b1fad5c0b788f9b2e1bf4d04e5ac6efa828f1ed9ee462c50ff9cf05" +checksum = "a154e8323dbd402514d5a3c0f12e0a5bddf72de674b565d58a5535500566428b" dependencies = [ "chrono", "libc", From 8ecc96571613d64f56d42f8208c1551bdb23bb21 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 21:36:48 +0000 Subject: [PATCH 588/864] fix(deps): update rust crate serde to v1.0.207 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7fe242ca..8ef5e650 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3839,18 +3839,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.206" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" +checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.206" +version = "1.0.207" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" +checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" dependencies = [ "proc-macro2", "quote", From 754463a554e83032438ca671f5d62905933e3b7a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 Aug 2024 23:14:27 +0000 Subject: [PATCH 589/864] chore(deps): update dependency axios to v1.7.4 [security] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 86ceee31..319b2f6d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.5.14", "adm-zip": "0.5.15", - "axios": "1.7.3", + "axios": "1.7.4", "axios-retry": "4.5.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -407,9 +407,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.3.tgz", - "integrity": "sha512-Ar7ND9pU99eJ9GpoGQKhKf58GpUOgnzuaB7ueNQ5BMi0p+LZ5oaEnfF999fAArcTIBwXTCHAmGcHOZJaWPq9Nw==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", + "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 1a6bd6e7..467a7191 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "7.4.3", - "axios": "1.7.3", + "axios": "1.7.4", "axios-retry": "4.5.0" }, "phoenixRepo": { From 2f108b755460f5106189c65bc1fe66873fd433f2 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 16 Aug 2024 10:27:54 +0530 Subject: [PATCH 590/864] chore: add chrome_os play store link --- docs/install.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/install.json b/docs/install.json index 842da500..71957c22 100644 --- a/docs/install.json +++ b/docs/install.json @@ -2,6 +2,7 @@ "phcode.io.DownloadURL": { "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_x64-setup.exe", "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_x64.dmg" + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_x64.dmg", + "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa" } } \ No newline at end of file From d83133594ab9923f51cff737c02df9f36f843e06 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 16 Aug 2024 10:31:11 +0530 Subject: [PATCH 591/864] chore: add chrome_os play store link --- .github/workflows/updateNotification.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js index 6d0fe8b4..2670c54d 100644 --- a/.github/workflows/updateNotification.js +++ b/.github/workflows/updateNotification.js @@ -183,7 +183,8 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) "phcode.io.DownloadURL": { "windows_x64": windowsDownloadURL, "mac_m1": macM1DownloadURL, - "mac_intel": macIntelDownloadURL + "mac_intel": macIntelDownloadURL, + "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa" } }; installJSON = JSON.stringify(installJSON, null, 4); From 413fa4948c8e092e4dca8d26c25f8f5285bca8ac Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 Aug 2024 20:30:22 +0000 Subject: [PATCH 592/864] fix(deps): update rust crate serde to v1.0.208 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 8ef5e650..78ec8caa 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3839,18 +3839,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.207" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.207" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", From 3b996793ed0967294bde3d005fbffe85792d0df2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 Aug 2024 21:21:28 +0000 Subject: [PATCH 593/864] chore(deps): update dependency execa to v9.3.1 --- package-lock.json | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 319b2f6d..d50cfe00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -632,9 +632,9 @@ "dev": true }, "node_modules/execa": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.0.tgz", - "integrity": "sha512-l6JFbqnHEadBoVAVpN5dl2yCyfX28WoBAGaoQcNmLLSedOxTxcn2Qa83s8I/PA5i56vWru2OHOtrwF7Om2vqlg==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.1.tgz", + "integrity": "sha512-gdhefCCNy/8tpH/2+ajP9IQc14vXchNdd0weyzSJEFURhRMGncQ+zKFxwjAufIewPEJm9BPOaJnvg2UtlH2gPQ==", "dev": true, "license": "MIT", "dependencies": { @@ -642,7 +642,7 @@ "cross-spawn": "^7.0.3", "figures": "^6.1.0", "get-stream": "^9.0.0", - "human-signals": "^7.0.0", + "human-signals": "^8.0.0", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^5.2.0", @@ -866,10 +866,11 @@ } }, "node_modules/human-signals": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-7.0.0.tgz", - "integrity": "sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz", + "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } From cd0a111da236514a1054f958cc39d4402ee6d00a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 17 Aug 2024 19:25:20 +0000 Subject: [PATCH 594/864] fix(deps): update rust crate tokio to v1.39.3 --- src-tauri/Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 78ec8caa..b9e2c2af 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1966,7 +1966,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -4748,9 +4748,9 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" [[package]] name = "tokio" -version = "1.39.2" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", From 9c973a6d68f75f644b82a9965a6bc05b1943ecd0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 23:08:13 +0000 Subject: [PATCH 595/864] fix(deps): update rust crate reqwest to v0.12.7 --- src-tauri/Cargo.lock | 134 ++++++++++++++++++++++++++++++------------- 1 file changed, 94 insertions(+), 40 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b9e2c2af..6346b54f 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -564,7 +564,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -2357,7 +2357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] @@ -3149,7 +3149,7 @@ dependencies = [ "os_info", "percent-encoding", "regex", - "reqwest 0.12.5", + "reqwest 0.12.7", "serde", "serde_json", "tauri", @@ -3546,7 +3546,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 0.1.2", - "system-configuration", + "system-configuration 0.5.1", "tokio", "tokio-native-tls", "tokio-util", @@ -3561,9 +3561,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ "base64 0.22.1", "bytes", @@ -3591,7 +3591,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper 1.0.1", - "system-configuration", + "system-configuration 0.6.0", "tokio", "tokio-native-tls", "tower-service", @@ -3599,7 +3599,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.52.0", + "windows-registry", ] [[package]] @@ -4202,6 +4202,9 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "sys-locale" @@ -4224,7 +4227,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", "core-foundation", - "system-configuration-sys", + "system-configuration-sys 0.5.0", +] + +[[package]] +name = "system-configuration" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "system-configuration-sys 0.6.0", ] [[package]] @@ -4237,6 +4251,16 @@ dependencies = [ "libc", ] +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "5.0.0" @@ -5607,7 +5631,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132" dependencies = [ "windows-core 0.56.0", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -5637,8 +5661,8 @@ checksum = "4698e52ed2d08f8658ab0c39512a7c00ee5fe2688c65f8c0a4f06750d729f2a6" dependencies = [ "windows-implement 0.56.0", "windows-interface", - "windows-result", - "windows-targets 0.52.5", + "windows-result 0.1.1", + "windows-targets 0.52.6", ] [[package]] @@ -5679,13 +5703,43 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result 0.2.0", + "windows-strings", + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "749f0da9cc72d82e600d8d2e44cadd0b9eedb9038f71a1c58556ac1c5791813b" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", ] [[package]] @@ -5727,7 +5781,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -5762,18 +5816,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -5788,7 +5842,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75aa004c988e080ad34aff5739c39d0312f4684699d6d71fc8a198d057b8b9b4" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -5805,9 +5859,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -5835,9 +5889,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -5865,15 +5919,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -5901,9 +5955,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -5931,9 +5985,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -5949,9 +6003,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -5979,9 +6033,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" From 4debcfade24d847856d8b918b4568fff9dd4c926 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 24 Aug 2024 08:44:32 +0000 Subject: [PATCH 596/864] fix(deps): update rust crate serde to v1.0.209 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 6346b54f..c321ac50 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3839,18 +3839,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", From 8c2e040735689635464f87239e997466a6758791 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 22:00:30 +0000 Subject: [PATCH 597/864] fix(deps): update rust crate serde_json to v1.0.127 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index c321ac50..1d9b40a0 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3859,9 +3859,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.124" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", From 933c72901a779a4d1b2abda6a4484ef6bdb2c4a6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 20:09:21 +0000 Subject: [PATCH 598/864] chore(deps): update tauri monorepo --- package-lock.json | 88 ++++++++++++++++++++-------------------- package.json | 2 +- src-tauri/Cargo.lock | 95 ++++++++++++++++++++++++-------------------- 3 files changed, 96 insertions(+), 89 deletions(-) diff --git a/package-lock.json b/package-lock.json index d50cfe00..92a4070d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.9.0", "hasInstallScript": true, "devDependencies": { - "@tauri-apps/cli": "1.5.14", + "@tauri-apps/cli": "1.6.1", "adm-zip": "0.5.15", "axios": "1.7.4", "axios-retry": "4.5.0", @@ -158,9 +158,9 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.5.14.tgz", - "integrity": "sha512-JOSMKymlg116UdEXSj69eg5p1OtZnQkUE0qIGbtNDO1sk3X/KgBN6+oHBW0BzPStp/W0AjBgrMWCqjHPwEpOug==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.6.1.tgz", + "integrity": "sha512-2S8WGmkz54Z9WxpaFVbUYsTiwx5OIEmdD5DDWRygX9VhaWwZg0y6DctsUtCRVre9I/Un/hTnmqkhZqPamCEx8A==", "dev": true, "license": "Apache-2.0 OR MIT", "bin": { @@ -174,22 +174,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.5.14", - "@tauri-apps/cli-darwin-x64": "1.5.14", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.5.14", - "@tauri-apps/cli-linux-arm64-gnu": "1.5.14", - "@tauri-apps/cli-linux-arm64-musl": "1.5.14", - "@tauri-apps/cli-linux-x64-gnu": "1.5.14", - "@tauri-apps/cli-linux-x64-musl": "1.5.14", - "@tauri-apps/cli-win32-arm64-msvc": "1.5.14", - "@tauri-apps/cli-win32-ia32-msvc": "1.5.14", - "@tauri-apps/cli-win32-x64-msvc": "1.5.14" + "@tauri-apps/cli-darwin-arm64": "1.6.1", + "@tauri-apps/cli-darwin-x64": "1.6.1", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.6.1", + "@tauri-apps/cli-linux-arm64-gnu": "1.6.1", + "@tauri-apps/cli-linux-arm64-musl": "1.6.1", + "@tauri-apps/cli-linux-x64-gnu": "1.6.1", + "@tauri-apps/cli-linux-x64-musl": "1.6.1", + "@tauri-apps/cli-win32-arm64-msvc": "1.6.1", + "@tauri-apps/cli-win32-ia32-msvc": "1.6.1", + "@tauri-apps/cli-win32-x64-msvc": "1.6.1" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.5.14.tgz", - "integrity": "sha512-lxoSOp3KKSqzHJa7iT32dukPGMlfsTuja1xXSgwR8o/fqzpYJY7FY/3ZxesP8HR66FcK+vtqa//HNqeOQ0mHkA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.6.1.tgz", + "integrity": "sha512-n+16Z9qQksBmY55Xwful8GGrw2dlyeqKPsjuNcwKUgVB5a4gIq6K6uUsbhwMUMUA3gqewQMBn44QXbSe5qNKfA==", "cpu": [ "arm64" ], @@ -204,9 +204,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.5.14.tgz", - "integrity": "sha512-EXSwN1n5spfG8FoXuyc90ACtmDJXzaZ1gxyENaq9xEpQoo7j/Q1vb6qXxmr6azKr8zmqY4h08ZFbv3exh93xJg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.6.1.tgz", + "integrity": "sha512-OHzm6qiywv0GEwBDowlzLSuztKE85NMxp2loVynQ4vDoVk6V0jMtQy/N9YvYA0BetvfNTuuAiz3hsTkMHMYm+g==", "cpu": [ "x64" ], @@ -221,9 +221,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.5.14.tgz", - "integrity": "sha512-Yb8BH/KYR7Tl+de40sZPfrqbhcU3Jlu+UPIrnXt05sjn48xqIps74Xjz8zzVp0TuHxUp8FmIGtCVhQgsbrsvvg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.6.1.tgz", + "integrity": "sha512-ZA4ByaiZbrXUbhaoWUVab4lHI2yI1/ucrRO6b9pky6ytgqx37hA/YOWoctD0yaf5giQJQZw160euaBIUOKzRXA==", "cpu": [ "arm" ], @@ -238,9 +238,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.5.14.tgz", - "integrity": "sha512-QrKHP4gRaHiup478rPBZ+BmNd88yze9jMmheoNy9mN1K/aECRmTHO+tWhsxv5moFHZzRhO0QDWxxvTtiaPXaGg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.6.1.tgz", + "integrity": "sha512-VBU4GRJPU9jzzeqaEGLHAJzqQhpl7WnRFyHPR8Qby0D17av3CClJ7nBa+CI3ob3JbIERfJM9kwFHdY9eQpfxnw==", "cpu": [ "arm64" ], @@ -255,9 +255,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.14.tgz", - "integrity": "sha512-Hb1C1VMxmUcyGjW/K/INKF87zzzgLEVRmWZZnQd7M1P4uue4xPyIwUELSdX12Z2jREPgmLW4AXPD0m6wsNu7iw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.6.1.tgz", + "integrity": "sha512-gyMgNZ8fwQFYzrIiHwhmKECkbuAZtzsRyl+bi1Ua11XVWYVUpY8+cNp7Y5ilMJ9AwNFI/HFKjzzua9r+e9FNzw==", "cpu": [ "arm64" ], @@ -272,9 +272,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.5.14.tgz", - "integrity": "sha512-kD9v/UwPDuhIgq2TJj/s2/7rqk+vmExVV6xHPKI8vVbIvlNAOZqmx3fpxjej1241vhJ/piGd/m6q6YMWGsL0oQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.6.1.tgz", + "integrity": "sha512-aYLjLXEBcOf4GUrLBZRQcoLSL3KgCKHwfAyGmTilH4juAw42ZaAYWIZwa59hp2kC4w1XrlmwAzGpi1RESBr5Mw==", "cpu": [ "x64" ], @@ -289,9 +289,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.14.tgz", - "integrity": "sha512-204Drgg9Zx0+THKndqASz4+iPCwqA3gQVF9C0CDIArNXrjPyJjVvW8VP5CHiZYaTNWxlz/ltyxluM6UFWbXNFw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.6.1.tgz", + "integrity": "sha512-j1M7ovICUrBDbrH8CNUwbMe0zk0/IAR7MXRv5PEanktAZ1w/LG3nlO/AhY5/Cbqqo3ziKTcMpe6x0j3aE8jYOA==", "cpu": [ "x64" ], @@ -306,9 +306,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.5.14.tgz", - "integrity": "sha512-sqPSni2MnWNCm+8YZnLdWCclxfSHaYqKuPFSz8q7Tn1G1m/cA9gyPoC1G0esHftY7bu/ZM5lB4kM3I4U0KlLiA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.6.1.tgz", + "integrity": "sha512-yCGT1jXHvZtu+yYPDmDOJDfgsj5EKdBPvya+kmN03BmLfOF+8EWHA9s6yXUdk9pSr6M9OQS0SXocbGDOu5AkMw==", "cpu": [ "arm64" ], @@ -323,9 +323,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.5.14.tgz", - "integrity": "sha512-8xN8W0zTs8oFsQmvYLxHFeqhzVI7oTaPK1xQMc5gbpFP45jN41c21aCXfjnvzT+h90EfCHUF9EWj2HTEJSb7Iw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.6.1.tgz", + "integrity": "sha512-klAt+KNcczC4gxz9vm6tSvFB4iyXVj4r+TtDVhStLCKkAZOVm0ZsFym1kDzltxrB/3xSjgzsgIiEJydN2cP7xw==", "cpu": [ "ia32" ], @@ -340,9 +340,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.5.14", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.5.14.tgz", - "integrity": "sha512-U0slee5tNM2PYECBpPHavLSwkT3szGMZ+qhcikQQbDan84bQdLn/kHWjyXOgLJs4KSve4+KxcrN+AVqj0VyHnw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.6.1.tgz", + "integrity": "sha512-WEzQzBgcaqjZoA5M/KOupHmt8W3QQ20vwETXpGEMPd7spj4eZsRv/2ZDuCz4ELbai1XlIsTITFNe2LlJjzqISA==", "cpu": [ "x64" ], diff --git a/package.json b/package.json index 467a7191..cf9d79a7 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { - "@tauri-apps/cli": "1.5.14", + "@tauri-apps/cli": "1.6.1", "adm-zip": "0.5.15", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1d9b40a0..9291b5d3 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -402,9 +402,9 @@ dependencies = [ [[package]] name = "brotli" -version = "3.5.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" +checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -413,9 +413,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "2.5.1" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -1277,6 +1277,15 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fluent-uri" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17c704e9dbe1ddd863da1e6ff3567795087b1eb201ce80d8fa81162e1516500d" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1966,7 +1975,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -2305,14 +2314,25 @@ dependencies = [ [[package]] name = "json-patch" -version = "1.2.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ff1e1486799e3f64129f8ccad108b38290df9cd7015cd31bed17239f0789d6" +checksum = "5b1fb8864823fad91877e6caea0baca82e49e8db50f8e5c9f9a453e27d3330fc" dependencies = [ + "jsonptr", "serde", "serde_json", "thiserror", - "treediff", +] + +[[package]] +name = "jsonptr" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c6e529149475ca0b2820835d3dce8fcc41c6b943ca608d32f35b449255e4627" +dependencies = [ + "fluent-uri", + "serde", + "serde_json", ] [[package]] @@ -2357,7 +2377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -3934,9 +3954,9 @@ dependencies = [ [[package]] name = "serialize-to-javascript" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9823f2d3b6a81d98228151fdeaf848206a7855a7a042bbf9bf870449a66cafb" +checksum = "04f3666a07a197cdb77cdf306c32be9b7f598d7060d50cfd4d5aa04bfd92f6c5" dependencies = [ "serde", "serde_json", @@ -3945,13 +3965,13 @@ dependencies = [ [[package]] name = "serialize-to-javascript-impl" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74064874e9f6a15f04c1f3cb627902d0e6b410abbf36668afa873c61889f1763" +checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.55", ] [[package]] @@ -4208,15 +4228,11 @@ dependencies = [ [[package]] name = "sys-locale" -version = "0.2.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a11bd9c338fdba09f7881ab41551932ad42e405f61d01e8406baea71c07aee" +checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" dependencies = [ - "js-sys", "libc", - "wasm-bindgen", - "web-sys", - "windows-sys 0.45.0", ] [[package]] @@ -4364,12 +4380,12 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.6.8" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77567d2b3b74de4588d544147142d02297f3eaa171a25a065252141d8597a516" +checksum = "0e33e3ba00a3b05eb6c57ef135781717d33728b48acf914bb05629e74d897d29" dependencies = [ "anyhow", - "base64 0.21.7", + "base64 0.22.1", "bytes", "clap", "cocoa 0.24.1", @@ -4428,9 +4444,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.5.2" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab30cba12974d0f9b09794f61e72cad6da2142d3ceb81e519321bab86ce53312" +checksum = "d5fb5a90a64241ddb7217d3210d844149070a911e87e8a107a707a1d4973f164" dependencies = [ "anyhow", "cargo_toml", @@ -4447,9 +4463,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "1.4.3" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a1d90db526a8cdfd54444ad3f34d8d4d58fa5c536463915942393743bd06f8" +checksum = "93a9e3f5cebf779a63bf24903e714ec91196c307d8249a0008b882424328bcda" dependencies = [ "base64 0.21.7", "brotli", @@ -4473,9 +4489,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.4" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a582d75414250122e4a597b9dd7d3c910a2c77906648fc2ac9353845ff0feec" +checksum = "d1d0e989f54fe06c5ef0875c5e19cf96453d099a0a774d5192ab47e80471cdab" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -4543,9 +4559,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7ffddf36d450791018e63a3ddf54979b9581d9644c584a5fb5611e6b5f20b4" +checksum = "f33fda7d213e239077fad52e96c6b734cecedb30c2382118b64f94cb5103ff3a" dependencies = [ "gtk", "http 0.2.12", @@ -4564,9 +4580,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.8" +version = "0.14.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1989b3b4d611f5428b3414a4abae6fa6df30c7eb8ed33250ca90a5f7e5bb3655" +checksum = "18c447dcd9b0f09c7dc4b752cc33e72788805bfd761fbda5692d30c48289efec" dependencies = [ "arboard", "cocoa 0.24.1", @@ -4585,9 +4601,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.5.4" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "450b17a7102e5d46d4bdabae0d1590fd27953e704e691fc081f06c06d2253b35" +checksum = "83a0c939e88d82903a0a7dfb28388b12a3c03504d6bd6086550edaa3b6d8beaa" dependencies = [ "brotli", "ctor", @@ -5021,15 +5037,6 @@ dependencies = [ "petgraph", ] -[[package]] -name = "treediff" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d127780145176e2b5d16611cc25a900150e86e9fd79d3bde6ff3a37359c9cb5" -dependencies = [ - "serde_json", -] - [[package]] name = "try-lock" version = "0.2.5" From de656c5ad1c3b9a4aae4a3f32d0cb054b3f93757 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 14:18:45 +0000 Subject: [PATCH 599/864] chore(deps): update dependency axios to v1.7.5 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 92a4070d..bf2448de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.6.1", "adm-zip": "0.5.15", - "axios": "1.7.4", + "axios": "1.7.5", "axios-retry": "4.5.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -407,9 +407,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz", - "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", + "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index cf9d79a7..ab7ebf2c 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "7.4.3", - "axios": "1.7.4", + "axios": "1.7.5", "axios-retry": "4.5.0" }, "phoenixRepo": { From 17c8fcc2a58adfd428216315a6d4ed6702a7f484 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 30 Aug 2024 08:19:11 +0000 Subject: [PATCH 600/864] chore(deps): update dependency adm-zip to v0.5.16 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index bf2448de..ad7fba5d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.1", - "adm-zip": "0.5.15", + "adm-zip": "0.5.16", "axios": "1.7.5", "axios-retry": "4.5.0", "chalk": "^5.3.0", @@ -357,9 +357,9 @@ } }, "node_modules/adm-zip": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.15.tgz", - "integrity": "sha512-jYPWSeOA8EFoZnucrKCNihqBjoEGQSU4HKgHYQgKNEQ0pQF9a/DYuo/+fAxY76k4qe75LUlLWpAM1QWcBMTOKw==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", "dev": true, "license": "MIT", "engines": { diff --git a/package.json b/package.json index ab7ebf2c..77f09086 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ }, "devDependencies": { "@tauri-apps/cli": "1.6.1", - "adm-zip": "0.5.15", + "adm-zip": "0.5.16", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", From d6ab03b65fe3269d1c5000b742941505edbc40c9 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Sep 2024 22:36:00 +0530 Subject: [PATCH 601/864] chore: add _open_url_in_browser_win API --- src-tauri/src/main.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1d1a91a9..f9e30582 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -114,6 +114,31 @@ fn _get_clipboard_files() -> Option> { } } +#[tauri::command] +fn _open_url_in_browser_win(url: String, browser: String) -> Result<(), String> { + #[cfg(target_os = "windows")] + { + let browser_path = match browser.as_str() { + "firefox" => "C:\\Program Files\\Mozilla Firefox\\firefox.exe", + "chrome" => "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", + "edge" => "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe", + _ => return Err(format!("Browser '{}' is not supported.", browser)) + }; + + // Spawn the browser process without waiting for it to finish + Command::new(browser_path) + .arg(url) + .spawn() + .map_err(|e| format!("Failed to open URL in {}: {}", browser, e.to_string()))?; + + Ok(()) + } + #[cfg(not(target_os = "windows"))] + { + Err("This API is only supported on Windows.".to_string()) + } +} + // this in memory hashmap is used to supplement the LMDB node layer in a multi window environment. struct Storage { map: Mutex>, @@ -412,7 +437,8 @@ fn main() { toggle_devtools, console_log, console_error, _get_commandline_args, get_current_working_dir, _get_window_labels, put_item, get_item, get_all_items, delete_item, - _get_windows_drives, _rename_path, show_in_folder, move_to_trash, zoom_window, _get_clipboard_files]) + _get_windows_drives, _rename_path, show_in_folder, move_to_trash, zoom_window, + _get_clipboard_files, _open_url_in_browser_win]) .setup(|app| { init::init_app(app); #[cfg(target_os = "linux")] From 6b125b8354d257a5db084eadd2c5751ec9167e59 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 6 Sep 2024 05:39:39 +0000 Subject: [PATCH 602/864] ci: update phcode version to 3.9.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 77f09086..98b93ff9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.9.0", + "version": "3.9.1", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "6105db879aa3f2fe4aa79b5aa0f96eb5384b15b1" + "commit": "a89b4c9a81a5d90eb0052d9d157093cc0ce89231" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index bab5e8dd..f670f7b0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.9.0" +version = "3.9.1" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index b5b976fd..3e3e5e37 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.9.0" + "version": "3.9.1" }, "tauri": { "allowlist": { From 614791c74cb8fc58a8347f14b76d7ca5948414ab Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 6 Sep 2024 07:16:50 +0000 Subject: [PATCH 603/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 3edf50c2..5a199195 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,19 +1,19 @@ { - "version": "3.8.4", - "notes": "Experimental build. not to be used.", - "pub_date": "2024-06-22T17:40:08.687Z", + "version": "3.9.1", + "notes": "# prerelase for testing only!\r\n\r\nSeptember release(3.9) of Phoenix Code is now available.\r\n\r\nThis month's core theme is `App robustness` and `stability` improvements.\r\nWe have also added several `HTML and Text Editing` workflow improvements.\r\n\r\n## Now Available on ChromeOS\r\n\r\nAll new native ChromeOS app is now available on the Google Play Store.\r\nThe ChromeOS app is a highly requested feature and is specially made for education and student use.\r\n\r\n[![google play icon (1)](https://github.com/user-attachments/assets/0a7f20ce-653c-43a8-ac3e-3875ea74df5b)](https://play.google.com/store/apps/details?id=prod.phcode.twa)\r\n\r\n## Auto rename start and end of HTML/XML/SVG tags\r\n\r\nAutomatically rename paired HTML/XML/SVG tags as you type at the start or end of the tag. [Read more...](https://docs.phcode.dev/docs/editing-text/#auto-rename-tag)\r\n\r\n![tag sync](https://github.com/user-attachments/assets/ad82db8c-df1c-4c83-a5db-145caab539ec)\r\n\r\n## Auto Tab and Spacing detection\r\n\r\nPhoenix Code can now automatically detect and apply the indentation style (tabs or spaces) based on the existing code in the file.\r\n[Read more...](https://docs.phcode.dev/docs/editing-text/#auto-space-detection)\r\n\r\n![image](https://github.com/user-attachments/assets/0adc47c5-a561-4002-bffb-d7bcde999b9d)\r\n\r\n## UX Improvements\r\n\r\n- `Reopen closed files` option added to `File` menu. Shortcut: `Ctrl-Shift-T`, or (`Cmd-Shift-T` on Mac).\r\n- `Go to Next Problem` and `Go to Previous Problem` option added to [`Navigate` menu.](https://github.com/phcode-dev/phoenix/pull/1732)\r\n- [Tab key press to insert code hints](https://github.com/orgs/phcode-dev/discussions/1809)\r\n- `window.alert`, `window.confirm` and `window.prompt` APIs [will work in live preview](https://github.com/phcode-dev/phoenix/pull/1814)\r\n- Clicking on live preview no longer automatically switches from your [current unrelated file to the main HTML file.](https://github.com/phcode-dev/phoenix/pull/1800)\r\n- Live preview usability and navigation improvements - ([1](https://github.com/phcode-dev/phoenix/pull/1741), [2](https://github.com/phcode-dev/phoenix/pull/1760))\r\n- Increase/Decrease font size will [change the Editor Font size Only](https://github.com/phcode-dev/phoenix/pull/1799).\r\n- Fixed issue where code folding markers disappear when hovering over gutter in dark theme.\r\n- `.cjs` and `.mjs` files support as javascript files.\r\n- Support for `shtml` custom server live preview.\r\n\r\n## Stability Improvements\r\n\r\n- [Fixes node crashes after wakeup from sleep in Windows/Mac.](https://github.com/phcode-dev/phoenix/issues/1791) \r\n- [Kaspersky AV trojan horse false positive mitigation.](https://github.com/phcode-dev/phoenix/issues/1821)\r\n- [Corrupt preferences auto reset.](https://github.com/phcode-dev/phoenix/pull/1818)\r\n- [Boot time crash recovery.](https://github.com/phcode-dev/phoenix/pull/1812)\r\n- Phoenix Code won't start in [some Fedora/other Linux distros.](https://github.com/phcode-dev/phoenix/pull/1740)\r\n\r\n## Update on Release Schedule\r\n\r\nIn the past, we've released Phoenix Code updates on a monthly basis. However, last month we encountered an issue with our release that led to stability problems for our users.\r\n\r\nTo address this, we've taken a step back to reevaluate our release process and make improvements to ensure greater robustness and reliability going forward.\r\n\r\nAs a result, we've decided to slow down the desktop release schedule to once every two months. This will allow us to thoroughly test each update and deliver a more stable experience.\r\n\r\nWe apologize for any inconvenience caused by the previous release and appreciate your patience and understanding as we work to improve the quality of Phoenix Code.\r\n\r\nWe look forward to bringing you new features and improvements in a more controlled and reliable manner.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", + "pub_date": "2024-09-06T06:32:12.965Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnQyUEprczJ6RUhxcXUrMmJGYVZsai8wNit0aWZDWnMweDdtaGx5ZVpVK2w5MGFsNnNkckZXZ0pNSDJVODU0cWt3d1FlY1h2bWJIZWdZQ3NFZUtHcUFVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5MDc3Mjk1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjguNF94NjQtc2V0dXAubnNpcy56aXAKSFZrc0FxWjA1MytjWDZTays3cGJVUkV5TjZtaU5FSzc0aTFPazRFWm5Iaml4VmdSR2lTd0pvd2xRSmV0cy85VDVJOVpqbmdsYzhubEdSK0UrVkxaQmc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.4/Phoenix.Code.Experimental.Build_3.8.4_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1VMklPT0w3YWJtZFB4d0Z4bGE2YlRSbTdPVHprdnYzejUvUHRHb3REdHhkTVF1Qy9aTGRWZzdUdG9VWXE5ajBHeHAvSzNVeklxeUwyTFNzdDhqQ1FzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1NjAzMTkwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjkuMV94NjQtc2V0dXAubnNpcy56aXAKTnFObk9OUXh0SUZzaDBBbi9NQTR2Z1ZqOHU3Z0hhWjNkcy95N28ycDgzT01wVjl2ayt6dWlNUDVRQitLK1djZlI5VE5qM3hsMTlIUkJGN0haYXliQmc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.9.1/Phoenix.Code.Experimental.Build_3.9.1_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1ZdWlBUGFxOEcyVFhqMm11akpvMUVDNXZ2SE96YkdpU0h3UnFLNDNhMnZhSHZObkl2S2k4b2ZHdHMzcVAzWEFvcGdzajFNdWlOOHRsTFJrSUxEQkFrPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5MDc3NTM2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CkxsaVdzM2N0UFg0ajBZUmhKL3RCb2NjcDVOdmdPQXl2ZzhqOW03R09kZXlEaFVmbDg1eHdVbzdYRy9VQ2Z2T2tIckorM2NmY3l5RE5ZKytsbHh5bUJRPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.4/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtvc1FRMTRsYjZiTm5FNDhvRlVoVDJZUGt1ZXd6dzRSR3ZhNms1MGUrNDlhNU1VaTBEcWVKZ2VCU0oxREszMG9ONmE5TWQrcUYxSGZEc1dIUktsdndzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1NjAzNTI4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cm83SU93YUJwL0tKRUZobFozS3pnYTNkWUtZM2FzRG9GLzErbVkrdWlZMEhFSEVZaUZpbUp6NTF0NTVsZVlFS2dZT2pnYndXT0hHcTFUNERLR0JlUUN3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.9.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZNZ0ZreDFXOEZJbEp1dWdoWkVlKzREK3VrMEZqQ3pWVDdEM3pIUDl5aGZQUXEzVFZvVXQ2V3VNekp6dmFDUGtsRERpS0JDRVlCRnFVVkMxbWV6V1FVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5MDc3OTkzCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cmo5OEYzV2hVZTQ0cUVGa3VHL0Vnai9rdmp3S1NCRDVaUDNOSHJPdUlPRHVaWDZlc2R6c3ZjS24zNHRaalVudXZ4MlBGTTlMampWdy9MU2pTa3lvbUFBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.8.4/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxvQW9NMStXbFFuWm0rbjZnamUwbjZRelVVTjg2Vzh5L2RIa1RZS2VsK2IxVDJJSWlXZGJxQndZNzkvRVhqeFBMUUc4SUZGVnprM1VGVGRzNERNQndNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1NjA0MzI0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnZ4Y05XMDY5Mks5Zy9CR0N3RXBWN0ZydmhWbkRBZDFwREViL2pnU2hHWkIzTEdPU1hJR0xVeDNiTHl5bVkwMjdNUXlvSGt0T3lFMUgyb1A0UFo3WkRBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.9.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From 8e0afaef87688aeb08f62399ebb44456fa31ebaf Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 7 Sep 2024 15:30:10 +0000 Subject: [PATCH 604/864] ci: update phcode version to 3.9.2 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 98b93ff9..634e36ed 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.9.1", + "version": "3.9.2", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "a89b4c9a81a5d90eb0052d9d157093cc0ce89231" + "commit": "a089d090ae7cb41519445d3931f94ae67ff57dd9" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f670f7b0..3ece03bc 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.9.1" +version = "3.9.2" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 3e3e5e37..6bff5ac9 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.9.1" + "version": "3.9.2" }, "tauri": { "allowlist": { From 46b070b3e40dfe1b5708505ff3e47d3720d7cc66 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 8 Sep 2024 19:49:55 +0530 Subject: [PATCH 605/864] fix: linux installer was failing in arch --- docs/linux/installer.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 8ac10ed3..abf50c58 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -263,8 +263,7 @@ install_dependencies() { ;; arch|manjaro) echo "Detected an Arch Linux based distribution." - sudo pacman -Syu - sudo pacman -S webkit2gtk gtk3 + yes | sudo pacman -S webkit2gtk gtk3 ;; *) echo "Unsupported distribution. Please manually install the required dependencies." From a4b2d2a1bc9f89d9af5eb658a674522626670314 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 9 Sep 2024 05:49:03 +0000 Subject: [PATCH 606/864] ci: update phcode version to 3.9.3 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 634e36ed..8fd28dbe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.9.2", + "version": "3.9.3", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "a089d090ae7cb41519445d3931f94ae67ff57dd9" + "commit": "3741db83bf32d5c9626428f38915c642b2eefaa2" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3ece03bc..f4594bcd 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.9.2" +version = "3.9.3" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6bff5ac9..19b3d53f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.9.2" + "version": "3.9.3" }, "tauri": { "allowlist": { From ddef6bc2579c6eda5cdbe16012c9d697658750db Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 9 Sep 2024 07:07:12 +0000 Subject: [PATCH 607/864] ci: update phcode version to 3.9.4 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 8fd28dbe..c8344f72 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.9.3", + "version": "3.9.4", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "3741db83bf32d5c9626428f38915c642b2eefaa2" + "commit": "1c25b224e755da32170e7441eea7e2b73ade6c20" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f4594bcd..4e55b508 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.9.3" +version = "3.9.4" description = "Phoenix is a modern open-source IDE for the web, built for the browser." authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 19b3d53f..1d2f5ca4 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.9.3" + "version": "3.9.4" }, "tauri": { "allowlist": { From 60c7e2f55423fcd75cf8cdf013dd4d0e9b92f20d Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 10 Sep 2024 07:41:31 +0000 Subject: [PATCH 608/864] ci: tauri release update notification json --- docs/install.json | 6 +++--- docs/tauri/update-latest-stable-prod.json | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/install.json b/docs/install.json index 71957c22..6183ebb1 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,8 +1,8 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_x64.dmg", + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_3.9.4_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_3.9.4_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_3.9.4_x64.dmg", "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 6e87f6c5..de4827e4 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,19 +1,19 @@ { - "version": "3.8.8", - "notes": "June release(3.8) of Phoenix Code is now available.\r\n\r\nThis month's release is all about `Drag and Drop`, `HTML assistance` and `ESLint`. We've also addressed numerous feature requests and bug reports, along with improving app UX and stability.\r\n\r\n#### Drag and Drop Files and Folders in Desktop Apps - Experimental\r\n\r\nDrag files from Explorer (Windows) or Finder (Mac) and drop them into Phoenix Code to open individual files. Drop a folder to open it as a project.\r\n\r\n> Note: This feature is currently disabled on Linux due to UI issues in some Linux distributions. To enable it, select menu\r\n> `Debug -> Experimental Features -> Drag And Drop Files.`\r\n\r\n> This feature is not available in the browser version @ phcode.dev\r\n\r\n![drag and drop](https://github.com/phcode-dev/phoenix/assets/5336369/ddd96ff7-bc99-46a6-a62d-6f6f5b78438b)\r\n\r\n#### HTML Validation\r\n\r\nWe have added HTML Validator to help you find errors like duplicate IDs, unrecognized tags, and more. [Read more here.](https://docs.phcode.dev/docs/Features/Problems%20Panel/html-lint/)\r\n\r\n![HTML validate](https://github.com/phcode-dev/phoenix/assets/5336369/5bc4a1cc-2429-477c-83ca-91f19dcc0b0f)\r\n\r\n#### ESLint Support\r\n\r\nAll new and simplified ESLint experience that displays all ESLint errors in a file. Fix one or all errors with a single click. To enable, open a project that uses ESLint in Phoenix Code. [Read more here.](https://docs.phcode.dev/docs/Features/Problems%20Panel/ESLint/)\r\n\r\n![image](https://github.com/phcode-dev/phoenix/assets/5336369/eb00691a-a0b4-4c1a-9209-d78fc7db764d)\r\n\r\n#### Notable Changes\r\n\r\n- **Non-Intrusive Automatic Updates:** Updates are now installed in the background with no more distracting dialogs when an update is available.\r\n- **Case-Sensitive File Renaming:** Renaming files to a different case, such as `a.txt` to `A.TXT`, is now supported.\r\n- `File > New Project` is now renamed to `Start Project`.\r\n- Increased stability and app startup experience.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", - "pub_date": "2024-06-27T08:59:05.475Z", + "version": "3.9.4", + "notes": "September release(3.9) of Phoenix Code is now available.\r\n\r\nThis month's core theme is `App robustness` and `stability` improvements.\r\nWe have also added several `HTML and Text Editing` workflow improvements.\r\n\r\n## Now Available on ChromeOS\r\n\r\nAll new native ChromeOS app is now available on the Google Play Store.\r\nThe ChromeOS app is a highly requested feature and is specially made for education and student use.\r\n\r\n[![google play icon (1)](https://github.com/user-attachments/assets/0a7f20ce-653c-43a8-ac3e-3875ea74df5b)](https://play.google.com/store/apps/details?id=prod.phcode.twa)\r\n\r\n## Auto rename start and end of HTML/XML/SVG tags\r\n\r\nAutomatically rename paired HTML/XML/SVG tags as you type at the start or end of the tag. [Read more...](https://docs.phcode.dev/docs/editing-text/#auto-rename-tag)\r\n\r\n![tag sync](https://github.com/user-attachments/assets/ad82db8c-df1c-4c83-a5db-145caab539ec)\r\n\r\n## Auto Tab and Spacing detection\r\n\r\nPhoenix Code can now automatically detect and apply the indentation style (tabs or spaces) based on the existing code in the file.\r\n[Read more...](https://docs.phcode.dev/docs/editing-text/#auto-space-detection)\r\n\r\n![image](https://github.com/user-attachments/assets/0adc47c5-a561-4002-bffb-d7bcde999b9d)\r\n\r\n## UX Improvements\r\n\r\n- `Reopen closed files` option added to `File` menu. Shortcut: `Ctrl-Shift-T`, or (`Cmd-Shift-T` on Mac).\r\n- `Go to Next Problem` and `Go to Previous Problem` option added to [`Navigate` menu.](https://github.com/phcode-dev/phoenix/pull/1732)\r\n- [Tab key press to insert code hints](https://github.com/orgs/phcode-dev/discussions/1809)\r\n- `window.alert`, `window.confirm` and `window.prompt` APIs [will work in live preview](https://github.com/phcode-dev/phoenix/pull/1814)\r\n- Clicking on live preview no longer automatically switches from your [current unrelated file to the main HTML file.](https://github.com/phcode-dev/phoenix/pull/1800)\r\n- Live preview usability and navigation improvements - ([1](https://github.com/phcode-dev/phoenix/pull/1741), [2](https://github.com/phcode-dev/phoenix/pull/1760))\r\n- Increase/Decrease font size will [change the Editor Font size Only](https://github.com/phcode-dev/phoenix/pull/1799).\r\n- Fixed issue where code folding markers disappear when hovering over gutter in dark theme.\r\n- `.cjs` and `.mjs` files support as javascript files.\r\n- Support for `shtml` custom server live preview.\r\n\r\n## Stability Improvements\r\n\r\n- [Fixes node crashes after wakeup from sleep in Windows/Mac.](https://github.com/phcode-dev/phoenix/issues/1791) \r\n- [Kaspersky AV trojan horse false positive mitigation.](https://github.com/phcode-dev/phoenix/issues/1821)\r\n- [Corrupt preferences auto reset.](https://github.com/phcode-dev/phoenix/pull/1818)\r\n- [Boot time crash recovery.](https://github.com/phcode-dev/phoenix/pull/1812)\r\n- Phoenix Code won't start in [some Fedora/other Linux distros.](https://github.com/phcode-dev/phoenix/pull/1740)\r\n\r\n## Update on Release Schedule\r\n\r\nIn the past, we've released Phoenix Code updates on a monthly basis. However, last month we encountered an issue with our release that led to stability problems for our users.\r\n\r\nTo address this, we've taken a step back to reevaluate our release process and make improvements to ensure greater robustness and reliability going forward.\r\n\r\nAs a result, we've decided to slow down the desktop release schedule to once every two months. This will allow us to thoroughly test each update and deliver a more stable experience.\r\n\r\nWe apologize for any inconvenience caused by the previous release and appreciate your patience and understanding as we work to improve the quality of Phoenix Code.\r\n\r\nWe look forward to bringing you new features and improvements in a more controlled and reliable manner.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", + "pub_date": "2024-09-09T07:51:47.896Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnJ2WlhnNlcrVWdYZE1nSmMvd0F5VEVWTTkyeVk5dWxnV0piRXpXNTc4WVFTVk1RUytxanZPZENDY3FXS1NsejZBd093ZzFXMGRvSFE1STNQMU9pMVFFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5NDc4MDI5CWZpbGU6UGhvZW5peCBDb2RlXzMuOC44X3g2NC1zZXR1cC5uc2lzLnppcAppS1NZVUJrUFp3TTk3QjY4UG1TY0RIZ2dqMldEbStvRzBRVnV4MnAxWDlENWFkU1k5N01SYzRTcnpvYVBWa0VydFFvTkNhSlNEWDVuR0IrRnpWSW1DZz09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_3.8.8_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNsRjM5a2JudEs3VFNtMDIrK0pEa2QwYTVwaTFpTUR6UTBNV2cvbW5ZejRKTmxtdTByT3BHVDdsTE1vdkNYekgyYTVxQ1VHbDFCdHhGai9kekpvTWcwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1ODY3MTk0CWZpbGU6UGhvZW5peCBDb2RlXzMuOS40X3g2NC1zZXR1cC5uc2lzLnppcApBQndIMDlhMWh2dlplQVI5VTNOT3hYckc2UUIwYThrclBWdXhMSDJITDJuRnpmV1JlNStrUHN3TnN4cThORXRUUUkwN1VWbzVRWTNOQ2NYVUc5SUpDQT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_3.9.4_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmt4RTBwTVhEN1BFS0ErSTIrS0pPOVZoL0NlU0VjWU9FMWZHVWR2SXVNZ0NOdFBSRVE2T0pLdXhlamVQclVwa3ZRZkdFRW11T0hyQlQxSTVWVjVKU2dFPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5NDc4MjYzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdEhVbzdmeTVTWTlxcDQ2ZFZ4bTh4QkdHT2syNklxZmtXM0Jqb0JlSGtXb2YvZlo0NjNzL1ZhOG1pWk1qR3dDWFpPdzhNSGlKQ1BMQnFkVlN6Nmh0Q3c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnR0dVpMUG16a1d2MENXMTZHeEtHV1ZBSUZqVHN1dVhLSEhLU3dwMURpT01UaW5UYXFBbFBNNFhFV29jVEZVVzlYdGxVTmNnUzE5aFBkaXcwYnJ3SVFnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1ODY3NjEyCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKN1dVNUVDUUV3QXY3Mzg3R2VFeCtaaytNc2RtZXozUDNtQjh1eHZERWRkbXBuYzZTVmVyVUttZGZHS1J6RW03OUxVKzFNRVNhUHlsTGQ2TWVkQlRWQ1E9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmo3S0ZIT0I4ak00YUhjdHpvVHdraE5peTRIRnVFN214Umhpb3BKTFZRb1ErM0pVSDdhbDF6L3dXTXFXVkZaNXIxSlFDdHVocHhiNDRXamZkYmN4amdRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzE5NDc4NzI4CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKazhodjlLaHQvNXM1ZnEyODBnamIxYVhsc0FqT0EwSEpnOFprT3RuYnBhNEMzV2xVMDVYa2xtRW9pc2NocnJLV2tjMEJiYmJNclRvSmVCeVI2cVNwQWc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.8.8/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnA1eG9VRUhzNytLaytMdG5WQmZCKzBkU0RlNGZRWDNWTDF0STlrRC8rS2p3UGxOb1BOYWduZ3hBb1hBMDA0SmtoRC84Wm9wa29UekJPNE8vY2xOaUFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1ODY4Mjk5CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKOHdaTVl2bm1LRXpyc2tsVTRJWDVXV1ZkUmpjeVJnem1IeFhTZ0xETXNpcHQ0UU9rMGlHV0dPMEtyRWtjR2c5eFh3RlJ1eHdHQk1DYXNKVnRMcUE3QVE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 27ffeb12f58129bf4034828e60eb7dc719ff07f2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:00:56 +0000 Subject: [PATCH 609/864] fix(deps): update rust crate serde to v1.0.210 --- src-tauri/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9291b5d3..7fecd016 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3154,7 +3154,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.9.0" +version = "3.9.1" dependencies = [ "backtrace", "chrono", From ed36c607bdc36555245af83139ff6d17b674f8d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Sep 2024 08:31:30 +0000 Subject: [PATCH 610/864] chore(deps): update peter-evans/create-pull-request action to v7 --- .github/workflows/update-phcode-build.yml | 2 +- .github/workflows/updateNotification.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 3c947f3f..0320adec 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -35,7 +35,7 @@ jobs: - name: Create phcode patch update Pull Request id: cpr - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: commit-message: 'ci: update phcode version to ${{ env.PHOENIX_VERSION }}' committer: GitHub diff --git a/.github/workflows/updateNotification.yml b/.github/workflows/updateNotification.yml index 69f026e4..77273a97 100644 --- a/.github/workflows/updateNotification.yml +++ b/.github/workflows/updateNotification.yml @@ -36,7 +36,7 @@ jobs: - name: Create update notification Pull Request id: cpr - uses: peter-evans/create-pull-request@v6 + uses: peter-evans/create-pull-request@v7 with: commit-message: 'ci: tauri release update notification json' committer: GitHub From 63fdfbff92b611641299a0b20fc3a50b2b803739 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 00:07:57 +0000 Subject: [PATCH 611/864] chore(deps): update dependency axios to v1.7.7 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index ad7fba5d..692d0a49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.6.1", "adm-zip": "0.5.16", - "axios": "1.7.5", + "axios": "1.7.7", "axios-retry": "4.5.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -407,9 +407,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz", - "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index c8344f72..7059e85a 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "7.4.3", - "axios": "1.7.5", + "axios": "1.7.7", "axios-retry": "4.5.0" }, "phoenixRepo": { From f442dc867357d4e998b904d999554874c45e26d5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Sep 2024 08:56:20 +0000 Subject: [PATCH 612/864] fix(deps): update rust crate serde to v1.0.210 --- src-tauri/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7fecd016..2cd0eeb7 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3154,7 +3154,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.9.1" +version = "3.9.4" dependencies = [ "backtrace", "chrono", From f168b6a8a2f0940dba129acd8710a6dd0676a7ea Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 11 Sep 2024 14:47:09 +0530 Subject: [PATCH 613/864] fix: long product names in windows --- src-build/ci-createDistReleaseConfig.js | 1 + src-tauri/tauri.conf.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index 9a39ca37..df157e51 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -85,6 +85,7 @@ async function ciCreateDistReleaseConfig() { // configJson.tauri.bundle.active = false; // #uncomment_line_for_local_build_1 configJson.package.version = phoenixVersion; configJson.package.productName = _getProductName(configJson.package.productName, phoenixStage); + configJson.tauri.bundle.shortDescription = configJson.package.productName; console.log("Product name is: ", configJson.package.productName); configJson.tauri.windows[0].title = configJson.package.productName; if(os.platform() === 'win32'){ diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1d2f5ca4..6233daef 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -196,7 +196,7 @@ "resources": [ "src-node/*" ], - "shortDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", + "shortDescription": "Phoenix Code", "targets": [ "appimage", "nsis", From 1ab9dfdc93750527989a7ddb2f105b15b6fd597c Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 13 Sep 2024 15:27:19 +0530 Subject: [PATCH 614/864] fix: dev build name --- src-tauri/tauri.conf.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6233daef..317d6791 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -196,7 +196,7 @@ "resources": [ "src-node/*" ], - "shortDescription": "Phoenix Code", + "shortDescription": "Phoenix Code Experimental Build", "targets": [ "appimage", "nsis", @@ -484,4 +484,4 @@ } ] } -} \ No newline at end of file +} From 814372ea74ac82c6eb43f922d2264a2e887d8916 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 13 Sep 2024 16:10:34 +0530 Subject: [PATCH 615/864] fix: long package names in windows open with options --- src-build/ci-createDistReleaseConfig.js | 1 + src-tauri/tauri.conf.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-createDistReleaseConfig.js index df157e51..746405d2 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-createDistReleaseConfig.js @@ -86,6 +86,7 @@ async function ciCreateDistReleaseConfig() { configJson.package.version = phoenixVersion; configJson.package.productName = _getProductName(configJson.package.productName, phoenixStage); configJson.tauri.bundle.shortDescription = configJson.package.productName; + configJson.tauri.bundle.longDescription = configJson.package.productName; console.log("Product name is: ", configJson.package.productName); configJson.tauri.windows[0].title = configJson.package.productName; if(os.platform() === 'win32'){ diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 317d6791..c88003fb 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -184,7 +184,8 @@ "icons/icon.ico" ], "identifier": "io.phcode.dev", - "longDescription": "Phoenix is a modern open-source IDE for the web, built for the browser", + "shortDescription": "Phoenix Code Experimental Build", + "longDescription": "Phoenix Code Experimental Build", "macOS": { "entitlements": "../entitlements.plist", "exceptionDomain": "localhost", @@ -196,7 +197,6 @@ "resources": [ "src-node/*" ], - "shortDescription": "Phoenix Code Experimental Build", "targets": [ "appimage", "nsis", From 070b9c8396b44ee2963d460964dac56d6732a6b1 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 13 Sep 2024 18:00:58 +0530 Subject: [PATCH 616/864] fix: long package names in windows open with options --- src-tauri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4e55b508..c14efd41 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "phoenix-code-ide" version = "3.9.4" -description = "Phoenix is a modern open-source IDE for the web, built for the browser." +description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" repository = "https://github.com/phcode-dev/phoenix-desktop" From 80ed9d8a9fd4dc0fc3b593fec5f274a353fc82d4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 15:33:19 +0000 Subject: [PATCH 617/864] fix(deps): update rust crate webbrowser to v1.0.2 --- src-tauri/Cargo.lock | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2cd0eeb7..cf12d63b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -634,7 +634,7 @@ dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.22.3", "foreign-types 0.3.2", "libc", @@ -650,7 +650,7 @@ dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.23.1", "foreign-types 0.5.0", "libc", @@ -665,7 +665,7 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", - "core-foundation", + "core-foundation 0.9.4", "core-graphics-types", "libc", "objc", @@ -712,11 +712,21 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" @@ -725,7 +735,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "core-graphics-types", "foreign-types 0.3.2", "libc", @@ -738,7 +748,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "core-graphics-types", "foreign-types 0.5.0", "libc", @@ -751,7 +761,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "libc", ] @@ -2377,7 +2387,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -2570,7 +2580,7 @@ dependencies = [ "ascii", "block", "cocoa 0.25.0", - "core-foundation", + "core-foundation 0.9.4", "dirs-next", "objc", "objc-foundation", @@ -3812,7 +3822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "core-foundation-sys", "libc", "security-framework-sys", @@ -4242,7 +4252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys 0.5.0", ] @@ -4253,7 +4263,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" dependencies = [ "bitflags 2.5.0", - "core-foundation", + "core-foundation 0.9.4", "system-configuration-sys 0.6.0", ] @@ -4313,7 +4323,7 @@ dependencies = [ "cairo-rs", "cc", "cocoa 0.24.1", - "core-foundation", + "core-foundation 0.9.4", "core-graphics 0.22.3", "crossbeam-channel", "dispatch", @@ -5413,12 +5423,12 @@ dependencies = [ [[package]] name = "webbrowser" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "425ba64c1e13b1c6e8c5d2541c8fac10022ca584f33da781db01b5756aef1f4e" +checksum = "2e5f07fb9bc8de2ddfe6b24a71a75430673fd679e568c48b52716cef1cfae923" dependencies = [ "block2", - "core-foundation", + "core-foundation 0.10.0", "home", "jni 0.21.1", "log", From 9ac21cf0f9c149568e7e48b145a7e20785191ef2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 14:12:16 +0000 Subject: [PATCH 618/864] fix(deps): update rust crate trash to v5.1.1 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index cf12d63b..8ef849f4 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -5018,9 +5018,9 @@ dependencies = [ [[package]] name = "trash" -version = "5.1.0" +version = "5.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a154e8323dbd402514d5a3c0f12e0a5bddf72de674b565d58a5535500566428b" +checksum = "33caf2a9be1812a263a4bfce74d2de225fcde12ee7b77001361abd2b34ffdcc4" dependencies = [ "chrono", "libc", From 692d38a0678876d31842e0a33f11b9cfaf146866 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 10:00:10 +0000 Subject: [PATCH 619/864] fix(deps): update rust crate serde to v1.0.210 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 8ef849f4..76c93aa0 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3869,18 +3869,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.209" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", From 55df17a5c2db2062dba0db41c54243d882bb6be4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 10:00:02 +0000 Subject: [PATCH 620/864] fix(deps): update rust crate backtrace to v0.3.74 --- src-tauri/Cargo.lock | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 76c93aa0..c40946b0 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aho-corasick" version = "1.1.3" @@ -308,17 +314,17 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.8.0", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -1284,7 +1290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.7.2", ] [[package]] @@ -1615,9 +1621,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "gio" @@ -2376,9 +2382,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libloading" @@ -2559,6 +2565,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "1.0.1" @@ -3268,7 +3283,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.7.2", ] [[package]] From 470fc713360532e7e70039f9a9a2ca365c958937 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 17 Sep 2024 05:54:12 +0000 Subject: [PATCH 621/864] chore(deps): update dependency execa to v9.4.0 --- package-lock.json | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 692d0a49..d77bdce8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.9.0", + "version": "3.9.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.9.0", + "version": "3.9.4", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.1", @@ -632,9 +632,9 @@ "dev": true }, "node_modules/execa": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.1.tgz", - "integrity": "sha512-gdhefCCNy/8tpH/2+ajP9IQc14vXchNdd0weyzSJEFURhRMGncQ+zKFxwjAufIewPEJm9BPOaJnvg2UtlH2gPQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.4.0.tgz", + "integrity": "sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==", "dev": true, "license": "MIT", "dependencies": { @@ -645,7 +645,7 @@ "human-signals": "^8.0.0", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", - "npm-run-path": "^5.2.0", + "npm-run-path": "^6.0.0", "pretty-ms": "^9.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", @@ -1170,15 +1170,17 @@ } }, "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1680,6 +1682,19 @@ "node": ">=8.0" } }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", From afff2c2cbc148a6e8a0d153fae33933f272dc1f4 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 19 Sep 2024 15:00:39 +0530 Subject: [PATCH 622/864] build: deps update only once every week as some of our deps are doing daily updates --- renovate.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/renovate.json b/renovate.json index 39a2b6e9..6f76f4d8 100644 --- a/renovate.json +++ b/renovate.json @@ -2,5 +2,8 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:base" + ], + "schedule": [ + "every weekend" ] } From 54846bcb62e09fc785862a8d15f56c512d513835 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 14:12:07 +0000 Subject: [PATCH 623/864] fix(deps): update rust crate serde_json to v1.0.128 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index c40946b0..8d440729 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3904,9 +3904,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", From e221f925677d119167beadf4e2b17c86a0c3395a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:03:38 +0000 Subject: [PATCH 624/864] fix(deps): update rust crate reqwest to v0.12.8 --- src-tauri/Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 8d440729..3de92e55 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1991,7 +1991,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -2393,7 +2393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -3194,7 +3194,7 @@ dependencies = [ "os_info", "percent-encoding", "regex", - "reqwest 0.12.7", + "reqwest 0.12.8", "serde", "serde_json", "tauri", @@ -3606,9 +3606,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", From 18b67d30eafc840dd7be43e903d2bc368f2cc572 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 5 Oct 2024 18:36:07 +0000 Subject: [PATCH 625/864] fix(deps): update rust crate once_cell to v1.20.2 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 3de92e55..f81accf3 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2860,9 +2860,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "open" From 83df7c69d20b6c9bc8bcc04359feeb3689077ac3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 29 Sep 2024 16:32:43 +0000 Subject: [PATCH 626/864] fix(deps): update rust crate regex to v1.11.0 --- src-tauri/Cargo.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f81accf3..ac47d44f 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1715,8 +1715,8 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -2143,7 +2143,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.6", + "regex-automata 0.4.8", "same-file", "walkdir", "winapi-util", @@ -3520,14 +3520,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -3541,13 +3541,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -3558,9 +3558,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" From bb31e5d6c0ef78c3c91b5b6b9d00d6bed74556fa Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 21 Oct 2024 08:35:04 +0530 Subject: [PATCH 627/864] fix: In some linux distoros, attaching an app to inode will take it as default --- docs/linux/installer-latest-experimental-build.sh | 5 ++--- docs/linux/installer.sh | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/linux/installer-latest-experimental-build.sh b/docs/linux/installer-latest-experimental-build.sh index d43a1d00..24327768 100755 --- a/docs/linux/installer-latest-experimental-build.sh +++ b/docs/linux/installer-latest-experimental-build.sh @@ -63,7 +63,6 @@ declare -a MIME_TYPES=( "text/mjs" "application/mjs" "text/cjs" - "inode/directory" # Added to include directory handling ) @@ -312,8 +311,8 @@ set_default_application() { local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file for mime_type in "${MIME_TYPES[@]}"; do - # Skip setting default application for inode/directory and text/html - if [ "$mime_type" = "inode/directory" ] || [ "$mime_type" = "text/html" ]; then + # Skip setting default application for text/html + if [ "$mime_type" = "text/html" ]; then continue # Skip to the next iteration fi diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index abf50c58..25fe48a5 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -46,7 +46,6 @@ declare -a MIME_TYPES=( "text/mjs" "application/mjs" "text/cjs" - "inode/directory" # Added to include directory handling ) @@ -482,8 +481,8 @@ set_default_application() { local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file for mime_type in "${MIME_TYPES[@]}"; do - # Skip setting default application for inode/directory and text/html - if [ "$mime_type" = "inode/directory" ] || [ "$mime_type" = "text/html" ]; then + # Skip setting default application for text/html + if [ "$mime_type" = "text/html" ]; then continue # Skip to the next iteration fi From 9015374f45c9720175c95de227858a58fa61c5b0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 22 Oct 2024 09:29:58 +0000 Subject: [PATCH 628/864] fix(deps): update rust crate tokio to v1.41.0 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ac47d44f..ac9758fb 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4813,9 +4813,9 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" [[package]] name = "tokio" -version = "1.39.3" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", "bytes", From 3d7e2bf734fab75f3e43d4f1411fed769b6e4865 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 27 Oct 2024 18:14:32 +0000 Subject: [PATCH 629/864] fix(deps): update rust crate regex to v1.11.1 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ac9758fb..e7b1622f 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3520,9 +3520,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", From 007581f23f4f5b8a4539f04103c9eeebd6767160 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 21 Nov 2024 17:22:57 +0530 Subject: [PATCH 630/864] chore: add survey show time dynamic config --- docs/surveys.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/surveys.json b/docs/surveys.json index 77aabe2e..127e131e 100644 --- a/docs/surveys.json +++ b/docs/surveys.json @@ -1,8 +1,12 @@ { "newUser": "https://s.surveyplanet.com/jssqbld8", "powerUser": "https://s.surveyplanet.com/v3j59a7z", + "newUserShowDelayMS": 1200000, + "powerUserShowIntervalDays": 35, "browser": { "newUser": "https://s.surveyplanet.com/5lrpp9ud", - "powerUser": "https://s.surveyplanet.com/wtohpj8x" + "powerUser": "https://s.surveyplanet.com/wtohpj8x", + "newUserShowDelayMS": 1200000, + "powerUserShowIntervalDays": 35 } } \ No newline at end of file From 3db9d63c5d4812e38319d069f1cf643f9dceb2cf Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 25 Nov 2024 03:25:06 +0000 Subject: [PATCH 631/864] ci: update phcode version to 3.10.0 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7059e85a..7833b8cf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.9.4", + "version": "3.10.0", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "1c25b224e755da32170e7441eea7e2b73ade6c20" + "commit": "9d96de414fca69d5fef91a2936d3b76eb94178fd" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c14efd41..23b50dec 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.9.4" +version = "3.10.0" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c88003fb..9db4b120 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.9.4" + "version": "3.10.0" }, "tauri": { "allowlist": { @@ -484,4 +484,4 @@ } ] } -} +} \ No newline at end of file From b273423748be7f17ae25e9799705e90fd3e6a12f Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 25 Nov 2024 08:45:16 +0000 Subject: [PATCH 632/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 5a199195..ea084a50 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,19 +1,19 @@ { - "version": "3.9.1", - "notes": "# prerelase for testing only!\r\n\r\nSeptember release(3.9) of Phoenix Code is now available.\r\n\r\nThis month's core theme is `App robustness` and `stability` improvements.\r\nWe have also added several `HTML and Text Editing` workflow improvements.\r\n\r\n## Now Available on ChromeOS\r\n\r\nAll new native ChromeOS app is now available on the Google Play Store.\r\nThe ChromeOS app is a highly requested feature and is specially made for education and student use.\r\n\r\n[![google play icon (1)](https://github.com/user-attachments/assets/0a7f20ce-653c-43a8-ac3e-3875ea74df5b)](https://play.google.com/store/apps/details?id=prod.phcode.twa)\r\n\r\n## Auto rename start and end of HTML/XML/SVG tags\r\n\r\nAutomatically rename paired HTML/XML/SVG tags as you type at the start or end of the tag. [Read more...](https://docs.phcode.dev/docs/editing-text/#auto-rename-tag)\r\n\r\n![tag sync](https://github.com/user-attachments/assets/ad82db8c-df1c-4c83-a5db-145caab539ec)\r\n\r\n## Auto Tab and Spacing detection\r\n\r\nPhoenix Code can now automatically detect and apply the indentation style (tabs or spaces) based on the existing code in the file.\r\n[Read more...](https://docs.phcode.dev/docs/editing-text/#auto-space-detection)\r\n\r\n![image](https://github.com/user-attachments/assets/0adc47c5-a561-4002-bffb-d7bcde999b9d)\r\n\r\n## UX Improvements\r\n\r\n- `Reopen closed files` option added to `File` menu. Shortcut: `Ctrl-Shift-T`, or (`Cmd-Shift-T` on Mac).\r\n- `Go to Next Problem` and `Go to Previous Problem` option added to [`Navigate` menu.](https://github.com/phcode-dev/phoenix/pull/1732)\r\n- [Tab key press to insert code hints](https://github.com/orgs/phcode-dev/discussions/1809)\r\n- `window.alert`, `window.confirm` and `window.prompt` APIs [will work in live preview](https://github.com/phcode-dev/phoenix/pull/1814)\r\n- Clicking on live preview no longer automatically switches from your [current unrelated file to the main HTML file.](https://github.com/phcode-dev/phoenix/pull/1800)\r\n- Live preview usability and navigation improvements - ([1](https://github.com/phcode-dev/phoenix/pull/1741), [2](https://github.com/phcode-dev/phoenix/pull/1760))\r\n- Increase/Decrease font size will [change the Editor Font size Only](https://github.com/phcode-dev/phoenix/pull/1799).\r\n- Fixed issue where code folding markers disappear when hovering over gutter in dark theme.\r\n- `.cjs` and `.mjs` files support as javascript files.\r\n- Support for `shtml` custom server live preview.\r\n\r\n## Stability Improvements\r\n\r\n- [Fixes node crashes after wakeup from sleep in Windows/Mac.](https://github.com/phcode-dev/phoenix/issues/1791) \r\n- [Kaspersky AV trojan horse false positive mitigation.](https://github.com/phcode-dev/phoenix/issues/1821)\r\n- [Corrupt preferences auto reset.](https://github.com/phcode-dev/phoenix/pull/1818)\r\n- [Boot time crash recovery.](https://github.com/phcode-dev/phoenix/pull/1812)\r\n- Phoenix Code won't start in [some Fedora/other Linux distros.](https://github.com/phcode-dev/phoenix/pull/1740)\r\n\r\n## Update on Release Schedule\r\n\r\nIn the past, we've released Phoenix Code updates on a monthly basis. However, last month we encountered an issue with our release that led to stability problems for our users.\r\n\r\nTo address this, we've taken a step back to reevaluate our release process and make improvements to ensure greater robustness and reliability going forward.\r\n\r\nAs a result, we've decided to slow down the desktop release schedule to once every two months. This will allow us to thoroughly test each update and deliver a more stable experience.\r\n\r\nWe apologize for any inconvenience caused by the previous release and appreciate your patience and understanding as we work to improve the quality of Phoenix Code.\r\n\r\nWe look forward to bringing you new features and improvements in a more controlled and reliable manner.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", - "pub_date": "2024-09-06T06:32:12.965Z", + "version": "3.10.0", + "notes": "**Phoenix Code Release Notes**\r\n\r\nExperimental build for testing purposes -- do not use.", + "pub_date": "2024-11-25T06:56:04.373Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1VMklPT0w3YWJtZFB4d0Z4bGE2YlRSbTdPVHprdnYzejUvUHRHb3REdHhkTVF1Qy9aTGRWZzdUdG9VWXE5ajBHeHAvSzNVeklxeUwyTFNzdDhqQ1FzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1NjAzMTkwCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjkuMV94NjQtc2V0dXAubnNpcy56aXAKTnFObk9OUXh0SUZzaDBBbi9NQTR2Z1ZqOHU3Z0hhWjNkcy95N28ycDgzT01wVjl2ayt6dWlNUDVRQitLK1djZlI5VE5qM3hsMTlIUkJGN0haYXliQmc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.9.1/Phoenix.Code.Experimental.Build_3.9.1_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnJiWksxckw2cG9SaTJIQmcySm45bEZqZnZlK3AwTGtmcjBiV09iU1BxWEpaYlhpK3grMjQ5aitQZkJwREdySThWWml3STIzeHM0Sm1CVzNGdjVqc3dVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE2ODA1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjEwLjBfeDY0LXNldHVwLm5zaXMuemlwCkF5Z3c0QjkxeDJiK3Nuc3dzTGhZL2pnd2ordkxCU2RaaWRTTmlSSUFiK0FYek1xRWNmTUtGcFlNS2RnZjBRMzhCRVJ1em9QbGFRbVBaNnNIQnIxdkF3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.10.0/Phoenix.Code.Experimental.Build_3.10.0_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmtvc1FRMTRsYjZiTm5FNDhvRlVoVDJZUGt1ZXd6dzRSR3ZhNms1MGUrNDlhNU1VaTBEcWVKZ2VCU0oxREszMG9ONmE5TWQrcUYxSGZEc1dIUktsdndzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1NjAzNTI4CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6Cm83SU93YUJwL0tKRUZobFozS3pnYTNkWUtZM2FzRG9GLzErbVkrdWlZMEhFSEVZaUZpbUp6NTF0NTVsZVlFS2dZT2pnYndXT0hHcTFUNERLR0JlUUN3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.9.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhYSTF1WTNVTGpQN3hmd3g3UTdVczYrS015UHdoakRQUkl1NzIxN0J6cnpMbGphTG5TS0VybXZqaVhVT0xCbXlka004NWNDeXJBN0JhZnFkU0tWd1FnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE3MTMxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClBZN2pIclJsYmVMNFlYYi81aTMrd1prc1RYSVZaNktFT1U0NjczTlkyNEIvR0NZaElJODc1M1hRL0hmcVMyQlowTlcvN2FPVWx4QzJJVXV6Ly9Sb0JBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.10.0/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxvQW9NMStXbFFuWm0rbjZnamUwbjZRelVVTjg2Vzh5L2RIa1RZS2VsK2IxVDJJSWlXZGJxQndZNzkvRVhqeFBMUUc4SUZGVnprM1VGVGRzNERNQndNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1NjA0MzI0CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnZ4Y05XMDY5Mks5Zy9CR0N3RXBWN0ZydmhWbkRBZDFwREViL2pnU2hHWkIzTEdPU1hJR0xVeDNiTHl5bVkwMjdNUXlvSGt0T3lFMUgyb1A0UFo3WkRBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.9.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZuMTBVUEIwZnJnT05ESlE4d3RkR3IyTDVYM1RCcUszOE1oL1F6NGlaRjhEc2xmT2plRi9IS20weWt3Q2JZblFxU0t6M1gwMSsrWHlKQlRHTDJKV3drPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE3NzU2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CldUOGlLTThCckE0L2NTR2tVKy9OU3Y4M2ZYRmJVZkM1Vmc0UHVKQ0FqbTUvdXdxbDFqYzhkUGNyOTA0ZmxGUUhxd2ZOZ2YyTFFrS2lDRGN4ZUtkR0RBPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.10.0/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" } } } \ No newline at end of file From c15f2795ee44fbbf6c2e6687272d2f2efe7bdce9 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 Nov 2024 04:46:24 +0000 Subject: [PATCH 633/864] ci: tauri release update notification json --- docs/install.json | 6 +++--- docs/tauri/update-latest-stable-prod.json | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/install.json b/docs/install.json index 6183ebb1..4b08d969 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,8 +1,8 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_3.9.4_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_3.9.4_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_3.9.4_x64.dmg", + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_3.10.0_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_3.10.0_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_3.10.0_x64.dmg", "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index de4827e4..3d13f380 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,19 +1,19 @@ { - "version": "3.9.4", - "notes": "September release(3.9) of Phoenix Code is now available.\r\n\r\nThis month's core theme is `App robustness` and `stability` improvements.\r\nWe have also added several `HTML and Text Editing` workflow improvements.\r\n\r\n## Now Available on ChromeOS\r\n\r\nAll new native ChromeOS app is now available on the Google Play Store.\r\nThe ChromeOS app is a highly requested feature and is specially made for education and student use.\r\n\r\n[![google play icon (1)](https://github.com/user-attachments/assets/0a7f20ce-653c-43a8-ac3e-3875ea74df5b)](https://play.google.com/store/apps/details?id=prod.phcode.twa)\r\n\r\n## Auto rename start and end of HTML/XML/SVG tags\r\n\r\nAutomatically rename paired HTML/XML/SVG tags as you type at the start or end of the tag. [Read more...](https://docs.phcode.dev/docs/editing-text/#auto-rename-tag)\r\n\r\n![tag sync](https://github.com/user-attachments/assets/ad82db8c-df1c-4c83-a5db-145caab539ec)\r\n\r\n## Auto Tab and Spacing detection\r\n\r\nPhoenix Code can now automatically detect and apply the indentation style (tabs or spaces) based on the existing code in the file.\r\n[Read more...](https://docs.phcode.dev/docs/editing-text/#auto-space-detection)\r\n\r\n![image](https://github.com/user-attachments/assets/0adc47c5-a561-4002-bffb-d7bcde999b9d)\r\n\r\n## UX Improvements\r\n\r\n- `Reopen closed files` option added to `File` menu. Shortcut: `Ctrl-Shift-T`, or (`Cmd-Shift-T` on Mac).\r\n- `Go to Next Problem` and `Go to Previous Problem` option added to [`Navigate` menu.](https://github.com/phcode-dev/phoenix/pull/1732)\r\n- [Tab key press to insert code hints](https://github.com/orgs/phcode-dev/discussions/1809)\r\n- `window.alert`, `window.confirm` and `window.prompt` APIs [will work in live preview](https://github.com/phcode-dev/phoenix/pull/1814)\r\n- Clicking on live preview no longer automatically switches from your [current unrelated file to the main HTML file.](https://github.com/phcode-dev/phoenix/pull/1800)\r\n- Live preview usability and navigation improvements - ([1](https://github.com/phcode-dev/phoenix/pull/1741), [2](https://github.com/phcode-dev/phoenix/pull/1760))\r\n- Increase/Decrease font size will [change the Editor Font size Only](https://github.com/phcode-dev/phoenix/pull/1799).\r\n- Fixed issue where code folding markers disappear when hovering over gutter in dark theme.\r\n- `.cjs` and `.mjs` files support as javascript files.\r\n- Support for `shtml` custom server live preview.\r\n\r\n## Stability Improvements\r\n\r\n- [Fixes node crashes after wakeup from sleep in Windows/Mac.](https://github.com/phcode-dev/phoenix/issues/1791) \r\n- [Kaspersky AV trojan horse false positive mitigation.](https://github.com/phcode-dev/phoenix/issues/1821)\r\n- [Corrupt preferences auto reset.](https://github.com/phcode-dev/phoenix/pull/1818)\r\n- [Boot time crash recovery.](https://github.com/phcode-dev/phoenix/pull/1812)\r\n- Phoenix Code won't start in [some Fedora/other Linux distros.](https://github.com/phcode-dev/phoenix/pull/1740)\r\n\r\n## Update on Release Schedule\r\n\r\nIn the past, we've released Phoenix Code updates on a monthly basis. However, last month we encountered an issue with our release that led to stability problems for our users.\r\n\r\nTo address this, we've taken a step back to reevaluate our release process and make improvements to ensure greater robustness and reliability going forward.\r\n\r\nAs a result, we've decided to slow down the desktop release schedule to once every two months. This will allow us to thoroughly test each update and deliver a more stable experience.\r\n\r\nWe apologize for any inconvenience caused by the previous release and appreciate your patience and understanding as we work to improve the quality of Phoenix Code.\r\n\r\nWe look forward to bringing you new features and improvements in a more controlled and reliable manner.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev).\r\n Every contribution helps us to keep improving Phoenix Code.\r\n", - "pub_date": "2024-09-09T07:51:47.896Z", + "version": "3.10.0", + "notes": "November release(3.10) of Phoenix Code is now available.\r\n\r\nThis month's core theme is `Editor UI improvements`. We have fine-tuned the editing experience for better \r\nperformance and visual feedback.\r\nWe've also made substantial improvements to [docs.phcode.dev](https://docs.phcode.dev) to better support extension\r\ndevelopers.\r\n\r\n## Indent Guide Lines\r\n\r\nPhoenix Code now supports indent guidelines to help you better visualize code structure. This feature can\r\nbe toggled via `View > Indent Guide Lines`. [Read more...](https://docs.phcode.dev/docs/editing-text#indent-guide-lines)\r\n\r\n![image](https://github.com/user-attachments/assets/3d9d0c55-3c9e-4ab3-bbc0-53b563d19e39)\r\n\r\n## Customizable Editor Line Height\r\n\r\nTheme Settings (`View > Themes...`) now has a new `Line Height` slider. Adjust the editor line height between 1x and 3x to find your\r\nperfect balance of readability and screen real estate. [Read more...](https://docs.phcode.dev/docs/editing-text#line-height)\r\n\r\nAlso added a `Get More...` button to the Themes dialog, linking directly to the themes section in Extension Manager.\r\n\r\n![image](https://github.com/user-attachments/assets/97a46d9a-e971-401d-8a77-015afa6d5972)\r\n\r\n## `Line:Col` Indicator Relocation\r\n\r\nMoved to the right of the status bar, accommodating future status bar extensions. Click on the `line:col` section in the\r\nstatusbar to jump to specific lines.\r\n\r\n![image](https://github.com/user-attachments/assets/540ea992-dda0-4a2c-8042-3c6228616636)\r\n\r\n## Performance Tweaks\r\n\r\n- [Major improvements to editor rendering](https://github.com/phcode-dev/phoenix/pull/1943) with better editor scroll\r\n consistency and performance, especially on Safari and macOS.\r\n- [Faster startup of extension manager.](https://github.com/phcode-dev/phoenix/pull/1937)\r\n\r\n## Stability Improvements\r\n\r\n- [File recovery now does integrity checks for more reliable crash recovery.](https://github.com/phcode-dev/phoenix/pull/1889)\r\n- [Fixed Markdown image link handling within href tags.](https://github.com/phcode-dev/phoenix/pull/1838)\r\n- [Improved extension registry management to prevent quota issues on Mac/Linux.](https://github.com/phcode-dev/phoenix/pull/1932)\r\n\r\n## Documentation Updates\r\nOur documentation site - [docs.phcode.dev](https://docs.phcode.dev) has received a major overhaul:\r\n\r\n- Updated user guide: [docs.phcode.dev/docs/intro](https://docs.phcode.dev/docs/intro)\r\n- New API documentation for extension developers: [docs.phcode.dev/api/getting-started](https://docs.phcode.dev/api/getting-started)\r\n\r\n## All changes\r\n\r\nPlease see [this link](https://github.com/phcode-dev/phoenix/commits/main/?since=2024-09-11&until=2024-11-24) for a full list of changes\r\nin GitHub.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev). Every contribution helps us\r\n to keep improving Phoenix Code.\r\n", + "pub_date": "2024-11-25T06:03:19.592Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnNsRjM5a2JudEs3VFNtMDIrK0pEa2QwYTVwaTFpTUR6UTBNV2cvbW5ZejRKTmxtdTByT3BHVDdsTE1vdkNYekgyYTVxQ1VHbDFCdHhGai9kekpvTWcwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1ODY3MTk0CWZpbGU6UGhvZW5peCBDb2RlXzMuOS40X3g2NC1zZXR1cC5uc2lzLnppcApBQndIMDlhMWh2dlplQVI5VTNOT3hYckc2UUIwYThrclBWdXhMSDJITDJuRnpmV1JlNStrUHN3TnN4cThORXRUUUkwN1VWbzVRWTNOQ2NYVUc5SUpDQT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_3.9.4_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1QQkhLZDVpZUsrbUVVbjhnUlpvSk94eS9ybXVISTVWcDZRVW9peDVDK3g5Z2RiUkk5MXloVGN5c3h5MXcyYUMrK1JRbjg4QzJ3dkluM1ZHSURCemdzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTEyMTQzCWZpbGU6UGhvZW5peCBDb2RlXzMuMTAuMF94NjQtc2V0dXAubnNpcy56aXAKb1NGendmUTNkOWM1Z2lFbTU2Q2FGbkFqREhjLzB2NEhKclRBclZpcFE4NkcwSHZ1TGhFbjVhMTdwbVptTmtwT3NlWGV2QXFiUWljeHl6NTdZSzhGQ2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_3.10.0_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnR0dVpMUG16a1d2MENXMTZHeEtHV1ZBSUZqVHN1dVhLSEhLU3dwMURpT01UaW5UYXFBbFBNNFhFV29jVEZVVzlYdGxVTmNnUzE5aFBkaXcwYnJ3SVFnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1ODY3NjEyCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKN1dVNUVDUUV3QXY3Mzg3R2VFeCtaaytNc2RtZXozUDNtQjh1eHZERWRkbXBuYzZTVmVyVUttZGZHS1J6RW03OUxVKzFNRVNhUHlsTGQ2TWVkQlRWQ1E9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnFVVkZMNktUaEQzVjY4ZzRmdUNiRVZFRm9IZHVvSlFjMGxvMFBSYmc0aHhKOFZ2L1ZNdnNCdSsyTldaMEVFUEdqeU9QYS9aQzlFaUMrMDRIeTVVbHdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE0MDAwCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKaWJxVmZub2VEdHJNOHZ5N3ZGSXJ0ZDE3bEZnL0dYNDFrT2V2MGViTFFmc3p5UlFIZEFjU0xmSHk0aVh0RmVzOTFDMk9hTzQxQnB5M1ZKc2ZHejlrQkE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnA1eG9VRUhzNytLaytMdG5WQmZCKzBkU0RlNGZRWDNWTDF0STlrRC8rS2p3UGxOb1BOYWduZ3hBb1hBMDA0SmtoRC84Wm9wa29UekJPNE8vY2xOaUFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzI1ODY4Mjk5CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKOHdaTVl2bm1LRXpyc2tsVTRJWDVXV1ZkUmpjeVJnem1IeFhTZ0xETXNpcHQ0UU9rMGlHV0dPMEtyRWtjR2c5eFh3RlJ1eHdHQk1DYXNKVnRMcUE3QVE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.9.4/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxrcjJuK0twWUdwSFJKcjZHYUozby9ZdFdLMmM3Z1AxTDV4Z0NCSmJLT1RvbTJtTHNQODlZMlBQbHhzZ1hQU2xlRndPVklmMU4zU1RoOExpL1AxT0FZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE0NTkyCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKMFV4bmtGZlJCNDJuQkhFYnVEZWxmUk44Y1piNXlzSVcwaVk1TFRGOUNndWplN0FScTRxQU9zOE92N2Q1b3pvL01SY1h2SEM0ZEZaUllBSVhCeTFxQlE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 6a1002975dc4e46223367ce18634c19592769675 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 5 Dec 2024 11:27:40 +0530 Subject: [PATCH 634/864] fix: macos-12 is deprecated in github, moving to macos-13 --- .github/workflows/desktop-mac-test-pull.yml | 2 +- .github/workflows/tauri-build-dev.yml | 14 +++++++------- .github/workflows/tauri-build-prod.yml | 14 +++++++------- .github/workflows/tauri-build-staging.yml | 14 +++++++------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 72a1d9d3..28414e89 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -9,7 +9,7 @@ concurrency: jobs: test-desktop-mac: - runs-on: macos-12 + runs-on: macos-13 timeout-minutes: 90 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 1e90df44..45277f94 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-12, windows-latest ] + platform: [ macos-13, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -92,7 +92,7 @@ jobs: node-version: 20 - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' uses: actions/download-artifact@v4 with: name: src-node-darwin-arm64.tar.gz @@ -108,7 +108,7 @@ jobs: npm run _ci-release:dev - name: setup src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' run: | ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node @@ -161,7 +161,7 @@ jobs: Set-Content -Path "./secrets.json" -Value $content shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -229,7 +229,7 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: inject src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' run: | ls src-node rm -rf src-tauri/src-node @@ -239,12 +239,12 @@ jobs: - name: setup env for mac arm (Mac only) env: GH_TOKEN: ${{ github.token }} - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index e6c8b923..bec6e04d 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-12, windows-latest ] + platform: [ macos-13, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -92,7 +92,7 @@ jobs: node-version: 20 - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' uses: actions/download-artifact@v4 with: name: src-node-darwin-arm64.tar.gz @@ -108,7 +108,7 @@ jobs: npm run _ci-release:prod - name: setup src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' run: | ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node @@ -162,7 +162,7 @@ jobs: shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -230,7 +230,7 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: inject src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' run: | ls src-node rm -rf src-tauri/src-node @@ -240,12 +240,12 @@ jobs: - name: setup env for mac arm (Mac only) env: GH_TOKEN: ${{ github.token }} - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 6ec35a13..a43117f9 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -78,7 +78,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-12, windows-latest ] + platform: [ macos-13, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -92,7 +92,7 @@ jobs: node-version: 20 - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' uses: actions/download-artifact@v4 with: name: src-node-darwin-arm64.tar.gz @@ -106,7 +106,7 @@ jobs: npm run _ci-release:staging - name: setup src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' run: | ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node @@ -159,7 +159,7 @@ jobs: Set-Content -Path "./secrets.json" -Value $content shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -227,7 +227,7 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: inject src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' run: | ls src-node rm -rf src-tauri/src-node @@ -237,12 +237,12 @@ jobs: - name: setup env for mac arm (Mac only) env: GH_TOKEN: ${{ github.token }} - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-12' + if: matrix.platform == 'macos-13' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ github.token }} From eb69d78c7bb2e6d6c73904797ee09410f2fd8df8 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 11 Dec 2024 14:35:26 +0530 Subject: [PATCH 635/864] fix: installer broken in ubuntu 24,10 --- docs/linux/installer.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 25fe48a5..0a30567e 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -128,11 +128,19 @@ TMP_DIR=$(mktemp -d) check_os_version() { if [ -f /etc/os-release ]; then . /etc/os-release - if [[ "$ID" = "ubuntu" && "$VERSION_ID" = "24.04" ]] || - [[ "$ID" = "linuxmint" && "$VERSION_ID" = "22" ]] || - ([[ "$ID" = "kali" ]] && [[ "$VERSION_ID" > "2024.2" ]] || [[ "$VERSION_ID" == "2024.2" ]]); then - return 0 # Ubuntu 24.04, Linux Mint 22, or Kali Linux 2024.2 or newer detected - fi + + # Define supported OS and version combinations + case "$ID:$VERSION_ID" in + ubuntu:24.04|ubuntu:24.10) # Ubuntu 24.04 or 24.10 + return 0 + ;; + linuxmint:22) # Linux Mint 22 + return 0 + ;; + kali:2024.2|kali:2024.[3-9]|kali:20[2-9][0-9].[0-9]) # Kali 2024.2 or newer + return 0 + ;; + esac fi return 1 # None of the specified versions detected } From 6400e5b1e012591a1db48f0fe835cc16a8d71b85 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 11 Dec 2024 14:44:01 +0530 Subject: [PATCH 636/864] fix: github workflow failure --- .github/workflows/desktop-linux-test-pull.yml | 2 +- .github/workflows/prod-desktop-tests-on-pull.yml | 2 +- .github/workflows/staging-desktop-tests-on-pull.yml | 2 +- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- .github/workflows/update-phcode-build.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index 1263a37e..f831cf31 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -9,7 +9,7 @@ concurrency: jobs: test-desktop-linux: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 90 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index 3a6ea408..be9021e3 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -7,7 +7,7 @@ on: jobs: testDesktopLinux: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 90 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index 83186ef6..6195d58e 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -7,7 +7,7 @@ on: jobs: testDesktopLinux: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 timeout-minutes: 90 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 45277f94..feb124c6 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -8,7 +8,7 @@ jobs: create-release: permissions: contents: write - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 outputs: release_id: ${{ steps.create-release.outputs.result }} diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index bec6e04d..d6c5a3ba 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -8,7 +8,7 @@ jobs: create-release: permissions: contents: write - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 outputs: release_id: ${{ steps.create-release.outputs.result }} diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index a43117f9..55cce5ec 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -8,7 +8,7 @@ jobs: create-release: permissions: contents: write - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 outputs: release_id: ${{ steps.create-release.outputs.result }} diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index 0320adec..fe960349 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -10,7 +10,7 @@ on: jobs: build-tasks: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: Event triggered by From 6e45d68d77ed306819c5201b0553016947189192 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 21:15:39 +0000 Subject: [PATCH 637/864] chore(deps): update tauri monorepo --- package-lock.json | 104 +++++++++++++++++++++++++------------------ package.json | 2 +- src-tauri/Cargo.lock | 13 +++--- 3 files changed, 69 insertions(+), 50 deletions(-) diff --git a/package-lock.json b/package-lock.json index d77bdce8..0ccf8f94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "3.9.4", "hasInstallScript": true, "devDependencies": { - "@tauri-apps/cli": "1.6.1", + "@tauri-apps/cli": "1.6.3", "adm-zip": "0.5.16", "axios": "1.7.7", "axios-retry": "4.5.0", @@ -158,11 +158,14 @@ } }, "node_modules/@tauri-apps/cli": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.6.1.tgz", - "integrity": "sha512-2S8WGmkz54Z9WxpaFVbUYsTiwx5OIEmdD5DDWRygX9VhaWwZg0y6DctsUtCRVre9I/Un/hTnmqkhZqPamCEx8A==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli/-/cli-1.6.3.tgz", + "integrity": "sha512-q46umd6QLRKDd4Gg6WyZBGa2fWvk0pbeUA5vFomm4uOs1/17LIciHv2iQ4UD+2Yv5H7AO8YiE1t50V0POiEGEw==", "dev": true, "license": "Apache-2.0 OR MIT", + "dependencies": { + "semver": ">=7.5.2" + }, "bin": { "tauri": "tauri.js" }, @@ -174,22 +177,22 @@ "url": "https://opencollective.com/tauri" }, "optionalDependencies": { - "@tauri-apps/cli-darwin-arm64": "1.6.1", - "@tauri-apps/cli-darwin-x64": "1.6.1", - "@tauri-apps/cli-linux-arm-gnueabihf": "1.6.1", - "@tauri-apps/cli-linux-arm64-gnu": "1.6.1", - "@tauri-apps/cli-linux-arm64-musl": "1.6.1", - "@tauri-apps/cli-linux-x64-gnu": "1.6.1", - "@tauri-apps/cli-linux-x64-musl": "1.6.1", - "@tauri-apps/cli-win32-arm64-msvc": "1.6.1", - "@tauri-apps/cli-win32-ia32-msvc": "1.6.1", - "@tauri-apps/cli-win32-x64-msvc": "1.6.1" + "@tauri-apps/cli-darwin-arm64": "1.6.3", + "@tauri-apps/cli-darwin-x64": "1.6.3", + "@tauri-apps/cli-linux-arm-gnueabihf": "1.6.3", + "@tauri-apps/cli-linux-arm64-gnu": "1.6.3", + "@tauri-apps/cli-linux-arm64-musl": "1.6.3", + "@tauri-apps/cli-linux-x64-gnu": "1.6.3", + "@tauri-apps/cli-linux-x64-musl": "1.6.3", + "@tauri-apps/cli-win32-arm64-msvc": "1.6.3", + "@tauri-apps/cli-win32-ia32-msvc": "1.6.3", + "@tauri-apps/cli-win32-x64-msvc": "1.6.3" } }, "node_modules/@tauri-apps/cli-darwin-arm64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.6.1.tgz", - "integrity": "sha512-n+16Z9qQksBmY55Xwful8GGrw2dlyeqKPsjuNcwKUgVB5a4gIq6K6uUsbhwMUMUA3gqewQMBn44QXbSe5qNKfA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-arm64/-/cli-darwin-arm64-1.6.3.tgz", + "integrity": "sha512-fQN6IYSL8bG4NvkdKE4sAGF4dF/QqqQq4hOAU+t8ksOzHJr0hUlJYfncFeJYutr/MMkdF7hYKadSb0j5EE9r0A==", "cpu": [ "arm64" ], @@ -204,9 +207,9 @@ } }, "node_modules/@tauri-apps/cli-darwin-x64": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.6.1.tgz", - "integrity": "sha512-OHzm6qiywv0GEwBDowlzLSuztKE85NMxp2loVynQ4vDoVk6V0jMtQy/N9YvYA0BetvfNTuuAiz3hsTkMHMYm+g==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-darwin-x64/-/cli-darwin-x64-1.6.3.tgz", + "integrity": "sha512-1yTXZzLajKAYINJOJhZfmMhCzweHSgKQ3bEgJSn6t+1vFkOgY8Yx4oFgWcybrrWI5J1ZLZAl47+LPOY81dLcyA==", "cpu": [ "x64" ], @@ -221,9 +224,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm-gnueabihf": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.6.1.tgz", - "integrity": "sha512-ZA4ByaiZbrXUbhaoWUVab4lHI2yI1/ucrRO6b9pky6ytgqx37hA/YOWoctD0yaf5giQJQZw160euaBIUOKzRXA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm-gnueabihf/-/cli-linux-arm-gnueabihf-1.6.3.tgz", + "integrity": "sha512-CjTEr9r9xgjcvos09AQw8QMRPuH152B1jvlZt4PfAsyJNPFigzuwed5/SF7XAd8bFikA7zArP4UT12RdBxrx7w==", "cpu": [ "arm" ], @@ -238,9 +241,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-gnu": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.6.1.tgz", - "integrity": "sha512-VBU4GRJPU9jzzeqaEGLHAJzqQhpl7WnRFyHPR8Qby0D17av3CClJ7nBa+CI3ob3JbIERfJM9kwFHdY9eQpfxnw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-gnu/-/cli-linux-arm64-gnu-1.6.3.tgz", + "integrity": "sha512-G9EUUS4M8M/Jz1UKZqvJmQQCKOzgTb8/0jZKvfBuGfh5AjFBu8LHvlFpwkKVm1l4951Xg4ulUp6P9Q7WRJ9XSA==", "cpu": [ "arm64" ], @@ -255,9 +258,9 @@ } }, "node_modules/@tauri-apps/cli-linux-arm64-musl": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.6.1.tgz", - "integrity": "sha512-gyMgNZ8fwQFYzrIiHwhmKECkbuAZtzsRyl+bi1Ua11XVWYVUpY8+cNp7Y5ilMJ9AwNFI/HFKjzzua9r+e9FNzw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.6.3.tgz", + "integrity": "sha512-MuBTHJyNpZRbPVG8IZBN8+Zs7aKqwD22tkWVBcL1yOGL4zNNTJlkfL+zs5qxRnHlUsn6YAlbW/5HKocfpxVwBw==", "cpu": [ "arm64" ], @@ -272,9 +275,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-gnu": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.6.1.tgz", - "integrity": "sha512-aYLjLXEBcOf4GUrLBZRQcoLSL3KgCKHwfAyGmTilH4juAw42ZaAYWIZwa59hp2kC4w1XrlmwAzGpi1RESBr5Mw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-gnu/-/cli-linux-x64-gnu-1.6.3.tgz", + "integrity": "sha512-Uvi7M+NK3tAjCZEY1WGel+dFlzJmqcvu3KND+nqa22762NFmOuBIZ4KJR/IQHfpEYqKFNUhJfCGnpUDfiC3Oxg==", "cpu": [ "x64" ], @@ -289,9 +292,9 @@ } }, "node_modules/@tauri-apps/cli-linux-x64-musl": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.6.1.tgz", - "integrity": "sha512-j1M7ovICUrBDbrH8CNUwbMe0zk0/IAR7MXRv5PEanktAZ1w/LG3nlO/AhY5/Cbqqo3ziKTcMpe6x0j3aE8jYOA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-linux-x64-musl/-/cli-linux-x64-musl-1.6.3.tgz", + "integrity": "sha512-rc6B342C0ra8VezB/OJom9j/N+9oW4VRA4qMxS2f4bHY2B/z3J9NPOe6GOILeg4v/CV62ojkLsC3/K/CeF3fqQ==", "cpu": [ "x64" ], @@ -306,9 +309,9 @@ } }, "node_modules/@tauri-apps/cli-win32-arm64-msvc": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.6.1.tgz", - "integrity": "sha512-yCGT1jXHvZtu+yYPDmDOJDfgsj5EKdBPvya+kmN03BmLfOF+8EWHA9s6yXUdk9pSr6M9OQS0SXocbGDOu5AkMw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-arm64-msvc/-/cli-win32-arm64-msvc-1.6.3.tgz", + "integrity": "sha512-cSH2qOBYuYC4UVIFtrc1YsGfc5tfYrotoHrpTvRjUGu0VywvmyNk82+ZsHEnWZ2UHmu3l3lXIGRqSWveLln0xg==", "cpu": [ "arm64" ], @@ -323,9 +326,9 @@ } }, "node_modules/@tauri-apps/cli-win32-ia32-msvc": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.6.1.tgz", - "integrity": "sha512-klAt+KNcczC4gxz9vm6tSvFB4iyXVj4r+TtDVhStLCKkAZOVm0ZsFym1kDzltxrB/3xSjgzsgIiEJydN2cP7xw==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-ia32-msvc/-/cli-win32-ia32-msvc-1.6.3.tgz", + "integrity": "sha512-T8V6SJQqE4PSWmYBl0ChQVmS6AR2hXFHURH2DwAhgSGSQ6uBXgwlYFcfIeQpBQA727K2Eq8X2hGfvmoySyHMRw==", "cpu": [ "ia32" ], @@ -340,9 +343,9 @@ } }, "node_modules/@tauri-apps/cli-win32-x64-msvc": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.6.1.tgz", - "integrity": "sha512-WEzQzBgcaqjZoA5M/KOupHmt8W3QQ20vwETXpGEMPd7spj4eZsRv/2ZDuCz4ELbai1XlIsTITFNe2LlJjzqISA==", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@tauri-apps/cli-win32-x64-msvc/-/cli-win32-x64-msvc-1.6.3.tgz", + "integrity": "sha512-HUkWZ+lYHI/Gjkh2QjHD/OBDpqLVmvjZGpLK9losur1Eg974Jip6k+vsoTUxQBCBDfj30eDBct9E1FvXOspWeg==", "cpu": [ "x64" ], @@ -1457,6 +1460,19 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", diff --git a/package.json b/package.json index 7833b8cf..d2023eb5 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "getPackageVersion": "node ./src-build/getVersion.js" }, "devDependencies": { - "@tauri-apps/cli": "1.6.1", + "@tauri-apps/cli": "1.6.3", "adm-zip": "0.5.16", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e7b1622f..b48b23f5 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1991,7 +1991,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -4405,9 +4405,9 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.7.2" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e33e3ba00a3b05eb6c57ef135781717d33728b48acf914bb05629e74d897d29" +checksum = "1bf327e247698d3f39af8aa99401c9708384290d1f5c544bf5d251d44c2fea22" dependencies = [ "anyhow", "base64 0.22.1", @@ -4428,6 +4428,8 @@ dependencies = [ "http 0.2.12", "ignore", "indexmap 1.9.3", + "infer", + "log", "minisign-verify", "nix 0.26.4", "notify-rust", @@ -4437,6 +4439,7 @@ dependencies = [ "os_info", "os_pipe", "percent-encoding", + "plist", "rand 0.8.5", "raw-window-handle", "regex", @@ -4469,9 +4472,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.5.4" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fb5a90a64241ddb7217d3210d844149070a911e87e8a107a707a1d4973f164" +checksum = "586f3e677f940c8bb4f70c52eda05dc59b79e61543f1182de83516810bb8e35d" dependencies = [ "anyhow", "cargo_toml", From 18d314ddb5accca9a8082a93661394c3d379374d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 14 Dec 2024 00:13:20 +0000 Subject: [PATCH 638/864] chore(deps): update dependency axios to v1.7.9 --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0ccf8f94..3b6b9402 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "phoenix-code-ide", - "version": "3.9.4", + "version": "3.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.9.4", + "version": "3.10.0", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.3", "adm-zip": "0.5.16", - "axios": "1.7.7", + "axios": "1.7.9", "axios-retry": "4.5.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -410,9 +410,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index d2023eb5..db248dc5 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.2.0", "shx": "^0.3.4", "tar": "7.4.3", - "axios": "1.7.7", + "axios": "1.7.9", "axios-retry": "4.5.0" }, "phoenixRepo": { From 6f27e1f3909256f0ce6fc3c8d6f7edcf993a541b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 21 Dec 2024 01:22:59 +0000 Subject: [PATCH 639/864] fix(deps): update rust crate chrono to v0.4.39 --- src-tauri/Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b48b23f5..e05601c3 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -560,9 +560,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -3179,7 +3179,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.9.4" +version = "3.10.0" dependencies = [ "backtrace", "chrono", From 930e8a9bd794f7dc88bde9d82c178a381b52482e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 28 Dec 2024 06:48:31 +0000 Subject: [PATCH 640/864] fix(deps): update rust crate serde to v1.0.217 --- src-tauri/Cargo.lock | 64 ++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e05601c3..62e5acd4 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -227,7 +227,7 @@ checksum = "30c5ef0ede93efbf733c1a727f3b6b5a1060bbedd5600183e66f6e4be4af0ec5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -262,7 +262,7 @@ checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -857,7 +857,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -867,7 +867,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" dependencies = [ "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -891,7 +891,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -902,7 +902,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -934,7 +934,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -1128,7 +1128,7 @@ checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -1335,7 +1335,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -1437,7 +1437,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -2897,7 +2897,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -3147,7 +3147,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -3227,7 +3227,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -3377,9 +3377,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -3884,22 +3884,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -3923,7 +3923,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -3974,7 +3974,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -3996,7 +3996,7 @@ checksum = "772ee033c0916d670af7860b6e1ef7d658a4629a6d0b4c8c3e67f09b3765b75d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -4227,9 +4227,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.55" +version = "2.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126" dependencies = [ "proc-macro2", "quote", @@ -4738,7 +4738,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -4840,7 +4840,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -4992,7 +4992,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -5298,7 +5298,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", "wasm-bindgen-shared", ] @@ -5332,7 +5332,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5718,7 +5718,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] @@ -5729,7 +5729,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.92", ] [[package]] From ecf740afda2f749ad327d23c65d2a6695ba4d19d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 28 Dec 2024 07:28:50 +0000 Subject: [PATCH 641/864] fix(deps): update rust crate reqwest to v0.12.11 --- src-tauri/Cargo.lock | 52 ++++++++++++++------------------------------ 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 62e5acd4..83d86984 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -457,9 +457,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" dependencies = [ "serde", ] @@ -1991,7 +1991,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -2066,9 +2066,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde7055719c54e36e95e8719f95883f22072a48ede39db7fc17a4e1d5281e9b9" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", @@ -2079,7 +2079,6 @@ dependencies = [ "pin-project-lite", "socket2 0.5.6", "tokio", - "tower", "tower-service", "tracing", ] @@ -3194,7 +3193,7 @@ dependencies = [ "os_info", "percent-encoding", "regex", - "reqwest 0.12.8", + "reqwest 0.12.11", "serde", "serde_json", "tauri", @@ -3210,26 +3209,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "pin-project" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.92", -] - [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3606,9 +3585,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.8" +version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" +checksum = "7fe060fe50f524be480214aba758c71f99f90ee8c83c5a36b5e9e1d568eb4eb3" dependencies = [ "base64 0.22.1", "bytes", @@ -3639,6 +3618,7 @@ dependencies = [ "system-configuration 0.6.0", "tokio", "tokio-native-tls", + "tower", "tower-service", "url", "wasm-bindgen", @@ -4948,14 +4928,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.4.13" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", - "pin-project", "pin-project-lite", + "sync_wrapper 1.0.1", "tokio", "tower-layer", "tower-service", @@ -4963,15 +4943,15 @@ dependencies = [ [[package]] name = "tower-layer" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" From b0a21161cae0d2ce9062739bab94ca2a7709b51a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 28 Dec 2024 07:27:28 +0000 Subject: [PATCH 642/864] fix(deps): update rust crate serde_json to v1.0.134 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 83d86984..2844663b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3884,9 +3884,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", From e80d47df3a0a44f828fc7045902d1d3910f5f069 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 28 Dec 2024 12:45:33 +0000 Subject: [PATCH 643/864] fix(deps): update rust crate webbrowser to v1.0.3 --- src-tauri/Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2844663b..9fd67931 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2392,7 +2392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -5421,9 +5421,9 @@ dependencies = [ [[package]] name = "webbrowser" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5f07fb9bc8de2ddfe6b24a71a75430673fd679e568c48b52716cef1cfae923" +checksum = "ea9fe1ebb156110ff855242c1101df158b822487e4957b0556d9ffce9db0f535" dependencies = [ "block2", "core-foundation 0.10.0", From 5029a0273bbe36884fa0f440db95094c352f1b32 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 18 Jan 2025 09:55:59 +0000 Subject: [PATCH 644/864] ci: update phcode version to 4.0.0 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index db248dc5..b05dc263 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "3.10.0", + "version": "4.0.0", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "9d96de414fca69d5fef91a2936d3b76eb94178fd" + "commit": "205a69218a8c149c0d66a9f866c17fe15cd675db" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 23b50dec..403f7d1b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "3.10.0" +version = "4.0.0" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 9db4b120..386eef69 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "3.10.0" + "version": "4.0.0" }, "tauri": { "allowlist": { From ea0d851e0b47362a43c940794d7e9090c6204368 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sun, 26 Jan 2025 16:18:58 +0530 Subject: [PATCH 645/864] fix: installer not working for linux mint 22.1 --- docs/linux/installer.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 0a30567e..98caed0e 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -128,21 +128,20 @@ TMP_DIR=$(mktemp -d) check_os_version() { if [ -f /etc/os-release ]; then . /etc/os-release - # Define supported OS and version combinations - case "$ID:$VERSION_ID" in - ubuntu:24.04|ubuntu:24.10) # Ubuntu 24.04 or 24.10 + case "$ID:${VERSION_ID%%.*}" in # Extract major version number + ubuntu:24) # Ubuntu 24.x return 0 ;; - linuxmint:22) # Linux Mint 22 + linuxmint:22) # Linux Mint 22.x return 0 ;; - kali:2024.2|kali:2024.[3-9]|kali:20[2-9][0-9].[0-9]) # Kali 2024.2 or newer + kali:2024|kali:20[2-9][0-9]) # Kali 2024.x or newer return 0 ;; esac fi - return 1 # None of the specified versions detected + return 1 } # Create Invocation Script Function From 582f333e55755f61554ca5bd9a6f898dff945eac Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 30 Jan 2025 05:45:34 +0000 Subject: [PATCH 646/864] ci: update phcode version to 4.0.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b05dc263..f70b4125 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "4.0.0", + "version": "4.0.1", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "205a69218a8c149c0d66a9f866c17fe15cd675db" + "commit": "c5115b8faad82f7f079caa590ace8a28c83026f6" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 403f7d1b..12eca042 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "4.0.0" +version = "4.0.1" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 386eef69..8706e8df 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "4.0.0" + "version": "4.0.1" }, "tauri": { "allowlist": { From 0fb9b8f8b504b6ed6d8f8685291da72e5dfff866 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 30 Jan 2025 13:21:01 +0000 Subject: [PATCH 647/864] ci: update phcode version to 4.0.2 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index f70b4125..6b70b1a8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "4.0.1", + "version": "4.0.2", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "c5115b8faad82f7f079caa590ace8a28c83026f6" + "commit": "cdab8e31c04f5877129c93840cd3ec07d7f71dcf" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 12eca042..4a770cad 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "4.0.1" +version = "4.0.2" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8706e8df..494a7075 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "4.0.1" + "version": "4.0.2" }, "tauri": { "allowlist": { From f135c6645ac3a98a6d8f6f2e54d557f6880df9a6 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 30 Jan 2025 19:57:59 +0530 Subject: [PATCH 648/864] ci: retry tauri build on failure as mac bundles builds are eraticaly failing --- .github/workflows/tauri-build-prod.yml | 46 +++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index d6c5a3ba..8c5d17fd 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -212,7 +212,51 @@ jobs: shell: bash - - uses: tauri-apps/tauri-action@v0 + - name: Run Tauri Action (Attempt 1) + id: tauri_attempt_1 + continue-on-error: true + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ github.token }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + with: + releaseId: ${{ needs.create-release.outputs.release_id }} + updaterJsonPreferNsis: true + tagName: ${{ env.GIT_TAG_NAME }} + + - name: Run Tauri Action (Attempt 2) + id: tauri_attempt_2 + if: steps.tauri_attempt_1.outcome == 'failure' + continue-on-error: true + uses: tauri-apps/tauri-action@v0 + env: + GITHUB_TOKEN: ${{ github.token }} + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} + APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} + APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + with: + releaseId: ${{ needs.create-release.outputs.release_id }} + updaterJsonPreferNsis: true + tagName: ${{ env.GIT_TAG_NAME }} + + - name: Run Tauri Action (Attempt 3 - Final) + id: tauri_attempt_3 + if: steps.tauri_attempt_2.outcome == 'failure' + uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ github.token }} TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} From 22ad4b6293f5b43242a5d5b956566cd5f4f940f1 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 31 Jan 2025 03:08:58 +0000 Subject: [PATCH 649/864] ci: update phcode version to 4.0.3 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 6b70b1a8..6c56d0ac 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "4.0.2", + "version": "4.0.3", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "cdab8e31c04f5877129c93840cd3ec07d7f71dcf" + "commit": "4cbb29f33b4cd2aeea01ebd33f452a0ea48770e0" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4a770cad..290cbdf4 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "4.0.2" +version = "4.0.3" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 494a7075..c4776b42 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "4.0.2" + "version": "4.0.3" }, "tauri": { "allowlist": { From e951a1d8935c38bd26b1ccdbe30c991689324e62 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 31 Jan 2025 10:54:33 +0000 Subject: [PATCH 650/864] ci: tauri release update notification json --- docs/install.json | 6 +++--- docs/tauri/update-latest-stable-prod.json | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/install.json b/docs/install.json index 4b08d969..6b66eecc 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,8 +1,8 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_3.10.0_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_3.10.0_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_3.10.0_x64.dmg", + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_4.0.3_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_4.0.3_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_4.0.3_x64.dmg", "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 3d13f380..61ab8b87 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,19 +1,19 @@ { - "version": "3.10.0", - "notes": "November release(3.10) of Phoenix Code is now available.\r\n\r\nThis month's core theme is `Editor UI improvements`. We have fine-tuned the editing experience for better \r\nperformance and visual feedback.\r\nWe've also made substantial improvements to [docs.phcode.dev](https://docs.phcode.dev) to better support extension\r\ndevelopers.\r\n\r\n## Indent Guide Lines\r\n\r\nPhoenix Code now supports indent guidelines to help you better visualize code structure. This feature can\r\nbe toggled via `View > Indent Guide Lines`. [Read more...](https://docs.phcode.dev/docs/editing-text#indent-guide-lines)\r\n\r\n![image](https://github.com/user-attachments/assets/3d9d0c55-3c9e-4ab3-bbc0-53b563d19e39)\r\n\r\n## Customizable Editor Line Height\r\n\r\nTheme Settings (`View > Themes...`) now has a new `Line Height` slider. Adjust the editor line height between 1x and 3x to find your\r\nperfect balance of readability and screen real estate. [Read more...](https://docs.phcode.dev/docs/editing-text#line-height)\r\n\r\nAlso added a `Get More...` button to the Themes dialog, linking directly to the themes section in Extension Manager.\r\n\r\n![image](https://github.com/user-attachments/assets/97a46d9a-e971-401d-8a77-015afa6d5972)\r\n\r\n## `Line:Col` Indicator Relocation\r\n\r\nMoved to the right of the status bar, accommodating future status bar extensions. Click on the `line:col` section in the\r\nstatusbar to jump to specific lines.\r\n\r\n![image](https://github.com/user-attachments/assets/540ea992-dda0-4a2c-8042-3c6228616636)\r\n\r\n## Performance Tweaks\r\n\r\n- [Major improvements to editor rendering](https://github.com/phcode-dev/phoenix/pull/1943) with better editor scroll\r\n consistency and performance, especially on Safari and macOS.\r\n- [Faster startup of extension manager.](https://github.com/phcode-dev/phoenix/pull/1937)\r\n\r\n## Stability Improvements\r\n\r\n- [File recovery now does integrity checks for more reliable crash recovery.](https://github.com/phcode-dev/phoenix/pull/1889)\r\n- [Fixed Markdown image link handling within href tags.](https://github.com/phcode-dev/phoenix/pull/1838)\r\n- [Improved extension registry management to prevent quota issues on Mac/Linux.](https://github.com/phcode-dev/phoenix/pull/1932)\r\n\r\n## Documentation Updates\r\nOur documentation site - [docs.phcode.dev](https://docs.phcode.dev) has received a major overhaul:\r\n\r\n- Updated user guide: [docs.phcode.dev/docs/intro](https://docs.phcode.dev/docs/intro)\r\n- New API documentation for extension developers: [docs.phcode.dev/api/getting-started](https://docs.phcode.dev/api/getting-started)\r\n\r\n## All changes\r\n\r\nPlease see [this link](https://github.com/phcode-dev/phoenix/commits/main/?since=2024-09-11&until=2024-11-24) for a full list of changes\r\nin GitHub.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev). Every contribution helps us\r\n to keep improving Phoenix Code.\r\n", - "pub_date": "2024-11-25T06:03:19.592Z", + "version": "4.0.3", + "notes": "2025 January release(4.0) of Phoenix Code is now available for download at [phcode.io](https://phcode.io).\r\n\r\nThis is the largest release we had in a while, and we are happy to announce the next phase of Phoenix Code with\r\na major version bump to 4.0.\r\n\r\n## The legacy of Brackets - Continued\r\nA decade-long journey of pushing web development forward: The Brackets story continues with Phoenix Code.\r\n[Read more about the story of Brackets and the journey to build Phoenix Code and the Brackets community.](https://docs.phcode.dev/blog/Blog-Legacy)\r\n\r\nThis release's core theme is `Git, Color previews, UX imporovements and stability`.\r\n\r\n## Git for Desktop\r\n\r\nGit is finally here. Integrated Git source control with a clean, intuitive interface. Stage changes, commit, and sync with a single click while keeping your focus on the code. Now available in the Windows, Mac and Linux desktop apps of Phoenix code. [Read More...](https://docs.phcode.dev/docs/Features/git)\r\n\r\nOur Git integration is built upon the incredible work of the developers behind [Brackets-Git](https://github.com/brackets-userland/brackets-git), whose contributions made this possible. Thank you!\r\n\r\n![Image](https://github.com/user-attachments/assets/aeacc7c0-3ee3-4a80-9b05-f2b48140bcdd)\r\n\r\n![Image](https://github.com/user-attachments/assets/6e7b9faf-d57b-448b-a5bb-a111c67489b5)\r\n\r\n## Color Previews\r\n\r\nPreview the color(s) used in the file in the gutter area. Hovering over a color box highlights the corresponding color text in the editor to quickly jump to editing that color. [Read More...](https://docs.phcode.dev/docs/editing-colors#color-preview)\r\n\r\n![image](https://github.com/user-attachments/assets/bedecc32-761b-448e-aced-61828ad3fec6)\r\n\r\n## Open in Terminal and File Explorer\r\n\r\nNew \"Open In\" feature lets you instantly open directories and files in the system Terminal or File Explorer across Windows, macOS, and Linux desktop apps!\r\n\r\n![Image](https://github.com/user-attachments/assets/710330ae-8b34-4a51-a1f9-4c02736ed9bd)\r\n\r\n## Better Translations\r\n\r\nWe've moved to an LLM-assisted translation framework, delivering higher-quality translations for non-English locales.\r\n\r\n## Notable changes and fixes\r\n\r\n- We've removed some inconsistent and rarely used keyboard shortcuts to free up more key combinations for customization.\r\n [Easily configure your own keyboard shortcuts through the UI.](https://docs.phcode.dev/docs/Features/keyboard-shortcuts)\r\n- Fixed `Option-[shift]-left` and `option-[shift]-right` keyboard shortcuts not working in mac to select/move words.\r\n- Survey popups are now less intrusive, appearing as notifications without disrupting your workflow.\r\n- Moved back `line:ch` status to left of statusbar. Go to line will accept `:ln:col` format along with `:ln,col`. ![Image](https://github.com/user-attachments/assets/7429ae42-cb56-444c-8546-6d565bedaaf9)\r\n- [Remove specific files from Recent Files](https://github.com/phcode-dev/phoenix/pull/2035)\r\n- Fixes [holding ctrl key in windows should not ui overlay mode.](https://github.com/phcode-dev/phoenix/pull/2015)\r\n- [fix: `cmd-click` in mac app and safari didn't open context menu.](https://github.com/phcode-dev/phoenix/pull/1994)\r\n- [Switching between Ctrl+F and Ctrl+Shift+F now correctly updates the search box with the latest selection.](https://github.com/phcode-dev/phoenix/pull/1999)\r\n- [fix: clicking on prevent defaulted A tags in desktop live preview opens browser tab.](https://github.com/phcode-dev/phoenix/pull/1997)\r\n \r\n## Performance & Stability Tweaks\r\n\r\n- [Faster boot times with extension compression and load changes](https://github.com/phcode-dev/phoenix/pull/2055)\r\n consistency and performance, especially on Safari and macOS.\r\n- [File recovery should only be shown on crash, and fix some file recovery issues.](https://github.com/phcode-dev/phoenix/pull/2082)\r\n\r\n## All changes\r\n\r\nPlease see [this link](https://github.com/phcode-dev/phoenix/commits/main/?since=2024-11-27&until=2025-01-30) for a full list of changes in GitHub.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev). Every contribution helps us to keep improving Phoenix Code.\r\n\r\nWith gratitude,\r\n\r\nThe Phoenix Team\r\n", + "pub_date": "2025-01-31T06:06:16.997Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1QQkhLZDVpZUsrbUVVbjhnUlpvSk94eS9ybXVISTVWcDZRVW9peDVDK3g5Z2RiUkk5MXloVGN5c3h5MXcyYUMrK1JRbjg4QzJ3dkluM1ZHSURCemdzPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTEyMTQzCWZpbGU6UGhvZW5peCBDb2RlXzMuMTAuMF94NjQtc2V0dXAubnNpcy56aXAKb1NGendmUTNkOWM1Z2lFbTU2Q2FGbkFqREhjLzB2NEhKclRBclZpcFE4NkcwSHZ1TGhFbjVhMTdwbVptTmtwT3NlWGV2QXFiUWljeHl6NTdZSzhGQ2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_3.10.0_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmpZZHVoMXU4OUs5UWJKcE1jSFh3Tk5hVFdMbkNzaXd0WmV3cm5kcVJQWmZHb3FiZURjNUxXRnJLZUJZWmFvUkgvNmRXYUhMZFBXOGdaekZYM1VpM3dNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzM4Mjk0MDcwCWZpbGU6UGhvZW5peCBDb2RlXzQuMC4zX3g2NC1zZXR1cC5uc2lzLnppcAp3aWc1cnBWbVdpbGZmUk1iUU1DWTJLc2tBQ3lVclJMZFp2N1lqWjNqUzVwcjdHWmVDTzF3QVVPZDZMQUFDWUJNZXRMci92Q0lyOGpHeVNjWmE1NGhDZz09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_4.0.3_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnFVVkZMNktUaEQzVjY4ZzRmdUNiRVZFRm9IZHVvSlFjMGxvMFBSYmc0aHhKOFZ2L1ZNdnNCdSsyTldaMEVFUEdqeU9QYS9aQzlFaUMrMDRIeTVVbHdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE0MDAwCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKaWJxVmZub2VEdHJNOHZ5N3ZGSXJ0ZDE3bEZnL0dYNDFrT2V2MGViTFFmc3p5UlFIZEFjU0xmSHk0aVh0RmVzOTFDMk9hTzQxQnB5M1ZKc2ZHejlrQkE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhSVTJWSjlNaG43SU1HM3dRNk9yZDc3SDRnMlZzb3UxRllCazI3KzNTejU2S0Z3Mk1lb2t0dE1JMUl2akwwa2s5SnR2ZldDRmc0OVdGZHFocHREZEFvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzM4MzAyOTI0CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKOTNMTnpMZE9XcXhUV1haK1BZUDdUampBSU9UWmR4S3Y2eWRZemRqMzNNQ1pTeGd4VllhT2trQW55bFBleXBLSzhDRUI1Rzl6OXFIMDFCWmo4SDdKQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxrcjJuK0twWUdwSFJKcjZHYUozby9ZdFdLMmM3Z1AxTDV4Z0NCSmJLT1RvbTJtTHNQODlZMlBQbHhzZ1hQU2xlRndPVklmMU4zU1RoOExpL1AxT0FZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE0NTkyCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKMFV4bmtGZlJCNDJuQkhFYnVEZWxmUk44Y1piNXlzSVcwaVk1TFRGOUNndWplN0FScTRxQU9zOE92N2Q1b3pvL01SY1h2SEM0ZEZaUllBSVhCeTFxQlE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v3.10.0/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmd1Rm9SOWRndHBhbHN5MHFTckV3RzJ1SVlIdDhaY1FYakYxcWJrSnp2TTJFZUhmUHYvUDcvMk1yMVhxanRNZlJtTTlOeFJaVU1ZL1VEd0k3R1lxVmdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzM4MzAzNTY4CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKcnJHOFBDdFRwZUtTY0h0c0JSSTVMT2RPM0s1aXlVcEdtYjVxK0VTVFNzZDlKRnJJZG14dkxtSkFmb0diNUZrZmJ2SjNkcm5HMDFpbFJzN2RacXB1QUE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 1a0cf74a34d4071ebdf16669dcc96d2c75cedb9f Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 3 Feb 2025 22:23:33 +0530 Subject: [PATCH 651/864] chore: update site features list in phcode.io --- docs/siteNotifications/en.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json index 2749b38d..52fbab88 100644 --- a/docs/siteNotifications/en.json +++ b/docs/siteNotifications/en.json @@ -30,6 +30,12 @@ "subtitle": "Find exactly what you need across your entire project with Instant search. We've fine-tuned the UX to help you pinpoint your query faster: search within specific file types, exclude files and folders, or use regular expressions for complex queries. Read more...", "titleIconSrc": "assets/images/flash.gif", "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/find_in_files.mp4" + }, + { + "title": "Git Simplified", + "subtitle": "Integrated Git source control with a clean, intuitive interface. Stage changes, commit, and sync with a single click while keeping your focus on the code. Read more...", + "titleIconSrc": "assets/images/git_branch_feature.svg", + "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/git_video.mp4" } ] } \ No newline at end of file From c8bc81096a2c78d6fe9a4b6391c0b3d7c4fb044b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Jan 2025 16:30:57 +0000 Subject: [PATCH 652/864] chore(deps): update dependency chalk to v5.4.1 --- package-lock.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3b6b9402..4cf9cce1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "3.10.0", + "version": "4.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "3.10.0", + "version": "4.0.2", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.3", @@ -484,10 +484,11 @@ } }, "node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, + "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, From 93de2d8cf20968aecec9bb3c365df3ed11347514 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 30 Jan 2025 16:31:03 +0000 Subject: [PATCH 653/864] chore(deps): update dependency execa to v9.5.2 --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4cf9cce1..74e3af50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -636,9 +636,9 @@ "dev": true }, "node_modules/execa": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.4.0.tgz", - "integrity": "sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", + "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==", "dev": true, "license": "MIT", "dependencies": { From dff68816029b37647a35dd2df297f0b8a226fae3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 5 Jan 2025 13:44:38 +0000 Subject: [PATCH 654/864] fix(deps): update rust crate os_info to v3.9.2 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9fd67931..2fc09a58 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2935,9 +2935,9 @@ dependencies = [ [[package]] name = "os_info" -version = "3.8.2" +version = "3.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae99c7fa6dd38c7cafe1ec085e804f8f555a2f8659b0dbe03f1f9963a9b51092" +checksum = "6e6520c8cc998c5741ee68ec1dc369fc47e5f0ea5320018ecf2a1ccd6328f48b" dependencies = [ "log", "serde", From af3ab9f5fcaee39f753d4f22d98381c9cf70ae11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 18:46:45 +0000 Subject: [PATCH 655/864] build(deps): bump openssl from 0.10.66 to 0.10.70 in /src-tauri Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.66 to 0.10.70. - [Release notes](https://github.com/sfackler/rust-openssl/releases) - [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.66...openssl-v0.10.70) --- updated-dependencies: - dependency-name: openssl dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 2fc09a58..4b4a5328 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2875,9 +2875,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.66" +version = "0.10.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" dependencies = [ "bitflags 2.5.0", "cfg-if 1.0.0", @@ -2907,9 +2907,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", @@ -3178,7 +3178,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "3.10.0" +version = "4.0.3" dependencies = [ "backtrace", "chrono", From 2782cd993edbc79269df4c221a1c2fa0c4583608 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 4 Feb 2025 10:39:17 +0530 Subject: [PATCH 656/864] fix: broken doc link in whcode.io website --- docs/siteNotifications/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json index 52fbab88..5fb3985d 100644 --- a/docs/siteNotifications/en.json +++ b/docs/siteNotifications/en.json @@ -15,7 +15,7 @@ "features": [ { "title": "Live Preview", - "subtitle": "See your HTML and CSS code changes instantly, without page reloads! Use powerful UI tools like the colour editor to tweak background and text colours, adjust font sizes and border-radius with number dials, or explore page layouts with live code hints. Read more...", + "subtitle": "See your HTML and CSS code changes instantly, without page reloads! Use powerful UI tools like the colour editor to tweak background and text colours, adjust font sizes and border-radius with number dials, or explore page layouts with live code hints. Read more...", "titleIconSrc": "assets/images/preview_o.png", "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/live_preview.mp4" }, From 88ca82cc96d6d99e3f605ba5e238803c0cc4be4d Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 26 Feb 2025 19:54:27 +0530 Subject: [PATCH 657/864] fix: installer was not working for kde neon 24.01 --- docs/linux/installer.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 98caed0e..c8125ffd 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -136,6 +136,10 @@ check_os_version() { linuxmint:22) # Linux Mint 22.x return 0 ;; + neon:24) # KDE Neon 24.x + return 0 + ;; + kali:2024|kali:20[2-9][0-9]) # Kali 2024.x or newer return 0 ;; @@ -313,7 +317,7 @@ download_and_install_gtk() { # - This piece of code should only be executed if the package manager does not distribute # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. - local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.3/" + local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.4/" local GTK_FILE="gtk.tar.xz" local WEBKIT2GTK_FILE="webkit2gtk-4.0.tar.xz" From a78639d72059785b26ec9132ab8dae5a31ec77bc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Feb 2025 03:28:39 +0000 Subject: [PATCH 658/864] fix(deps): update rust crate serde_json to v1.0.139 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 4b4a5328..ad96aa79 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3884,9 +3884,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", From 2e4780fe4205f07d4b8872cbcf392d126616efc4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 8 Feb 2025 01:11:30 +0000 Subject: [PATCH 659/864] fix(deps): update rust crate once_cell to v1.20.3 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ad96aa79..94851456 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2859,9 +2859,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "open" From 6eaed960736c88f16fc466f96377d9f35b403039 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 8 Feb 2025 01:11:37 +0000 Subject: [PATCH 660/864] fix(deps): update rust crate reqwest to v0.12.12 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 94851456..ae2a64cf 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2392,7 +2392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -3193,7 +3193,7 @@ dependencies = [ "os_info", "percent-encoding", "regex", - "reqwest 0.12.11", + "reqwest 0.12.12", "serde", "serde_json", "tauri", @@ -3585,9 +3585,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.11" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe060fe50f524be480214aba758c71f99f90ee8c83c5a36b5e9e1d568eb4eb3" +checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64 0.22.1", "bytes", From bcc5328baef6b7b56761ca629156af6d3a336324 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 2 Mar 2025 14:09:59 +0530 Subject: [PATCH 661/864] feat: totp credential storage in system keychain all plats for auth --- src-tauri/Cargo.lock | 215 +++++++++++++++++++++++++++++++++++++++++- src-tauri/Cargo.toml | 3 + src-tauri/src/main.rs | 90 ++++++++++++++++++ 3 files changed, 305 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index ae2a64cf..db45a60e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -23,6 +23,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if 1.0.0", + "cipher", + "cpufeatures", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -327,6 +338,18 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "base32" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" + +[[package]] +name = "base32" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" + [[package]] name = "base64" version = "0.13.1" @@ -381,6 +404,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + [[package]] name = "block2" version = "0.5.1" @@ -498,6 +530,15 @@ dependencies = [ "toml 0.7.8", ] +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.1.6" @@ -573,6 +614,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "3.2.25" @@ -702,6 +753,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "constant_time_eq" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" + [[package]] name = "convert_case" version = "0.4.0" @@ -968,6 +1025,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -1877,6 +1935,24 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.9" @@ -1991,7 +2067,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -2193,6 +2269,16 @@ dependencies = [ "cfb", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + [[package]] name = "instant" version = "0.1.12" @@ -2360,6 +2446,20 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "keyring" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "363387f0019d714aa60cc30ab4fe501a747f4c08fc58f069dd14be971bd495a0" +dependencies = [ + "byteorder", + "lazy_static", + "linux-keyutils", + "secret-service", + "security-framework", + "windows-sys 0.52.0", +] + [[package]] name = "kuchikiki" version = "0.8.2" @@ -2412,6 +2512,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" +[[package]] +name = "linux-keyutils" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e" +dependencies = [ + "bitflags 2.5.0", + "libc", +] + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -2723,17 +2833,81 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -3181,11 +3355,13 @@ name = "phoenix-code-ide" version = "4.0.3" dependencies = [ "backtrace", + "base32 0.5.1", "chrono", "clipboard-files", "dialog", "fix-path-env", "gtk", + "keyring", "lazy_static", "native-dialog", "objc", @@ -3203,6 +3379,7 @@ dependencies = [ "tauri-plugin-single-instance", "tauri-plugin-window-state", "tokio", + "totp-rs", "trash", "webbrowser", "webkit2gtk", @@ -3810,6 +3987,25 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "secret-service" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5204d39df37f06d1944935232fd2dfe05008def7ca599bf28c0800366c8a8f9" +dependencies = [ + "aes", + "cbc", + "futures-util", + "generic-array", + "hkdf", + "num", + "once_cell", + "rand 0.8.5", + "serde", + "sha2", + "zbus", +] + [[package]] name = "security-framework" version = "2.9.2" @@ -4926,6 +5122,19 @@ dependencies = [ "winnow 0.6.5", ] +[[package]] +name = "totp-rs" +version = "5.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b2f27dad992486c26b4e7455f38aa487e838d6d61b57e72906ee2b8c287a90" +dependencies = [ + "base32 0.4.0", + "constant_time_eq", + "hmac", + "sha1", + "sha2", +] + [[package]] name = "tower" version = "0.5.2" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 290cbdf4..3b10a643 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -33,6 +33,9 @@ tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } +keyring = "2.3.3" +totp-rs = "5.6.0" +base32 = "0.5.1" [target.'cfg(target_os = "windows")'.dependencies] native-dialog = "0.7.0" diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index f9e30582..84eabd44 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -46,6 +46,12 @@ use trash; mod platform; use tauri_plugin_window_state::StateFlags; +use keyring::Entry; +use totp_rs::{Algorithm, Secret, TOTP}; +use std::time::{SystemTime, UNIX_EPOCH}; +use serde_json::json; +use base32::{Alphabet, encode as base32_encode}; + #[derive(Clone, serde::Serialize)] struct Payload { args: Vec, @@ -297,6 +303,89 @@ fn get_mac_deep_link_requests() -> Vec { } } +const PHOENIX_CRED_PREFIX: &str = "phcode_"; + +// Stores or updates the sessionID and OTP seed securely. The otp_seed can never be read from js and only +// the 30-second valid t-otp can be read. this helps improving security posture with auth flows as +// unsecure extensions are not being able to get long term session tokens. +// A compromised extension will need real time control of the editor instance to get the changing session +// otp to steal user session serving as a deterrent. +#[tauri::command] +fn store_credential(scope_name: String, session_id: String, otp_seed: String) -> Result<(), String> { + let service = format!("{}{}", PHOENIX_CRED_PREFIX, scope_name); // Unique service name per scope + + // Combine sessionID and OTP seed into one stored value + let credential_data = format!("{}|{}", session_id, otp_seed); + + let entry = Entry::new(&service, "default_user").map_err(|e| e.to_string())?; + entry.set_password(&credential_data).map_err(|e| e.to_string())?; + + Ok(()) +} + +// Deletes a stored credential securely +#[tauri::command] +fn delete_credential(scope_name: String) -> Result<(), String> { + let service = format!("{}{}", PHOENIX_CRED_PREFIX, scope_name); + + let entry = Entry::new(&service, "default_user").map_err(|e| e.to_string())?; + entry.delete_password().map_err(|e| e.to_string())?; + + Ok(()) +} + +// credential is applied on seed that is base32:Rfc4648 encoded +#[tauri::command] +fn get_credential_otp(scope_name: String) -> serde_json::Value { + let service = format!("{}{}", PHOENIX_CRED_PREFIX, scope_name); + let entry = match Entry::new(&service, "default_user") { + Ok(entry) => entry, + Err(_) => return json!({ "err_code": "CREDENTIAL_ERROR" }), // Error creating keyring entry + }; + + // Retrieve stored credentials + let stored_data = match entry.get_password() { + Ok(data) => data, + Err(keyring::Error::NoEntry) => return json!({ "err_code": "NO_ENTRY" }), // No credentials stored + Err(_) => return json!({ "err_code": "RETRIEVE_ERROR" }), // Other keyring errors + }; + + let parts: Vec<&str> = stored_data.split('|').collect(); + if parts.len() != 2 { + return json!({ "err_code": "INVALID_FORMAT" }); // Data stored incorrectly + } + + let session_id = parts[0].to_string(); + let otp_seed = parts[1]; + + // Convert the OTP seed to Base32 (Required for TOTP) + let otp_seed_base32 = base32_encode(Alphabet::Rfc4648 { padding: false }, otp_seed.as_bytes()); + + // Convert the Base32-encoded OTP seed into a Secret + let secret = match Secret::Encoded(otp_seed_base32).to_bytes() { + Ok(secret) => secret, + Err(_) => return json!({ "err_code": "SECRET_ERROR" }), // Error converting seed + }; + + // Create a TOTP instance + let totp = match TOTP::new(Algorithm::SHA1, 6, 1, 30, secret) { + Ok(totp) => totp, + Err(_) => return json!({ "err_code": "TOTP_CREATION_ERROR" }), // Error creating TOTP instance + }; + + // Get the current timestamp (Unix time in seconds) + let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + + // Generate the OTP + let otp = totp.generate(timestamp); + + // Return JSON with sessionID and OTP + json!({ + "session_id": session_id, + "totp": otp + }) +} + fn main() { let args: Vec = env::args().collect(); @@ -436,6 +525,7 @@ fn main() { get_mac_deep_link_requests, get_process_id, toggle_devtools, console_log, console_error, _get_commandline_args, get_current_working_dir, _get_window_labels, + store_credential, get_credential_otp, delete_credential, put_item, get_item, get_all_items, delete_item, _get_windows_drives, _rename_path, show_in_folder, move_to_trash, zoom_window, _get_clipboard_files, _open_url_in_browser_win]) From e011487c9d994be9c5456a777f3e4a8b4413b86b Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 2 Mar 2025 14:53:50 +0530 Subject: [PATCH 662/864] fix: use current username for keyring RW --- src-tauri/Cargo.lock | 33 ++++++++++++++++++++++++++++++--- src-tauri/Cargo.toml | 1 + src-tauri/src/main.rs | 18 +++++++++++++++--- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index db45a60e..151e8b03 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1322,7 +1322,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.4.1", "windows-sys 0.52.0", ] @@ -2503,7 +2503,7 @@ checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ "bitflags 2.5.0", "libc", - "redox_syscall", + "redox_syscall 0.4.1", ] [[package]] @@ -3189,7 +3189,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", ] @@ -3383,6 +3383,7 @@ dependencies = [ "trash", "webbrowser", "webkit2gtk", + "whoami", "winapi 0.3.9", ] @@ -3663,6 +3664,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b568323e98e49e2a0899dcee453dd679fae22d69adf9b11dd508d1549b7e2f" +dependencies = [ + "bitflags 2.5.0", +] + [[package]] name = "redox_users" version = "0.4.4" @@ -5466,6 +5476,12 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.92" @@ -5759,6 +5775,17 @@ dependencies = [ "rustix 0.38.32", ] +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall 0.5.9", + "wasite", + "web-sys", +] + [[package]] name = "winapi" version = "0.2.8" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3b10a643..94405a40 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -36,6 +36,7 @@ fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } keyring = "2.3.3" totp-rs = "5.6.0" base32 = "0.5.1" +whoami = "1.5.2" [target.'cfg(target_os = "windows")'.dependencies] native-dialog = "0.7.0" diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 84eabd44..17f0c6d1 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -51,6 +51,7 @@ use totp_rs::{Algorithm, Secret, TOTP}; use std::time::{SystemTime, UNIX_EPOCH}; use serde_json::json; use base32::{Alphabet, encode as base32_encode}; +use whoami; #[derive(Clone, serde::Serialize)] struct Payload { @@ -305,6 +306,14 @@ fn get_mac_deep_link_requests() -> Vec { const PHOENIX_CRED_PREFIX: &str = "phcode_"; +fn get_username() -> String { + // Ensure a fallback username in case retrieval fails + match whoami::username().as_str() { + "" => "unknown_user".to_string(), // Fallback if username is empty + username => username.to_string(), // Otherwise, use the retrieved username + } +} + // Stores or updates the sessionID and OTP seed securely. The otp_seed can never be read from js and only // the 30-second valid t-otp can be read. this helps improving security posture with auth flows as // unsecure extensions are not being able to get long term session tokens. @@ -313,11 +322,12 @@ const PHOENIX_CRED_PREFIX: &str = "phcode_"; #[tauri::command] fn store_credential(scope_name: String, session_id: String, otp_seed: String) -> Result<(), String> { let service = format!("{}{}", PHOENIX_CRED_PREFIX, scope_name); // Unique service name per scope + let user = get_username(); // Combine sessionID and OTP seed into one stored value let credential_data = format!("{}|{}", session_id, otp_seed); - let entry = Entry::new(&service, "default_user").map_err(|e| e.to_string())?; + let entry = Entry::new(&service, &user).map_err(|e| e.to_string())?; entry.set_password(&credential_data).map_err(|e| e.to_string())?; Ok(()) @@ -327,8 +337,9 @@ fn store_credential(scope_name: String, session_id: String, otp_seed: String) -> #[tauri::command] fn delete_credential(scope_name: String) -> Result<(), String> { let service = format!("{}{}", PHOENIX_CRED_PREFIX, scope_name); + let user = get_username(); - let entry = Entry::new(&service, "default_user").map_err(|e| e.to_string())?; + let entry = Entry::new(&service, &user).map_err(|e| e.to_string())?; entry.delete_password().map_err(|e| e.to_string())?; Ok(()) @@ -338,7 +349,8 @@ fn delete_credential(scope_name: String) -> Result<(), String> { #[tauri::command] fn get_credential_otp(scope_name: String) -> serde_json::Value { let service = format!("{}{}", PHOENIX_CRED_PREFIX, scope_name); - let entry = match Entry::new(&service, "default_user") { + let user = get_username(); + let entry = match Entry::new(&service, &user) { Ok(entry) => entry, Err(_) => return json!({ "err_code": "CREDENTIAL_ERROR" }), // Error creating keyring entry }; From ea39cabcd40cb74c7608d32d4f2d5c96e300daad Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 2 Mar 2025 17:05:11 +0530 Subject: [PATCH 663/864] fix: seed too short error if invalid seed length --- src-tauri/src/main.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 17f0c6d1..312cdf4e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -305,6 +305,7 @@ fn get_mac_deep_link_requests() -> Vec { } const PHOENIX_CRED_PREFIX: &str = "phcode_"; +const MIN_SEED_LENGTH: usize = 10; // Minimum required length for a valid TOTP seed fn get_username() -> String { // Ensure a fallback username in case retrieval fails @@ -324,6 +325,14 @@ fn store_credential(scope_name: String, session_id: String, otp_seed: String) -> let service = format!("{}{}", PHOENIX_CRED_PREFIX, scope_name); // Unique service name per scope let user = get_username(); + // Check if the seed is too short + if otp_seed.len() < MIN_SEED_LENGTH { + return Err(format!( + "SEED_TOO_SHORT: Seed length must be at least {} characters, but got {}.", + MIN_SEED_LENGTH, otp_seed.len() + )); + } + // Combine sessionID and OTP seed into one stored value let credential_data = format!("{}|{}", session_id, otp_seed); @@ -370,8 +379,15 @@ fn get_credential_otp(scope_name: String) -> serde_json::Value { let session_id = parts[0].to_string(); let otp_seed = parts[1]; + if otp_seed.len() < MIN_SEED_LENGTH { + return json!({ + "err_code": "SEED_TOO_SHORT", + "message": format!("Seed length must be at least {} characters, but got {}.", MIN_SEED_LENGTH, otp_seed.len()) + }); + } + // Convert the OTP seed to Base32 (Required for TOTP) - let otp_seed_base32 = base32_encode(Alphabet::Rfc4648 { padding: false }, otp_seed.as_bytes()); + let otp_seed_base32 = base32_encode(Alphabet::Rfc4648 { padding: true }, otp_seed.as_bytes()); // Convert the Base32-encoded OTP seed into a Secret let secret = match Secret::Encoded(otp_seed_base32).to_bytes() { From 19992035cc0d5a0c158721d45e1a7a59d4b5a8ad Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 02:37:45 +0000 Subject: [PATCH 664/864] fix(deps): update rust crate chrono to v0.4.40 --- src-tauri/Cargo.lock | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 151e8b03..b3f4ab01 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -601,9 +601,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "chrono" -version = "0.4.39" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" dependencies = [ "android-tzdata", "iana-time-zone", @@ -611,7 +611,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -5948,6 +5948,12 @@ dependencies = [ "syn 2.0.92", ] +[[package]] +name = "windows-link" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" + [[package]] name = "windows-metadata" version = "0.39.0" From bfed172262e56914666ea7e7b1cb7a5ad1525d0b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 02:37:56 +0000 Subject: [PATCH 665/864] fix(deps): update rust crate serde to v1.0.218 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index b3f4ab01..e351af2f 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4070,18 +4070,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.217" +version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", From 271caf58e374a60c4f56389e216b4dadf061bb5d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 01:24:44 +0000 Subject: [PATCH 666/864] fix(deps): update rust crate serde_json to v1.0.140 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e351af2f..bd11beed 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4090,9 +4090,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.139" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f86c3acccc9c65b153fe1b85a3be07fe5515274ec9f0653b4a0875731c72a6" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "indexmap 2.2.6", "itoa 1.0.10", From 441aaf84584eeba62494d6858d97580cf7c3364f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 06:23:34 +0000 Subject: [PATCH 667/864] chore(deps): update dependency fs-extra to v11.3.0 --- package-lock.json | 13 +++++++------ package.json | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 74e3af50..0a4cc871 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "4.0.2", + "version": "4.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "4.0.2", + "version": "4.0.3", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.3", @@ -16,7 +16,7 @@ "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", - "fs-extra": "11.2.0", + "fs-extra": "11.3.0", "shx": "^0.3.4", "tar": "7.4.3" } @@ -752,10 +752,11 @@ } }, "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", diff --git a/package.json b/package.json index 6c56d0ac..30c8d80b 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", "execa": "^9.0.0", - "fs-extra": "11.2.0", + "fs-extra": "11.3.0", "shx": "^0.3.4", "tar": "7.4.3", "axios": "1.7.9", From ececa107f23d69f0161a239bdc75aebf16a174af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Mar 2025 17:07:51 +0000 Subject: [PATCH 668/864] build(deps): bump ring from 0.17.8 to 0.17.13 in /src-tauri Bumps [ring](https://github.com/briansmith/ring) from 0.17.8 to 0.17.13. - [Changelog](https://github.com/briansmith/ring/blob/main/RELEASES.md) - [Commits](https://github.com/briansmith/ring/commits) --- updated-dependencies: - dependency-name: ring dependency-type: indirect ... Signed-off-by: dependabot[bot] --- src-tauri/Cargo.lock | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index bd11beed..7973716b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -541,9 +541,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.6" +version = "1.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +dependencies = [ + "shlex", +] [[package]] name = "cesu8" @@ -2492,7 +2495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -3840,15 +3843,14 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.8" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +checksum = "70ac5d832aa16abd7d1def883a8545280c20a60f523a370aa3a9617c2b8550ee" dependencies = [ "cc", "cfg-if 1.0.0", "getrandom 0.2.12", "libc", - "spin", "untrusted", "windows-sys 0.52.0", ] @@ -4236,6 +4238,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -4320,12 +4328,6 @@ dependencies = [ "system-deps 5.0.0", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "stable_deref_trait" version = "1.2.0" From 683d8253bcd521fd051b30dd7fae9765ce60fad9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 08:41:39 +0000 Subject: [PATCH 669/864] fix(deps): update rust crate os_info to v3.10.0 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 7973716b..832c2ff7 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3112,9 +3112,9 @@ dependencies = [ [[package]] name = "os_info" -version = "3.9.2" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6520c8cc998c5741ee68ec1dc369fc47e5f0ea5320018ecf2a1ccd6328f48b" +checksum = "2a604e53c24761286860eba4e2c8b23a0161526476b1de520139d69cdb85a6b5" dependencies = [ "log", "serde", From 665a4a8e13243d12a4717a9048f1bf2cb8427d23 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 08:41:51 +0000 Subject: [PATCH 670/864] build(deps-dev): bump axios from 1.7.9 to 1.8.2 Bumps [axios](https://github.com/axios/axios) from 1.7.9 to 1.8.2. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](https://github.com/axios/axios/compare/v1.7.9...v1.8.2) --- updated-dependencies: - dependency-name: axios dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0a4cc871..08942b67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.6.3", "adm-zip": "0.5.16", - "axios": "1.7.9", + "axios": "1.8.2", "axios-retry": "4.5.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -410,9 +410,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz", + "integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 30c8d80b..1337d394 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.3.0", "shx": "^0.3.4", "tar": "7.4.3", - "axios": "1.7.9", + "axios": "1.8.2", "axios-retry": "4.5.0" }, "phoenixRepo": { From 57dc16133358c837b334b527dca4b723d5e575a1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 18:50:18 +0000 Subject: [PATCH 671/864] fix(deps): update rust crate trash to v5.2.2 --- src-tauri/Cargo.lock | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 832c2ff7..f735be87 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2495,7 +2495,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -5237,9 +5237,9 @@ dependencies = [ [[package]] name = "trash" -version = "5.1.1" +version = "5.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33caf2a9be1812a263a4bfce74d2de225fcde12ee7b77001361abd2b34ffdcc4" +checksum = "22746c6b0c6d85d60a8f0d858f7057dfdf11297c132679f452ec908fba42b871" dependencies = [ "chrono", "libc", @@ -5247,6 +5247,7 @@ dependencies = [ "objc2 0.5.2", "objc2-foundation", "once_cell", + "percent-encoding", "scopeguard", "urlencoding", "windows 0.56.0", From 59659363646c08b853fa67b0aa74c3adbb13bc43 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 8 Mar 2025 18:50:10 +0000 Subject: [PATCH 672/864] fix(deps): update rust crate tokio to v1.44.0 --- src-tauri/Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f735be87..8b54cee8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2070,7 +2070,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.5.6", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -2484,9 +2484,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" [[package]] name = "libloading" @@ -5004,9 +5004,9 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" [[package]] name = "tokio" -version = "1.41.0" +version = "1.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "9975ea0f48b5aa3972bf2d888c238182458437cc2a19374b81b25cdf1023fb3a" dependencies = [ "backtrace", "bytes", @@ -5022,9 +5022,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", From 7230e588434317e981a062216af498fd3327d035 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 06:31:47 +0000 Subject: [PATCH 673/864] chore(deps): update dependency axios to v1.8.3 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 08942b67..b9ee5287 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.6.3", "adm-zip": "0.5.16", - "axios": "1.8.2", + "axios": "1.8.3", "axios-retry": "4.5.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -410,9 +410,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz", - "integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", + "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 1337d394..1cb6c1c1 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.3.0", "shx": "^0.3.4", "tar": "7.4.3", - "axios": "1.8.2", + "axios": "1.8.3", "axios-retry": "4.5.0" }, "phoenixRepo": { From 24dd87bb7fbaa5d6fd86f4813bbd82000e7fa897 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 02:33:03 +0000 Subject: [PATCH 674/864] fix(deps): update rust crate reqwest to v0.12.14 --- src-tauri/Cargo.lock | 124 +++++++++++++++++++++++++++++++++---------- 1 file changed, 96 insertions(+), 28 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 8b54cee8..298ab672 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2409,10 +2409,11 @@ checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -3372,7 +3373,7 @@ dependencies = [ "os_info", "percent-encoding", "regex", - "reqwest 0.12.12", + "reqwest 0.12.14", "serde", "serde_json", "tauri", @@ -3775,9 +3776,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.12" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" +checksum = "989e327e510263980e231de548a33e63d34962d29ae61b467389a1a09627a254" dependencies = [ "base64 0.22.1", "bytes", @@ -5487,23 +5488,24 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if 1.0.0", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn 2.0.92", @@ -5524,9 +5526,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5534,9 +5536,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -5547,9 +5549,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "wasm-streams" @@ -5965,13 +5970,13 @@ checksum = "9ee5e275231f07c6e240d14f34e1b635bf1faa1c76c57cfd59a5cdb9848e4278" [[package]] name = "windows-registry" -version = "0.2.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ - "windows-result 0.2.0", + "windows-result 0.3.1", "windows-strings", - "windows-targets 0.52.6", + "windows-targets 0.53.0", ] [[package]] @@ -5985,21 +5990,20 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" dependencies = [ - "windows-targets 0.52.6", + "windows-link", ] [[package]] name = "windows-strings" -version = "0.1.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -6083,13 +6087,29 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm", + "windows_i686_gnullvm 0.52.6", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + [[package]] name = "windows-tokens" version = "0.39.0" @@ -6123,6 +6143,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.37.0" @@ -6153,6 +6179,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.37.0" @@ -6183,12 +6215,24 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.37.0" @@ -6219,6 +6263,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.37.0" @@ -6249,6 +6299,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -6267,6 +6323,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.37.0" @@ -6297,6 +6359,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "winnow" version = "0.5.40" From 573d4f8daffc6474aaef98074cb707ad982326ef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 17:31:54 +0000 Subject: [PATCH 675/864] fix(deps): update rust crate tokio to v1.44.1 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 298ab672..cc62769a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -5005,9 +5005,9 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" [[package]] name = "tokio" -version = "1.44.0" +version = "1.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9975ea0f48b5aa3972bf2d888c238182458437cc2a19374b81b25cdf1023fb3a" +checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" dependencies = [ "backtrace", "bytes", From a99bff8bcbb5ed2f2af110355393ea1caa5bebe2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 17:31:47 +0000 Subject: [PATCH 676/864] fix(deps): update rust crate serde to v1.0.219 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index cc62769a..87fafdd9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -4073,18 +4073,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", From a67421e96a8d525f047c81603ad8b61d297657d9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:06:39 +0000 Subject: [PATCH 677/864] fix(deps): update rust crate once_cell to v1.21.1 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 87fafdd9..9bc37b0e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3037,9 +3037,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" [[package]] name = "open" From 6ef38a74635cca0e22cb450e277663bd909df8e5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:05:49 +0000 Subject: [PATCH 678/864] fix(deps): update rust crate webbrowser to v1.0.4 --- src-tauri/Cargo.lock | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 9bc37b0e..09305a4d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2496,7 +2496,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -2981,7 +2981,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" dependencies = [ "objc-sys", - "objc2-encode 4.0.3", + "objc2-encode 4.1.0", +] + +[[package]] +name = "objc2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59" +dependencies = [ + "objc2-encode 4.1.0", ] [[package]] @@ -2992,9 +3001,9 @@ checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" [[package]] name = "objc2-encode" -version = "4.0.3" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] name = "objc2-foundation" @@ -3008,6 +3017,16 @@ dependencies = [ "objc2 0.5.2", ] +[[package]] +name = "objc2-foundation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" +dependencies = [ + "bitflags 2.5.0", + "objc2 0.6.0", +] + [[package]] name = "objc_exception" version = "0.1.2" @@ -5246,7 +5265,7 @@ dependencies = [ "libc", "log", "objc2 0.5.2", - "objc2-foundation", + "objc2-foundation 0.2.2", "once_cell", "percent-encoding", "scopeguard", @@ -5654,18 +5673,17 @@ dependencies = [ [[package]] name = "webbrowser" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9fe1ebb156110ff855242c1101df158b822487e4957b0556d9ffce9db0f535" +checksum = "d5df295f8451142f1856b1bd86a606dfe9587d439bc036e319c827700dbd555e" dependencies = [ - "block2", "core-foundation 0.10.0", "home", "jni 0.21.1", "log", "ndk-context", - "objc2 0.5.2", - "objc2-foundation", + "objc2 0.6.0", + "objc2-foundation 0.3.0", "url", "web-sys", ] From d680aa73ab365e52464c86a676a125f42114ca6a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 22 Mar 2025 02:57:10 +0000 Subject: [PATCH 679/864] chore(deps): update dependency axios to v1.8.4 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index b9ee5287..5f45672c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "devDependencies": { "@tauri-apps/cli": "1.6.3", "adm-zip": "0.5.16", - "axios": "1.8.3", + "axios": "1.8.4", "axios-retry": "4.5.0", "chalk": "^5.3.0", "chokidar-cli": "^3.0.0", @@ -410,9 +410,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", - "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 1cb6c1c1..efa5292d 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "fs-extra": "11.3.0", "shx": "^0.3.4", "tar": "7.4.3", - "axios": "1.8.3", + "axios": "1.8.4", "axios-retry": "4.5.0" }, "phoenixRepo": { From 9fbabf57c217d06922f0cbc1dd678af11be6f797 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 22 Mar 2025 02:57:53 +0000 Subject: [PATCH 680/864] fix(deps): update rust crate reqwest to v0.12.15 --- src-tauri/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 09305a4d..50be2354 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2496,7 +2496,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if 1.0.0", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -3392,7 +3392,7 @@ dependencies = [ "os_info", "percent-encoding", "regex", - "reqwest 0.12.14", + "reqwest 0.12.15", "serde", "serde_json", "tauri", @@ -3795,9 +3795,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.14" +version = "0.12.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e327e510263980e231de548a33e63d34962d29ae61b467389a1a09627a254" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" dependencies = [ "base64 0.22.1", "bytes", From 85bb879c686aec12a2f22adca59bee21448b49a6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 29 Mar 2025 02:13:26 +0000 Subject: [PATCH 681/864] chore(deps): update dependency shx to ^0.4.0 --- package-lock.json | 454 ++++++++++++++++++++++++++++++++++++---------- package.json | 2 +- 2 files changed, 357 insertions(+), 99 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5f45672c..879eebf1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "chokidar-cli": "^3.0.0", "execa": "^9.0.0", "fs-extra": "11.3.0", - "shx": "^0.3.4", + "shx": "^0.4.0", "tar": "7.4.3" } }, @@ -129,6 +129,44 @@ "node": ">=18.0.0" } }, + "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/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -452,23 +490,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "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.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -585,12 +614,6 @@ "node": ">= 0.8" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -635,6 +658,16 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/execa": { "version": "9.5.2", "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", @@ -662,6 +695,33 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "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.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/figures": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", @@ -678,10 +738,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "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" }, @@ -766,12 +827,6 @@ "node": ">=14.14" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -820,26 +875,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -880,22 +915,6 @@ "node": ">=18.18.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "node_modules/interpret": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", @@ -964,6 +983,7 @@ "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" } @@ -1086,6 +1106,30 @@ "node": "14 || >=16.14" } }, + "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/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -1107,18 +1151,6 @@ "node": ">= 0.6" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -1165,6 +1197,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "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/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -1208,10 +1247,21 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "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/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -1269,15 +1319,6 @@ "node": ">=4" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -1342,6 +1383,38 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "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/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -1398,6 +1471,17 @@ "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/rimraf": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.7.tgz", @@ -1462,6 +1546,30 @@ "url": "https://github.com/sponsors/isaacs" } }, + "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": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -1503,36 +1611,174 @@ } }, "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "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": { - "glob": "^7.0.0", + "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/shelljs/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/shelljs/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/shelljs/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/shelljs/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/shelljs/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/shelljs/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/shelljs/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/shelljs/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/shelljs/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/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/shelljs/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/shx": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", - "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==", + "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.3", - "shelljs": "^0.8.5" + "minimist": "^1.2.8", + "shelljs": "^0.9.2" }, "bin": { "shx": "lib/cli.js" }, "engines": { - "node": ">=6" + "node": ">=18" } }, "node_modules/signal-exit": { @@ -1646,6 +1892,16 @@ "node": ">=8" } }, + "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/strip-final-newline": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", @@ -1693,6 +1949,7 @@ "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" }, @@ -1862,7 +2119,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/y18n": { "version": "4.0.3", diff --git a/package.json b/package.json index efa5292d..b88ae40f 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,7 @@ "chokidar-cli": "^3.0.0", "execa": "^9.0.0", "fs-extra": "11.3.0", - "shx": "^0.3.4", + "shx": "^0.4.0", "tar": "7.4.3", "axios": "1.8.4", "axios-retry": "4.5.0" From 4e6911f6ba792be14bdcaa785735d2c66066e8f3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 29 Mar 2025 02:13:07 +0000 Subject: [PATCH 682/864] fix(deps): update rust crate once_cell to v1.21.3 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 50be2354..f2e713c9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3056,9 +3056,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "open" From 719757d5d14c7124f9f031ee23283c52875ed208 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 29 Mar 2025 07:36:28 +0000 Subject: [PATCH 683/864] fix(deps): update rust crate whoami to v1.6.0 --- src-tauri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f2e713c9..3376a14b 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -5803,9 +5803,9 @@ dependencies = [ [[package]] name = "whoami" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" dependencies = [ "redox_syscall 0.5.9", "wasite", From ab5d5ffd04fbbab770c1ef6250cd0ec5323289c2 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 9 Apr 2025 21:17:01 +0530 Subject: [PATCH 684/864] fix: macos entitlements hardening --- entitlements.plist | 4 ---- 1 file changed, 4 deletions(-) diff --git a/entitlements.plist b/entitlements.plist index 045df8ea..273caa29 100644 --- a/entitlements.plist +++ b/entitlements.plist @@ -8,10 +8,6 @@ com.apple.security.cs.disable-executable-page-protection - com.apple.security.cs.allow-dyld-environment-variables - - com.apple.security.cs.disable-library-validation - com.apple.security.get-task-allow From 8795f27672af7be30348cbca6cbcae68eeb45519 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 9 Apr 2025 16:16:18 +0000 Subject: [PATCH 685/864] ci: update phcode version to 4.1.0 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b88ae40f..bc3dffa6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "4.0.3", + "version": "4.1.0", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "4cbb29f33b4cd2aeea01ebd33f452a0ea48770e0" + "commit": "ae4a1230a171f885d3112f8cedc1343f429bef02" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 94405a40..484b9bdd 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "4.0.3" +version = "4.1.0" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c4776b42..9d0c1303 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "4.0.3" + "version": "4.1.0" }, "tauri": { "allowlist": { From 2ef09c0e816b9d45bf305cd9700dc9d12b0aba37 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 9 Apr 2025 22:39:58 +0530 Subject: [PATCH 686/864] fix: mac notarize fail --- entitlements.plist | 2 -- 1 file changed, 2 deletions(-) diff --git a/entitlements.plist b/entitlements.plist index 273caa29..68fea254 100644 --- a/entitlements.plist +++ b/entitlements.plist @@ -8,7 +8,5 @@ com.apple.security.cs.disable-executable-page-protection - com.apple.security.get-task-allow - From 8c73b0360fd75265fb24c67c716e5ff844260761 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 1 Mar 2025 05:09:37 +0000 Subject: [PATCH 687/864] fix(deps): update tauri monorepo --- src-tauri/Cargo.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 3376a14b..5839137e 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -440,9 +440,9 @@ dependencies = [ [[package]] name = "brotli" -version = "6.0.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" +checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -2070,7 +2070,7 @@ dependencies = [ "httpdate", "itoa 1.0.10", "pin-project-lite", - "socket2 0.4.10", + "socket2 0.5.6", "tokio", "tower-service", "tracing", @@ -2187,9 +2187,9 @@ dependencies = [ [[package]] name = "ico" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3804960be0bb5e4edb1e1ad67afd321a9ecfd875c3e65c099468fd2717d7cae" +checksum = "cc50b891e4acf8fe0e71ef88ec43ad82ee07b3810ad09de10f1d01f072ed4b98" dependencies = [ "byteorder", "png", @@ -4613,9 +4613,9 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "tauri" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf327e247698d3f39af8aa99401c9708384290d1f5c544bf5d251d44c2fea22" +checksum = "e1be4ef682d128826ba4bce70a5cd18b7f5c5803e347835a2c6fed2d6ef3a690" dependencies = [ "anyhow", "base64 0.22.1", @@ -4680,9 +4680,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "1.5.5" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "586f3e677f940c8bb4f70c52eda05dc59b79e61543f1182de83516810bb8e35d" +checksum = "2db08694eec06f53625cfc6fff3a363e084e5e9a238166d2989996413c346453" dependencies = [ "anyhow", "cargo_toml", @@ -4699,9 +4699,9 @@ dependencies = [ [[package]] name = "tauri-codegen" -version = "1.4.5" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93a9e3f5cebf779a63bf24903e714ec91196c307d8249a0008b882424328bcda" +checksum = "53438d78c4a037ffe5eafa19e447eea599bedfb10844cb08ec53c2471ac3ac3f" dependencies = [ "base64 0.21.7", "brotli", @@ -4725,9 +4725,9 @@ dependencies = [ [[package]] name = "tauri-macros" -version = "1.4.6" +version = "1.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1d0e989f54fe06c5ef0875c5e19cf96453d099a0a774d5192ab47e80471cdab" +checksum = "233988ac08c1ed3fe794cd65528d48d8f7ed4ab3895ca64cdaa6ad4d00c45c0b" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -4795,9 +4795,9 @@ dependencies = [ [[package]] name = "tauri-runtime" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33fda7d213e239077fad52e96c6b734cecedb30c2382118b64f94cb5103ff3a" +checksum = "8066855882f00172935e3fa7d945126580c34dcbabab43f5d4f0c2398a67d47b" dependencies = [ "gtk", "http 0.2.12", @@ -4816,9 +4816,9 @@ dependencies = [ [[package]] name = "tauri-runtime-wry" -version = "0.14.10" +version = "0.14.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18c447dcd9b0f09c7dc4b752cc33e72788805bfd761fbda5692d30c48289efec" +checksum = "ce361fec1e186705371f1c64ae9dd2a3a6768bc530d0a2d5e75a634bb416ad4d" dependencies = [ "arboard", "cocoa 0.24.1", @@ -4837,9 +4837,9 @@ dependencies = [ [[package]] name = "tauri-utils" -version = "1.6.1" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0c939e88d82903a0a7dfb28388b12a3c03504d6bd6086550edaa3b6d8beaa" +checksum = "c357952645e679de02cd35007190fcbce869b93ffc61b029f33fe02648453774" dependencies = [ "brotli", "ctor", From f2b770e3af1f212da245b4c31c553fdb3e7d87f5 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 11 Apr 2025 16:19:43 +0530 Subject: [PATCH 688/864] fix: npm run serve fails after rust update, locked rust to 1.85.1 --- .github/workflows/desktop-linux-test-pull.yml | 2 ++ .github/workflows/desktop-mac-m1-test-pull.yml | 2 ++ .github/workflows/desktop-mac-test-pull.yml | 2 ++ .github/workflows/desktop-windows-test-pull.yml | 2 ++ .github/workflows/prod-desktop-tests-on-pull.yml | 6 ++++++ .github/workflows/staging-desktop-tests-on-pull.yml | 6 ++++++ .github/workflows/tauri-build-dev.yml | 4 ++++ .github/workflows/tauri-build-prod.yml | 4 ++++ .github/workflows/tauri-build-staging.yml | 4 ++++ src-tauri/rust-toolchain | 1 + 10 files changed, 33 insertions(+) create mode 100644 src-tauri/rust-toolchain diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index f831cf31..0b7c0d0a 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -19,6 +19,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: install dependencies (ubuntu only) run: | diff --git a/.github/workflows/desktop-mac-m1-test-pull.yml b/.github/workflows/desktop-mac-m1-test-pull.yml index 21e29956..25348a69 100644 --- a/.github/workflows/desktop-mac-m1-test-pull.yml +++ b/.github/workflows/desktop-mac-m1-test-pull.yml @@ -21,6 +21,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: npm install ci deps env: diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 28414e89..6513fac3 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -19,6 +19,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: npm install ci deps env: diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index df048e88..d712521f 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -19,6 +19,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: npm install ci deps env: diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index be9021e3..e90c0a8c 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -17,6 +17,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: install dependencies (ubuntu only) run: | @@ -92,6 +94,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: npm install ci deps env: @@ -162,6 +166,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: npm install ci deps env: diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index 6195d58e..ee1f4b10 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -17,6 +17,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: install dependencies (ubuntu only) run: | @@ -87,6 +89,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: npm install ci deps env: @@ -148,6 +152,8 @@ jobs: node-version: 20 - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: npm install ci deps env: diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index feb124c6..5233e1be 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -100,6 +100,8 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} @@ -288,6 +290,8 @@ jobs: ldd --version - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: install dependencies (ubuntu only) run: | sudo apt-get update diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 8c5d17fd..349f8ae3 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -100,6 +100,8 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} @@ -332,6 +334,8 @@ jobs: ldd --version - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: install dependencies (ubuntu only) run: | sudo apt-get update diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 55cce5ec..e08c58bc 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -100,6 +100,8 @@ jobs: - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: install frontend dependencies run: | npm ci @@ -285,6 +287,8 @@ jobs: ldd --version - name: install Rust stable uses: dtolnay/rust-toolchain@stable + with: + toolchain: 1.85.1 - name: install dependencies (ubuntu only) run: | sudo apt-get update diff --git a/src-tauri/rust-toolchain b/src-tauri/rust-toolchain new file mode 100644 index 00000000..20f3b74a --- /dev/null +++ b/src-tauri/rust-toolchain @@ -0,0 +1 @@ +1.85.1 \ No newline at end of file From 1ac29134d756667b79d2e7833c62a83f56ef1f8d Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 17 Apr 2025 13:57:22 +0530 Subject: [PATCH 689/864] chore: schools ai notification --- docs/appNotifications/prod/de/banner.json | 8 +++++++- docs/appNotifications/prod/fr/banner.json | 8 +++++++- docs/appNotifications/prod/it/banner.json | 8 +++++++- docs/appNotifications/prod/ja/banner.json | 8 +++++++- docs/appNotifications/prod/ko/banner.json | 8 +++++++- docs/appNotifications/prod/pt-BR/banner.json | 8 +++++++- docs/appNotifications/prod/root/banner.json | 8 +++++++- 7 files changed, 49 insertions(+), 7 deletions(-) diff --git a/docs/appNotifications/prod/de/banner.json b/docs/appNotifications/prod/de/banner.json index 8e2023df..a277553d 100644 --- a/docs/appNotifications/prod/de/banner.json +++ b/docs/appNotifications/prod/de/banner.json @@ -4,5 +4,11 @@ "HTML_CONTENT": "

Wir stellen vor Phoenix Code Desktop-Apps für Windows, Mac und Linux. Klicken Sie hier, um es jetzt zu erhalten!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "DISABLE_AI_FOR_EDUCATION_NOTICE": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Achtung Schulen: Phoenix Code AI

Phoenix Code AI wird ab dem 20. Mai 2025 eingeführt. Bildungseinrichtungen sollten diese Anleitung befolgen, um AI campusweit vor diesem Datum zu deaktivieren/konfigurieren.

" + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM": "all" } -} \ No newline at end of file +} diff --git a/docs/appNotifications/prod/fr/banner.json b/docs/appNotifications/prod/fr/banner.json index 5a4bf362..7f81b04e 100644 --- a/docs/appNotifications/prod/fr/banner.json +++ b/docs/appNotifications/prod/fr/banner.json @@ -4,5 +4,11 @@ "HTML_CONTENT": "
Présentation des applications de bureau de Phoenix Code pour Windows, Mac et Linux. Cliquez ici pour l'obtenir maintenant !
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "DISABLE_AI_FOR_EDUCATION_NOTICE": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Attention écoles : Phoenix Code AI

Phoenix Code AI sera déployé après le 20 mai 2025. Les établissements scolaires doivent suivre ce guide pour désactiver/configurer l'IA à l'échelle du campus avant cette date.

", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM": "all" } -} \ No newline at end of file +} diff --git a/docs/appNotifications/prod/it/banner.json b/docs/appNotifications/prod/it/banner.json index 0d5a41bd..d2a19727 100644 --- a/docs/appNotifications/prod/it/banner.json +++ b/docs/appNotifications/prod/it/banner.json @@ -4,5 +4,11 @@ "HTML_CONTENT": "
Presentazione delle app desktop di Phoenix Code per Windows, Mac e Linux. Fai clic qui per ottenerlo ora!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "DISABLE_AI_FOR_EDUCATION_NOTICE": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Attenzione scuole: Phoenix Code AI

Phoenix Code AI sarà distribuito dopo il 20 maggio 2025. Gli istituti scolastici devono seguire questa guida per disattivare/configurare l'AI in tutto il campus prima di questa data.

", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM": "all" } -} \ No newline at end of file +} diff --git a/docs/appNotifications/prod/ja/banner.json b/docs/appNotifications/prod/ja/banner.json index 4192b1e2..d83c9f9c 100644 --- a/docs/appNotifications/prod/ja/banner.json +++ b/docs/appNotifications/prod/ja/banner.json @@ -4,5 +4,11 @@ "HTML_CONTENT": "
Windows、Mac、Linux 用の Phoenix Code のデスクトップ アプリを紹介します。 ここをクリックして今すぐ入手してください。
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "DISABLE_AI_FOR_EDUCATION_NOTICE": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
学校向け通知: Phoenix Code AI

Phoenix Code AIは2025年5月20日以降に展開されます。教育機関はこの日までにこちらのガイドに従って、AIを無効化または構成してください。

", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM": "all" } -} \ No newline at end of file +} diff --git a/docs/appNotifications/prod/ko/banner.json b/docs/appNotifications/prod/ko/banner.json index ddd01e81..2e558e54 100644 --- a/docs/appNotifications/prod/ko/banner.json +++ b/docs/appNotifications/prod/ko/banner.json @@ -4,5 +4,11 @@ "HTML_CONTENT": "
Windows, Mac 및 Linux용 소개 Phoenix Code 데스크톱 앱. 지금 다운로드하려면 여기를 클릭하세요!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "DISABLE_AI_FOR_EDUCATION_NOTICE": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
학교 주의사항: Phoenix Code AI

Phoenix Code AI는 2025년 5월 20일 이후 출시됩니다. 교육기관은 이 날짜 전에 이 가이드를 따라 AI를 비활성화하거나 설정해야 합니다.

", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM": "all" } -} \ No newline at end of file +} diff --git a/docs/appNotifications/prod/pt-BR/banner.json b/docs/appNotifications/prod/pt-BR/banner.json index c86e06ac..21c574c5 100644 --- a/docs/appNotifications/prod/pt-BR/banner.json +++ b/docs/appNotifications/prod/pt-BR/banner.json @@ -4,5 +4,11 @@ "HTML_CONTENT": "
Apresentamos os aplicativos de desktop Phoenix Code para Windows, Mac e Linux. Clique aqui para obtê-lo agora!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "DISABLE_AI_FOR_EDUCATION_NOTICE": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Atenção escolas: Phoenix Code AI

O Phoenix Code AI será lançado após 20 de maio de 2025. As instituições educacionais devem seguir este guia para desativar/configurar a IA em todo o campus antes dessa data.

", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM": "all" } -} \ No newline at end of file +} diff --git a/docs/appNotifications/prod/root/banner.json b/docs/appNotifications/prod/root/banner.json index af561164..64136041 100644 --- a/docs/appNotifications/prod/root/banner.json +++ b/docs/appNotifications/prod/root/banner.json @@ -4,5 +4,11 @@ "HTML_CONTENT": "
Introducing Phoenix Code Desktop Apps for Windows, Mac & Linux. Click here to get it now!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "DISABLE_AI_FOR_EDUCATION_NOTICE": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Attention schools: Phoenix Code AI

Phoenix Code AI will be rolled out after May 20, 2025. Educational institutions should follow this guide to disable/configure AI campus-wide before this date.

", + "FOR_VERSIONS": ">=3.0.0", + "PLATFORM": "all" } -} \ No newline at end of file +} From 3a7b19934786e2aee5bff35fb9f1d58e69c18076 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 9 Jun 2025 12:01:22 +0530 Subject: [PATCH 690/864] fix: installer borken in ubuntu 25 --- docs/linux/installer.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index c8125ffd..965f0fb5 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -133,6 +133,9 @@ check_os_version() { ubuntu:24) # Ubuntu 24.x return 0 ;; + ubuntu:25) # Ubuntu 25.x + return 0 + ;; linuxmint:22) # Linux Mint 22.x return 0 ;; @@ -317,7 +320,7 @@ download_and_install_gtk() { # - This piece of code should only be executed if the package manager does not distribute # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. - local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.4/" + local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.5/" local GTK_FILE="gtk.tar.xz" local WEBKIT2GTK_FILE="webkit2gtk-4.0.tar.xz" From 4bd0c2072001fc3b3f0aebdb83c58194decf4083 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 10 Jun 2025 11:24:55 +0530 Subject: [PATCH 691/864] feta: window aes trust ring apis --- src-tauri/Cargo.lock | 109 +++++++++++++++------- src-tauri/Cargo.toml | 6 +- src-tauri/src/main.rs | 212 ++++++++++++++++++++++++++++-------------- 3 files changed, 220 insertions(+), 107 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 5839137e..548ab58f 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -23,6 +23,16 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + [[package]] name = "aes" version = "0.8.4" @@ -34,6 +44,20 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "aes-gcm" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -338,18 +362,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "base32" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" - -[[package]] -name = "base32" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022dfe9eb35f19ebbcb51e0b40a5ab759f46ad60cadf7297e0bd085afb50e076" - [[package]] name = "base64" version = "0.13.1" @@ -756,12 +768,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "constant_time_eq" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" - [[package]] name = "convert_case" version = "0.4.0" @@ -890,6 +896,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array", + "rand_core 0.6.4", "typenum", ] @@ -930,6 +937,15 @@ dependencies = [ "syn 2.0.92", ] +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + [[package]] name = "darling" version = "0.20.8" @@ -1680,6 +1696,16 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + [[package]] name = "gimli" version = "0.31.0" @@ -3060,6 +3086,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "open" version = "3.2.0" @@ -3375,15 +3407,16 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "4.0.3" +version = "4.1.0" dependencies = [ + "aes-gcm", "backtrace", - "base32 0.5.1", "chrono", "clipboard-files", "dialog", "fix-path-env", "gtk", + "hex", "keyring", "lazy_static", "native-dialog", @@ -3402,7 +3435,6 @@ dependencies = [ "tauri-plugin-single-instance", "tauri-plugin-window-state", "tokio", - "totp-rs", "trash", "webbrowser", "webkit2gtk", @@ -3497,6 +3529,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -5154,19 +5198,6 @@ dependencies = [ "winnow 0.6.5", ] -[[package]] -name = "totp-rs" -version = "5.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b2f27dad992486c26b4e7455f38aa487e838d6d61b57e72906ee2b8c287a90" -dependencies = [ - "base32 0.4.0", - "constant_time_eq", - "hmac", - "sha1", - "sha2", -] - [[package]] name = "tower" version = "0.5.2" @@ -5337,6 +5368,16 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 484b9bdd..618a5458 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -34,9 +34,11 @@ tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-works tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } keyring = "2.3.3" -totp-rs = "5.6.0" -base32 = "0.5.1" whoami = "1.5.2" +# AES encryption dependencies +# AES encryption dependencies +aes-gcm = "0.10" +hex = "0.4.3" [target.'cfg(target_os = "windows")'.dependencies] native-dialog = "0.7.0" diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 312cdf4e..6b1452e1 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -47,10 +47,6 @@ mod platform; use tauri_plugin_window_state::StateFlags; use keyring::Entry; -use totp_rs::{Algorithm, Secret, TOTP}; -use std::time::{SystemTime, UNIX_EPOCH}; -use serde_json::json; -use base32::{Alphabet, encode as base32_encode}; use whoami; #[derive(Clone, serde::Serialize)] @@ -59,6 +55,17 @@ struct Payload { cwd: String, } +// AES Key Trust Management Structure +#[derive(Clone, Debug)] +struct AesKeyData { + key: String, + iv: String, +} + +struct WindowAesTrust { + trust_map: Mutex>, +} + // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command #[tauri::command] fn console_log(_handle: tauri::AppHandle, message: &str) { @@ -176,6 +183,74 @@ fn delete_item(state: State<'_, Storage>, key: String) { } // in memory hashmap end +// AES Key Trust Management Commands +#[tauri::command] +fn trust_window_aes_key(window: tauri::Window, key: String, iv: String, trust_state: State<'_, WindowAesTrust>) -> Result<(), String> { + let window_label = window.label().to_string(); + let mut trust_map = trust_state.trust_map.lock().unwrap(); + + // Check if trust is already established + if trust_map.contains_key(&window_label) { + return Err("Trust has already been established for this window. remove trust to set again.".to_string()); + } + + // Validate AES key format and length + let key_bytes = hex::decode(&key).map_err(|_| "Invalid AES key format. Key must be a valid hex string.".to_string())?; + if key_bytes.len() != 32 { + return Err("Invalid AES key length. Key must be 32 bytes (64 hex characters) for AES-256.".to_string()); + } + + // Validate nonce format and length + let nonce_bytes = hex::decode(&iv).map_err(|_| "Invalid nonce format. Nonce must be a valid hex string.".to_string())?; + if nonce_bytes.len() != 12 { + return Err("Invalid nonce length. Nonce must be 12 bytes (24 hex characters) for AES-GCM.".to_string()); + } + + // Test that we can create a valid cipher with these parameters + use aes_gcm::{Aes256Gcm, Key}; + use aes_gcm::aead::KeyInit; + + let aes_key = Key::::from_slice(&key_bytes); + let _cipher = Aes256Gcm::new(aes_key); + + // Just verify we can create a slice of the right size - no need to store it + if nonce_bytes.len() == 12 { + // This validates that we have the right size for AES-GCM nonce + } else { + return Err("Invalid nonce length. Nonce must be 12 bytes (24 hex characters) for AES-GCM.".to_string()); + } + + // If we get here, the key and nonce are valid + // Store the AES key and IV for this window + trust_map.insert(window_label.clone(), AesKeyData { key, iv }); + + println!("AES trust established for window: {}", window_label); + Ok(()) +} + +#[tauri::command] +fn remove_trust_window_aes_key(window: tauri::Window, key: String, iv: String, trust_state: State<'_, WindowAesTrust>) -> Result<(), String> { + let window_label = window.label().to_string(); + let mut trust_map = trust_state.trust_map.lock().unwrap(); + + // Check if trust exists for this window + match trust_map.get(&window_label) { + Some(stored_data) => { + // Verify the provided key and IV match the stored ones + if stored_data.key == key && stored_data.iv == iv { + trust_map.remove(&window_label); + println!("AES trust removed for window: {}", window_label); + Ok(()) + } else { + Err("Provided key and IV do not match the stored trust data.".to_string()) + } + } + None => { + Err("No trust association found for this window.".to_string()) + } + } +} + static mut DEVTOOLS_LOADED:bool = false; #[tauri::command] @@ -264,8 +339,16 @@ fn zoom_window(window: tauri::Window, scale_factor: f64) { }); } -fn process_window_event(event: &GlobalWindowEvent) { +fn process_window_event(event: &GlobalWindowEvent, trust_state: &State) { if let tauri::WindowEvent::CloseRequested { .. } = event.event() { + // Remove AES trust for the closing window + let window_label = event.window().label().to_string(); + let mut trust_map = trust_state.trust_map.lock().unwrap(); + + if trust_map.remove(&window_label).is_some() { + println!("AES trust removed for closing window: {}", window_label); + } + // this does nothing and is here if in future you need to persist something on window close. boot_config::write_boot_config(1); } @@ -305,7 +388,6 @@ fn get_mac_deep_link_requests() -> Vec { } const PHOENIX_CRED_PREFIX: &str = "phcode_"; -const MIN_SEED_LENGTH: usize = 10; // Minimum required length for a valid TOTP seed fn get_username() -> String { // Ensure a fallback username in case retrieval fails @@ -315,29 +397,14 @@ fn get_username() -> String { } } -// Stores or updates the sessionID and OTP seed securely. The otp_seed can never be read from js and only -// the 30-second valid t-otp can be read. this helps improving security posture with auth flows as -// unsecure extensions are not being able to get long term session tokens. -// A compromised extension will need real time control of the editor instance to get the changing session -// otp to steal user session serving as a deterrent. +// Stores the secret value securely in the system keyring #[tauri::command] -fn store_credential(scope_name: String, session_id: String, otp_seed: String) -> Result<(), String> { +fn store_credential(scope_name: String, secret_val: String) -> Result<(), String> { let service = format!("{}{}", PHOENIX_CRED_PREFIX, scope_name); // Unique service name per scope let user = get_username(); - // Check if the seed is too short - if otp_seed.len() < MIN_SEED_LENGTH { - return Err(format!( - "SEED_TOO_SHORT: Seed length must be at least {} characters, but got {}.", - MIN_SEED_LENGTH, otp_seed.len() - )); - } - - // Combine sessionID and OTP seed into one stored value - let credential_data = format!("{}|{}", session_id, otp_seed); - let entry = Entry::new(&service, &user).map_err(|e| e.to_string())?; - entry.set_password(&credential_data).map_err(|e| e.to_string())?; + entry.set_password(&secret_val).map_err(|e| e.to_string())?; Ok(()) } @@ -354,64 +421,58 @@ fn delete_credential(scope_name: String) -> Result<(), String> { Ok(()) } -// credential is applied on seed that is base32:Rfc4648 encoded +// Gets the stored credential, encrypts it with the window's AES key, and returns the encrypted value #[tauri::command] -fn get_credential_otp(scope_name: String) -> serde_json::Value { +fn get_credential(window: tauri::Window, scope_name: String, trust_state: State<'_, WindowAesTrust>) -> Result { + let window_label = window.label().to_string(); + + // Check if AES trust is established for this window + let trust_map = trust_state.trust_map.lock().unwrap(); + let aes_data = match trust_map.get(&window_label) { + Some(data) => data.clone(), + None => { + return Err("Trust needs to be first established by calling the trust_window_aes_key API to use this API.".to_string()); + } + }; + drop(trust_map); // Release the lock early + + // Retrieve the stored credential let service = format!("{}{}", PHOENIX_CRED_PREFIX, scope_name); let user = get_username(); - let entry = match Entry::new(&service, &user) { - Ok(entry) => entry, - Err(_) => return json!({ "err_code": "CREDENTIAL_ERROR" }), // Error creating keyring entry - }; + let entry = Entry::new(&service, &user).map_err(|e| e.to_string())?; - // Retrieve stored credentials - let stored_data = match entry.get_password() { + let stored_credential = match entry.get_password() { Ok(data) => data, - Err(keyring::Error::NoEntry) => return json!({ "err_code": "NO_ENTRY" }), // No credentials stored - Err(_) => return json!({ "err_code": "RETRIEVE_ERROR" }), // Other keyring errors + Err(keyring::Error::NoEntry) => return Err("No credential found for the specified scope.".to_string()), + Err(e) => return Err(format!("Failed to retrieve credential: {}", e.to_string())), }; - let parts: Vec<&str> = stored_data.split('|').collect(); - if parts.len() != 2 { - return json!({ "err_code": "INVALID_FORMAT" }); // Data stored incorrectly - } + // Encrypt the credential using AES-GCM + use aes_gcm::{Aes256Gcm, Key, Nonce}; + use aes_gcm::aead::{Aead, KeyInit}; - let session_id = parts[0].to_string(); - let otp_seed = parts[1]; + // Decode the key and nonce from hex strings + let key_bytes = hex::decode(&aes_data.key).map_err(|_| "Invalid AES key format".to_string())?; + let nonce_bytes = hex::decode(&aes_data.iv).map_err(|_| "Invalid nonce format".to_string())?; - if otp_seed.len() < MIN_SEED_LENGTH { - return json!({ - "err_code": "SEED_TOO_SHORT", - "message": format!("Seed length must be at least {} characters, but got {}.", MIN_SEED_LENGTH, otp_seed.len()) - }); + if key_bytes.len() != 32 { + return Err("AES key must be 32 bytes (256 bits)".to_string()); + } + if nonce_bytes.len() != 12 { + return Err("Nonce must be 12 bytes for AES-GCM".to_string()); } - // Convert the OTP seed to Base32 (Required for TOTP) - let otp_seed_base32 = base32_encode(Alphabet::Rfc4648 { padding: true }, otp_seed.as_bytes()); - - // Convert the Base32-encoded OTP seed into a Secret - let secret = match Secret::Encoded(otp_seed_base32).to_bytes() { - Ok(secret) => secret, - Err(_) => return json!({ "err_code": "SECRET_ERROR" }), // Error converting seed - }; - - // Create a TOTP instance - let totp = match TOTP::new(Algorithm::SHA1, 6, 1, 30, secret) { - Ok(totp) => totp, - Err(_) => return json!({ "err_code": "TOTP_CREATION_ERROR" }), // Error creating TOTP instance - }; - - // Get the current timestamp (Unix time in seconds) - let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(); + // Create cipher + let key = Key::::from_slice(&key_bytes); + let cipher = Aes256Gcm::new(key); + let nonce = Nonce::from_slice(&nonce_bytes); - // Generate the OTP - let otp = totp.generate(timestamp); + // Encrypt the credential + let encrypted_data = cipher.encrypt(nonce, stored_credential.as_bytes()) + .map_err(|_| "Failed to encrypt credential".to_string())?; - // Return JSON with sessionID and OTP - json!({ - "session_id": session_id, - "totp": otp - }) + // Return the encrypted data as a hex string + Ok(hex::encode(encrypted_data)) } fn main() { @@ -496,6 +557,9 @@ fn main() { .manage(Storage { map: Mutex::new(HashMap::new()), }) + .manage(WindowAesTrust { + trust_map: Mutex::new(HashMap::new()), + }) .register_uri_scheme_protocol("phtauri", move |app, request| { // can't use `tauri` because that's already in use let path = remove_version_from_url(request.uri()); let path = path.strip_prefix("phtauri://localhost"); @@ -548,13 +612,19 @@ fn main() { app.emit_all("single-instance", Payload { args: argv, cwd }).unwrap(); })) - .on_window_event(|event| process_window_event(&event)) + .on_window_event(|event| { + // Get the trust state from the app handle + let app_handle = event.window().app_handle(); + let trust_state = app_handle.state::(); + process_window_event(&event, &trust_state); + }) .invoke_handler(tauri::generate_handler![ get_mac_deep_link_requests, get_process_id, toggle_devtools, console_log, console_error, _get_commandline_args, get_current_working_dir, _get_window_labels, - store_credential, get_credential_otp, delete_credential, + store_credential, get_credential, delete_credential, put_item, get_item, get_all_items, delete_item, + trust_window_aes_key, remove_trust_window_aes_key, _get_windows_drives, _rename_path, show_in_folder, move_to_trash, zoom_window, _get_clipboard_files, _open_url_in_browser_win]) .setup(|app| { From d3401555330befaa170a0fb2a9261649e12cfe26 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 10 Jun 2025 13:51:39 +0530 Subject: [PATCH 692/864] chore: if there is no stored credential, return null instead of throwing --- src-tauri/src/main.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 6b1452e1..7e090fb1 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -422,8 +422,9 @@ fn delete_credential(scope_name: String) -> Result<(), String> { } // Gets the stored credential, encrypts it with the window's AES key, and returns the encrypted value +// Returns None if no credential is found #[tauri::command] -fn get_credential(window: tauri::Window, scope_name: String, trust_state: State<'_, WindowAesTrust>) -> Result { +fn get_credential(window: tauri::Window, scope_name: String, trust_state: State<'_, WindowAesTrust>) -> Result, String> { let window_label = window.label().to_string(); // Check if AES trust is established for this window @@ -443,7 +444,7 @@ fn get_credential(window: tauri::Window, scope_name: String, trust_state: State< let stored_credential = match entry.get_password() { Ok(data) => data, - Err(keyring::Error::NoEntry) => return Err("No credential found for the specified scope.".to_string()), + Err(keyring::Error::NoEntry) => return Ok(None), // Return None if no credential found Err(e) => return Err(format!("Failed to retrieve credential: {}", e.to_string())), }; @@ -471,8 +472,8 @@ fn get_credential(window: tauri::Window, scope_name: String, trust_state: State< let encrypted_data = cipher.encrypt(nonce, stored_credential.as_bytes()) .map_err(|_| "Failed to encrypt credential".to_string())?; - // Return the encrypted data as a hex string - Ok(hex::encode(encrypted_data)) + // Return the encrypted data as a hex string wrapped in Some + Ok(Some(hex::encode(encrypted_data))) } fn main() { From 4aeb6898b5f0e00d854052bdd66dd54d3c9eed43 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 18 Jun 2025 15:51:31 +0000 Subject: [PATCH 693/864] ci: update phcode version to 4.1.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index bc3dffa6..4f144293 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "4.1.0", + "version": "4.1.1", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "ae4a1230a171f885d3112f8cedc1343f429bef02" + "commit": "a24e0b5d37a989818c2d37560fa31038556a8e17" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 618a5458..c6ac1445 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "4.1.0" +version = "4.1.1" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 9d0c1303..ec8ed338 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "4.1.0" + "version": "4.1.1" }, "tauri": { "allowlist": { From a2ab568ff39a7ed73cd5c168c079ae5bbe46cb7c Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 3 Sep 2025 01:59:23 +0530 Subject: [PATCH 694/864] feat: adding suppor for debian 13 --- docs/linux/installer.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 965f0fb5..9bb52355 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -124,7 +124,6 @@ TMP_DIR=$(mktemp -d) # - This function assumes that the /etc/os-release file follows the standard format for Linux OS # identification and that the distribution's identifiers are consistent with those specified in the script. - check_os_version() { if [ -f /etc/os-release ]; then . /etc/os-release @@ -142,7 +141,9 @@ check_os_version() { neon:24) # KDE Neon 24.x return 0 ;; - + debian:13) # Debian 13.x (Trixie) + return 0 + ;; kali:2024|kali:20[2-9][0-9]) # Kali 2024.x or newer return 0 ;; From ccf88d21cfe90d1b55240e9263d0762143967a3b Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 4 Oct 2025 17:26:32 +0530 Subject: [PATCH 695/864] chore: extension take down urls --- docs/extension_takedown.json | 1 + docs/readme.md | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 docs/extension_takedown.json diff --git a/docs/extension_takedown.json b/docs/extension_takedown.json new file mode 100644 index 00000000..fe51488c --- /dev/null +++ b/docs/extension_takedown.json @@ -0,0 +1 @@ +[] diff --git a/docs/readme.md b/docs/readme.md index 202cc41d..a25f222e 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -2,4 +2,6 @@ This folder hosts static website for `updates.phcode.io` which generally sends update notifications to all installed phcode builds. * `install.json` file in this folder is used by website `phcode.io` to set download button. This is auto updated - when a new release is published or edited. \ No newline at end of file + when a new release is published or edited. +* `extension_takedown.json` file is an array of extension ids that can to be taken down from the app due to + security issue(ie malicious extension)/TOS violation. From f16e8307912d82c9e789c8fe09aa7ea16bd280aa Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 18 Oct 2025 18:21:03 +0530 Subject: [PATCH 696/864] chore: we no loger rely on site notifications json in phcode.io --- docs/siteNotifications/en.json | 41 ---------------------------------- 1 file changed, 41 deletions(-) delete mode 100644 docs/siteNotifications/en.json diff --git a/docs/siteNotifications/en.json b/docs/siteNotifications/en.json deleted file mode 100644 index 5fb3985d..00000000 --- a/docs/siteNotifications/en.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "all": {}, - "mac": {}, - "linux": {}, - "win": {}, - "android": {}, - "ios": {}, - "schema": { - "titleHTML": "an html text to show as title", - "messageHTML": "an html text to show error message", - "severity": "critical | warning | info", - "type": "1 | 2 | 3 - a number, not string, different styles of the message", - "dismissable": "true | false - boolean, not string" - }, - "features": [ - { - "title": "Live Preview", - "subtitle": "See your HTML and CSS code changes instantly, without page reloads! Use powerful UI tools like the colour editor to tweak background and text colours, adjust font sizes and border-radius with number dials, or explore page layouts with live code hints. Read more...", - "titleIconSrc": "assets/images/preview_o.png", - "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/live_preview.mp4" - }, - { - "title": "Code Intelligence for the Web", - "subtitle": "Write HTML, CSS, and JavaScript faster with on-the-fly code completion and catch errors before they become problems. We're always adding better smarts to our code intelligence, making Phoenix Code sharper with every release. Read more...", - "titleIconSrc": "assets/images/intelligence.png", - "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/error_detect.mp4" - }, - { - "title": "Lightning-Fast Search", - "subtitle": "Find exactly what you need across your entire project with Instant search. We've fine-tuned the UX to help you pinpoint your query faster: search within specific file types, exclude files and folders, or use regular expressions for complex queries. Read more...", - "titleIconSrc": "assets/images/flash.gif", - "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/find_in_files.mp4" - }, - { - "title": "Git Simplified", - "subtitle": "Integrated Git source control with a clean, intuitive interface. Stage changes, commit, and sync with a single click while keeping your focus on the code. Read more...", - "titleIconSrc": "assets/images/git_branch_feature.svg", - "videoSrc": "https://docs-images.phcode.dev/videos/phcode.io-site/git_video.mp4" - } - ] -} \ No newline at end of file From 314780735f33e64bf6079ad404e3ecfe3117dbde Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 23 Oct 2025 16:08:47 +0530 Subject: [PATCH 697/864] docs: add readme for how to use surveys.json --- docs/surveys-readme.md | 53 ++++++++++++++++++++++++++++++++++++++++++ docs/surveys.json | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 docs/surveys-readme.md diff --git a/docs/surveys-readme.md b/docs/surveys-readme.md new file mode 100644 index 00000000..29ca13f0 --- /dev/null +++ b/docs/surveys-readme.md @@ -0,0 +1,53 @@ +# Survey Configuration + +Configuration file for user surveys displayed in Phoenix Code. + +## Survey Types + +- **newUser**: Survey shown once to new users after initial delay +- **powerUser**: Recurring survey shown to active users at regular intervals + +## Configuration Properties + +| Property | Type | Default | Description | +|----------|------|---------|----------------------------------------------------------------------------------| +| `newUser` | string | - | URL for new user survey | +| `powerUser` | string | - | URL for power user survey | +| `newUserTitle` | string/null | null | Custom title for new user survey (null uses translated default) | +| `powerUserTitle` | string/null | null | Custom title for power user survey (null uses translated default) | +| `newUserShowDelayMS` | number | 1200000 | Delay before showing new user survey (20 minutes) | +| `powerUserShowIntervalDays` | number | 35 | Days between power user surveys | +| `newUserUseDialog` | boolean | false | Display mode: `true` = dialog, `false` = notification | +| `powerUserUseDialog` | boolean | false | Display mode: `true` = dialog, `false` = notification | +| `browser` | object | - | Browser app will use this if present, else it will default to the above version | + +## Platform-Specific Configuration + +Use the `browser` object to override settings for browser deployments. All properties from the main config can be overridden. + +## Example + +```json +{ + "newUser": "https://s.surveyplanet.com/jssqbld8", + "newUserTitle": null, + "newUserUseDialog": false, + "newUserShowDelayMS": 1200000, + "powerUser": "https://s.surveyplanet.com/v3j59a7z", + "powerUserTitle": null, + "powerUserUseDialog": false, + "powerUserShowIntervalDays": 35, + "browser": { + "newUser": "https://s.surveyplanet.com/5lrpp9ud", + "powerUser": "https://s.surveyplanet.com/wtohpj8x", + "newUserShowDelayMS": 600000, + "powerUserShowIntervalDays": 30 + } +} +``` + +## Behavior + +- **New User Survey**: Shown once per user. Version number in code determines if shown again after updates. +- **Power User Survey**: First shown 14 days after initial boot, then repeats at configured interval. +- **Fallback**: If browser-specific config exists, native app uses main config, browser uses browser config with fallback to main. diff --git a/docs/surveys.json b/docs/surveys.json index 127e131e..6f50e5b1 100644 --- a/docs/surveys.json +++ b/docs/surveys.json @@ -9,4 +9,4 @@ "newUserShowDelayMS": 1200000, "powerUserShowIntervalDays": 35 } -} \ No newline at end of file +} From 1380036971d97309c840790957ff3d650a9ce5e4 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 23 Oct 2025 18:58:37 +0530 Subject: [PATCH 698/864] docs: new power user survey fields pxplanation powerUserLoggedIn powerUserPaid --- docs/surveys-readme.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/surveys-readme.md b/docs/surveys-readme.md index 29ca13f0..f7beb486 100644 --- a/docs/surveys-readme.md +++ b/docs/surveys-readme.md @@ -6,13 +6,17 @@ Configuration file for user surveys displayed in Phoenix Code. - **newUser**: Survey shown once to new users after initial delay - **powerUser**: Recurring survey shown to active users at regular intervals + - **powerUserLoggedIn**: Optional survey URL for logged-in users (fallback to `powerUser` if not given) + - **powerUserPaid**: Optional survey URL for paid subscribers (takes precedence over `powerUserLoggedIn`) ## Configuration Properties | Property | Type | Default | Description | |----------|------|---------|----------------------------------------------------------------------------------| | `newUser` | string | - | URL for new user survey | -| `powerUser` | string | - | URL for power user survey | +| `powerUser` | string | - | URL for power user survey (fallback for all users) | +| `powerUserLoggedIn` | string/null | null | URL for logged-in users (overrides `powerUser`) | +| `powerUserPaid` | string/null | null | URL for paid subscribers (overrides `powerUserLoggedIn`) | | `newUserTitle` | string/null | null | Custom title for new user survey (null uses translated default) | | `powerUserTitle` | string/null | null | Custom title for power user survey (null uses translated default) | | `newUserShowDelayMS` | number | 1200000 | Delay before showing new user survey (20 minutes) | @@ -34,12 +38,16 @@ Use the `browser` object to override settings for browser deployments. All prope "newUserUseDialog": false, "newUserShowDelayMS": 1200000, "powerUser": "https://s.surveyplanet.com/v3j59a7z", + "powerUserLoggedIn": "https://s.surveyplanet.com/abc123", + "powerUserPaid": "https://s.surveyplanet.com/xyz789", "powerUserTitle": null, "powerUserUseDialog": false, "powerUserShowIntervalDays": 35, "browser": { "newUser": "https://s.surveyplanet.com/5lrpp9ud", "powerUser": "https://s.surveyplanet.com/wtohpj8x", + "powerUserLoggedIn": "https://s.surveyplanet.com/def456", + "powerUserPaid": "https://s.surveyplanet.com/uvw321", "newUserShowDelayMS": 600000, "powerUserShowIntervalDays": 30 } @@ -50,4 +58,5 @@ Use the `browser` object to override settings for browser deployments. All prope - **New User Survey**: Shown once per user. Version number in code determines if shown again after updates. - **Power User Survey**: First shown 14 days after initial boot, then repeats at configured interval. + - Survey URL selection priority: `powerUserPaid` (if paid subscriber) → `powerUserLoggedIn` (if logged in) → `powerUser` (fallback) - **Fallback**: If browser-specific config exists, native app uses main config, browser uses browser config with fallback to main. From da453046be4ea2a2fa97b7a05089dc70677d349b Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Sat, 8 Nov 2025 14:38:25 +0530 Subject: [PATCH 699/864] fix: catch os not working --- docs/linux/installer.sh | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 9bb52355..87f8b54e 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -127,6 +127,8 @@ TMP_DIR=$(mktemp -d) check_os_version() { if [ -f /etc/os-release ]; then . /etc/os-release + # Set VERSION_ID to empty string if not defined (for rolling releases) + VERSION_ID="${VERSION_ID:-}" # Define supported OS and version combinations case "$ID:${VERSION_ID%%.*}" in # Extract major version number ubuntu:24) # Ubuntu 24.x @@ -275,9 +277,11 @@ install_dependencies() { yes | sudo dnf upgrade webkit2gtk3 gtk3 \ gstreamer1 gstreamer1-plugins-base gstreamer1-plugins-good ;; - arch|manjaro) + arch|manjaro|cachyos) echo "Detected an Arch Linux based distribution." - yes | sudo pacman -S webkit2gtk gtk3 + echo "Updating package database..." + sudo pacman -Sy + yes | sudo pacman -S webkit2gtk gtk3 libxml2 ;; *) echo "Unsupported distribution. Please manually install the required dependencies." @@ -495,6 +499,26 @@ verify_and_install_dependencies() { set_default_application() { local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file + # Dynamically detect qtpaths if KDE is running and qtpaths is not in PATH + if [ "${KDE_SESSION_VERSION:-0}" -gt 0 ] && ! command -v qtpaths &> /dev/null; then + # Common locations where qtpaths might be installed + local qtpaths_locations=( + "/usr/lib/qt6/bin" + "/usr/lib/qt5/bin" + "/usr/lib64/qt6/bin" + "/usr/lib64/qt5/bin" + "/opt/qt6/bin" + "/opt/qt5/bin" + ) + + for qtpath_dir in "${qtpaths_locations[@]}"; do + if [ -x "$qtpath_dir/qtpaths" ] || [ -x "$qtpath_dir/qtpaths6" ]; then + export PATH="$qtpath_dir:$PATH" + break + fi + done + fi + for mime_type in "${MIME_TYPES[@]}"; do # Skip setting default application for text/html if [ "$mime_type" = "text/html" ]; then From 5d023c7cfdc9d795ed057a7c8d60db6dc33b54f1 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 17 Dec 2025 19:05:21 +0530 Subject: [PATCH 700/864] chore: remove ai coming soon notification --- docs/appNotifications/prod/de/banner.json | 6 ------ docs/appNotifications/prod/fr/banner.json | 6 ------ docs/appNotifications/prod/it/banner.json | 6 ------ docs/appNotifications/prod/ja/banner.json | 6 ------ docs/appNotifications/prod/ko/banner.json | 6 ------ docs/appNotifications/prod/pt-BR/banner.json | 6 ------ docs/appNotifications/prod/root/banner.json | 6 ------ docs/appNotifications/staging/root/banner.json | 8 +------- 8 files changed, 1 insertion(+), 49 deletions(-) diff --git a/docs/appNotifications/prod/de/banner.json b/docs/appNotifications/prod/de/banner.json index a277553d..5b881470 100644 --- a/docs/appNotifications/prod/de/banner.json +++ b/docs/appNotifications/prod/de/banner.json @@ -4,11 +4,5 @@ "HTML_CONTENT": "
Wir stellen vor Phoenix Code Desktop-Apps für Windows, Mac und Linux. Klicken Sie hier, um es jetzt zu erhalten!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" - }, - "DISABLE_AI_FOR_EDUCATION_NOTICE": { - "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Achtung Schulen: Phoenix Code AI

Phoenix Code AI wird ab dem 20. Mai 2025 eingeführt. Bildungseinrichtungen sollten diese Anleitung befolgen, um AI campusweit vor diesem Datum zu deaktivieren/konfigurieren.

" - "FOR_VERSIONS": ">=3.0.0", - "PLATFORM": "all" } } diff --git a/docs/appNotifications/prod/fr/banner.json b/docs/appNotifications/prod/fr/banner.json index 7f81b04e..02bc291b 100644 --- a/docs/appNotifications/prod/fr/banner.json +++ b/docs/appNotifications/prod/fr/banner.json @@ -4,11 +4,5 @@ "HTML_CONTENT": "
Présentation des applications de bureau de Phoenix Code pour Windows, Mac et Linux. Cliquez ici pour l'obtenir maintenant !
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" - }, - "DISABLE_AI_FOR_EDUCATION_NOTICE": { - "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Attention écoles : Phoenix Code AI

Phoenix Code AI sera déployé après le 20 mai 2025. Les établissements scolaires doivent suivre ce guide pour désactiver/configurer l'IA à l'échelle du campus avant cette date.

", - "FOR_VERSIONS": ">=3.0.0", - "PLATFORM": "all" } } diff --git a/docs/appNotifications/prod/it/banner.json b/docs/appNotifications/prod/it/banner.json index d2a19727..3df5cd36 100644 --- a/docs/appNotifications/prod/it/banner.json +++ b/docs/appNotifications/prod/it/banner.json @@ -4,11 +4,5 @@ "HTML_CONTENT": "
Presentazione delle app desktop di Phoenix Code per Windows, Mac e Linux. Fai clic qui per ottenerlo ora!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" - }, - "DISABLE_AI_FOR_EDUCATION_NOTICE": { - "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Attenzione scuole: Phoenix Code AI

Phoenix Code AI sarà distribuito dopo il 20 maggio 2025. Gli istituti scolastici devono seguire questa guida per disattivare/configurare l'AI in tutto il campus prima di questa data.

", - "FOR_VERSIONS": ">=3.0.0", - "PLATFORM": "all" } } diff --git a/docs/appNotifications/prod/ja/banner.json b/docs/appNotifications/prod/ja/banner.json index d83c9f9c..ac401425 100644 --- a/docs/appNotifications/prod/ja/banner.json +++ b/docs/appNotifications/prod/ja/banner.json @@ -4,11 +4,5 @@ "HTML_CONTENT": "
Windows、Mac、Linux 用の Phoenix Code のデスクトップ アプリを紹介します。 ここをクリックして今すぐ入手してください。
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" - }, - "DISABLE_AI_FOR_EDUCATION_NOTICE": { - "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
学校向け通知: Phoenix Code AI

Phoenix Code AIは2025年5月20日以降に展開されます。教育機関はこの日までにこちらのガイドに従って、AIを無効化または構成してください。

", - "FOR_VERSIONS": ">=3.0.0", - "PLATFORM": "all" } } diff --git a/docs/appNotifications/prod/ko/banner.json b/docs/appNotifications/prod/ko/banner.json index 2e558e54..2b37f804 100644 --- a/docs/appNotifications/prod/ko/banner.json +++ b/docs/appNotifications/prod/ko/banner.json @@ -4,11 +4,5 @@ "HTML_CONTENT": "
Windows, Mac 및 Linux용 소개 Phoenix Code 데스크톱 앱. 지금 다운로드하려면 여기를 클릭하세요!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" - }, - "DISABLE_AI_FOR_EDUCATION_NOTICE": { - "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
학교 주의사항: Phoenix Code AI

Phoenix Code AI는 2025년 5월 20일 이후 출시됩니다. 교육기관은 이 날짜 전에 이 가이드를 따라 AI를 비활성화하거나 설정해야 합니다.

", - "FOR_VERSIONS": ">=3.0.0", - "PLATFORM": "all" } } diff --git a/docs/appNotifications/prod/pt-BR/banner.json b/docs/appNotifications/prod/pt-BR/banner.json index 21c574c5..674888d4 100644 --- a/docs/appNotifications/prod/pt-BR/banner.json +++ b/docs/appNotifications/prod/pt-BR/banner.json @@ -4,11 +4,5 @@ "HTML_CONTENT": "
Apresentamos os aplicativos de desktop Phoenix Code para Windows, Mac e Linux. Clique aqui para obtê-lo agora!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" - }, - "DISABLE_AI_FOR_EDUCATION_NOTICE": { - "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Atenção escolas: Phoenix Code AI

O Phoenix Code AI será lançado após 20 de maio de 2025. As instituições educacionais devem seguir este guia para desativar/configurar a IA em todo o campus antes dessa data.

", - "FOR_VERSIONS": ">=3.0.0", - "PLATFORM": "all" } } diff --git a/docs/appNotifications/prod/root/banner.json b/docs/appNotifications/prod/root/banner.json index 64136041..19c29552 100644 --- a/docs/appNotifications/prod/root/banner.json +++ b/docs/appNotifications/prod/root/banner.json @@ -4,11 +4,5 @@ "HTML_CONTENT": "
Introducing Phoenix Code Desktop Apps for Windows, Mac & Linux. Click here to get it now!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" - }, - "DISABLE_AI_FOR_EDUCATION_NOTICE": { - "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Attention schools: Phoenix Code AI

Phoenix Code AI will be rolled out after May 20, 2025. Educational institutions should follow this guide to disable/configure AI campus-wide before this date.

", - "FOR_VERSIONS": ">=3.0.0", - "PLATFORM": "all" } } diff --git a/docs/appNotifications/staging/root/banner.json b/docs/appNotifications/staging/root/banner.json index 4688b4da..dec52ecb 100644 --- a/docs/appNotifications/staging/root/banner.json +++ b/docs/appNotifications/staging/root/banner.json @@ -4,11 +4,5 @@ "HTML_CONTENT": "
Welcome to Phoenix Code dev community! Click here to chat with our Discord Community.
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "all" - }, - "DESKTOP_APP_BANNER": { - "DANGER_SHOW_ON_EVERY_BOOT" : false, - "HTML_CONTENT": "
Introducing Phoenix Code Desktop Apps for Windows, Mac & Linux. Click here to get it now!
", - "FOR_VERSIONS": ">=3.0.0", - "PLATFORM" : "allBrowser" } -} \ No newline at end of file +} From f225b2b30e367dc6088ef3e7a957342bf807e5ef Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 18 Dec 2025 08:13:22 +0530 Subject: [PATCH 701/864] ci: pro build creds in github actions --- .github/workflows/desktop-linux-test-pull.yml | 4 ++++ .github/workflows/desktop-mac-m1-test-pull.yml | 4 ++++ .github/workflows/desktop-mac-test-pull.yml | 4 ++++ .github/workflows/desktop-windows-test-pull.yml | 4 ++++ .github/workflows/prod-desktop-tests-on-pull.yml | 14 ++++++++++++++ .../workflows/staging-desktop-tests-on-pull.yml | 16 ++++++++++++++++ .github/workflows/tauri-build-dev.yml | 10 ++++++++++ .github/workflows/tauri-build-prod.yml | 14 ++++++++++++++ .github/workflows/tauri-build-staging.yml | 12 ++++++++++++ 9 files changed, 82 insertions(+) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index 0b7c0d0a..0cd9d29c 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -37,6 +37,8 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -48,6 +50,8 @@ jobs: - name: build test runner env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/desktop-mac-m1-test-pull.yml b/.github/workflows/desktop-mac-m1-test-pull.yml index 25348a69..cbf7ee76 100644 --- a/.github/workflows/desktop-mac-m1-test-pull.yml +++ b/.github/workflows/desktop-mac-m1-test-pull.yml @@ -32,6 +32,8 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -43,6 +45,8 @@ jobs: - name: build test runner env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 6513fac3..38c95e9e 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -30,6 +30,8 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -41,6 +43,8 @@ jobs: - name: build test runner env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index d712521f..fc641988 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -30,6 +30,8 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -41,6 +43,8 @@ jobs: - name: build test runner env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index e90c0a8c..568dae62 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -35,6 +35,8 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -44,6 +46,10 @@ jobs: npm run release:prod - name: build test runner + env: + GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug @@ -105,6 +111,8 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -116,6 +124,8 @@ jobs: - name: build test runner env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug @@ -177,6 +187,8 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -188,6 +200,8 @@ jobs: - name: build test runner env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index ee1f4b10..69f77a55 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -35,6 +35,8 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -46,6 +48,8 @@ jobs: - name: build test runner env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug @@ -100,6 +104,8 @@ jobs: - name: Download phoenix and build build phoenix dist-test env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -109,6 +115,10 @@ jobs: npm run release:staging - name: build test runner + env: + GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug @@ -161,6 +171,10 @@ jobs: run: npm ci - name: Download phoenix and build build phoenix dist-test + env: + GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm run _ci-clonePhoenixForTests cd .. @@ -172,6 +186,8 @@ jobs: - name: build test runner env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run releaseDistTestDebug diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 5233e1be..2218e3c9 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -55,6 +55,8 @@ jobs: - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run _ci-cloneAndBuildPhoenix @@ -105,6 +107,8 @@ jobs: - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run _ci-release:dev @@ -225,6 +229,8 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true @@ -259,6 +265,8 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin @@ -302,6 +310,8 @@ jobs: - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run _ci-release:dev diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 349f8ae3..9e8a95b9 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -55,6 +55,8 @@ jobs: - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run _ci-cloneAndBuildPhoenix @@ -105,6 +107,8 @@ jobs: - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run _ci-release:prod @@ -229,6 +233,8 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true @@ -250,6 +256,8 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true @@ -270,6 +278,8 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true @@ -304,6 +314,8 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin @@ -346,6 +358,8 @@ jobs: - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run _ci-release:prod diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index e08c58bc..862e14c3 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -55,6 +55,8 @@ jobs: - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run _ci-cloneAndBuildPhoenix @@ -103,6 +105,10 @@ jobs: with: toolchain: 1.85.1 - name: install frontend dependencies + env: + GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run _ci-release:staging @@ -223,6 +229,8 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} with: releaseId: ${{ needs.create-release.outputs.release_id }} updaterJsonPreferNsis: true @@ -257,6 +265,8 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} with: releaseId: ${{ needs.create-release.outputs.release_id }} args: --target aarch64-apple-darwin @@ -299,6 +309,8 @@ jobs: - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} + PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} + PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} run: | npm ci npm run _ci-release:staging From 7ab26317558b2dd9c0e6eeb1be7261a3724b064d Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 18 Dec 2025 08:21:59 +0530 Subject: [PATCH 702/864] ci: move all github action runners to macos 15 as mac 13 is depecated in actions --- .github/workflows/desktop-mac-m1-test-pull.yml | 2 +- .github/workflows/desktop-mac-test-pull.yml | 2 +- .github/workflows/prod-desktop-tests-on-pull.yml | 2 +- .../workflows/staging-desktop-tests-on-pull.yml | 2 +- .github/workflows/tauri-build-dev.yml | 16 ++++++++-------- .github/workflows/tauri-build-prod.yml | 16 ++++++++-------- .github/workflows/tauri-build-staging.yml | 16 ++++++++-------- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/desktop-mac-m1-test-pull.yml b/.github/workflows/desktop-mac-m1-test-pull.yml index cbf7ee76..7d77ed13 100644 --- a/.github/workflows/desktop-mac-m1-test-pull.yml +++ b/.github/workflows/desktop-mac-m1-test-pull.yml @@ -9,7 +9,7 @@ concurrency: jobs: test-desktop-mac-m1: - runs-on: macos-14 + runs-on: macos-15 timeout-minutes: 90 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 38c95e9e..340c6cef 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -9,7 +9,7 @@ concurrency: jobs: test-desktop-mac: - runs-on: macos-13 + runs-on: macos-15-intel timeout-minutes: 90 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index 568dae62..3cdefaf0 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -90,7 +90,7 @@ jobs: command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q testDesktopMac: - runs-on: macos-latest + runs-on: macos-15 timeout-minutes: 90 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index 69f77a55..5cd743b3 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -83,7 +83,7 @@ jobs: command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q testDesktopMac: - runs-on: macos-latest + runs-on: macos-15 timeout-minutes: 90 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 2218e3c9..d9a1e48b 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -43,7 +43,7 @@ jobs: permissions: contents: write timeout-minutes: 15 - runs-on: macos-14 + runs-on: macos-15 steps: - uses: actions/checkout@v4 - name: macos hardware info @@ -80,7 +80,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-13, windows-latest ] + platform: [ macos-15-intel, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -94,7 +94,7 @@ jobs: node-version: 20 - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' uses: actions/download-artifact@v4 with: name: src-node-darwin-arm64.tar.gz @@ -114,7 +114,7 @@ jobs: npm run _ci-release:dev - name: setup src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' run: | ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node @@ -167,7 +167,7 @@ jobs: Set-Content -Path "./secrets.json" -Value $content shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -237,7 +237,7 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: inject src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' run: | ls src-node rm -rf src-tauri/src-node @@ -247,12 +247,12 @@ jobs: - name: setup env for mac arm (Mac only) env: GH_TOKEN: ${{ github.token }} - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 9e8a95b9..0ee9c993 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -43,7 +43,7 @@ jobs: permissions: contents: write timeout-minutes: 15 - runs-on: macos-14 + runs-on: macos-15 steps: - uses: actions/checkout@v4 - name: macos hardware info @@ -80,7 +80,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-13, windows-latest ] + platform: [ macos-15-intel, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -94,7 +94,7 @@ jobs: node-version: 20 - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' uses: actions/download-artifact@v4 with: name: src-node-darwin-arm64.tar.gz @@ -114,7 +114,7 @@ jobs: npm run _ci-release:prod - name: setup src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' run: | ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node @@ -168,7 +168,7 @@ jobs: shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -286,7 +286,7 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: inject src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' run: | ls src-node rm -rf src-tauri/src-node @@ -296,12 +296,12 @@ jobs: - name: setup env for mac arm (Mac only) env: GH_TOKEN: ${{ github.token }} - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 862e14c3..ad7aff0c 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -43,7 +43,7 @@ jobs: permissions: contents: write timeout-minutes: 15 - runs-on: macos-14 + runs-on: macos-15 steps: - uses: actions/checkout@v4 - name: macos hardware info @@ -80,7 +80,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ macos-13, windows-latest ] + platform: [ macos-15-intel, windows-latest ] runs-on: ${{ matrix.platform }} steps: @@ -94,7 +94,7 @@ jobs: node-version: 20 - name: Download src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' uses: actions/download-artifact@v4 with: name: src-node-darwin-arm64.tar.gz @@ -114,7 +114,7 @@ jobs: npm run _ci-release:staging - name: setup src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' run: | ls /tmp/src-node-darwin-arm64.tar.gz rm -rf src-node @@ -167,7 +167,7 @@ jobs: Set-Content -Path "./secrets.json" -Value $content shell: powershell - name: Sign embedded executables for (Mac Only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' env : APPLE_KEY_IDENTITY_NAME: ${{ secrets.APPLE_KEY_IDENTITY_NAME }} APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} @@ -237,7 +237,7 @@ jobs: tagName: ${{ env.GIT_TAG_NAME }} - name: inject src-node built on mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' run: | ls src-node rm -rf src-tauri/src-node @@ -247,12 +247,12 @@ jobs: - name: setup env for mac arm (Mac only) env: GH_TOKEN: ${{ github.token }} - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' run: | rustup target add aarch64-apple-darwin npm run installNodeArmDarwin - name: build for mac arm (Mac only) - if: matrix.platform == 'macos-13' + if: matrix.platform == 'macos-15-intel' uses: tauri-apps/tauri-action@v0 env: GITHUB_TOKEN: ${{ github.token }} From ff88ffaaf75f913546f9bb4851d7578cb332eabf Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 18 Dec 2025 12:19:58 +0530 Subject: [PATCH 703/864] ci: run tests even after failure of one sute for other suites to complete --- .github/workflows/desktop-linux-test-pull.yml | 32 ++++++++++ .../workflows/desktop-mac-m1-test-pull.yml | 32 ++++++++++ .github/workflows/desktop-mac-test-pull.yml | 32 ++++++++++ .../workflows/prod-desktop-tests-on-pull.yml | 64 +++++++++++++++++++ .../staging-desktop-tests-on-pull.yml | 54 ++++++++++++++++ 5 files changed, 214 insertions(+) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index 0cd9d29c..dad96d70 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -58,6 +58,8 @@ jobs: - name: Run tauri unit tests uses: nick-fields/retry@v3 + id: linuxRunUnit + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -65,6 +67,8 @@ jobs: - name: Run tauri integration tests uses: nick-fields/retry@v3 + id: linuxRunIntegration + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -72,6 +76,8 @@ jobs: - name: Run tauri mainview tests uses: nick-fields/retry@v3 + id: linuxRunMainview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -79,6 +85,8 @@ jobs: - name: Run tauri livepreview tests uses: nick-fields/retry@v3 + id: linuxRunLivepreview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -86,7 +94,31 @@ jobs: - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v3 + id: linuxRunLegacyInteg + continue-on-error: true with: timeout_minutes: 20 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + + - name: Fail on test runs failed in Linux + if: steps.linuxRunUnit.outcome == 'failure' || steps.linuxRunIntegration.outcome == 'failure' || steps.linuxRunMainview.outcome == 'failure' || steps.linuxRunLivepreview.outcome == 'failure' || steps.linuxRunLegacyInteg.outcome == 'failure' + run: | + echo "Linux tests failed, marking step as failed" + echo "Failed tests:" + if [ "${{ steps.linuxRunUnit.outcome }}" == "failure" ]; then + echo "- Run tauri unit tests" + fi + if [ "${{ steps.linuxRunIntegration.outcome }}" == "failure" ]; then + echo "- Run tauri integration tests" + fi + if [ "${{ steps.linuxRunMainview.outcome }}" == "failure" ]; then + echo "- Run tauri mainview tests" + fi + if [ "${{ steps.linuxRunLivepreview.outcome }}" == "failure" ]; then + echo "- Run tauri livepreview tests" + fi + if [ "${{ steps.linuxRunLegacyInteg.outcome }}" == "failure" ]; then + echo "- Run tauri LegacyInteg tests" + fi + exit 1 diff --git a/.github/workflows/desktop-mac-m1-test-pull.yml b/.github/workflows/desktop-mac-m1-test-pull.yml index 7d77ed13..e24527be 100644 --- a/.github/workflows/desktop-mac-m1-test-pull.yml +++ b/.github/workflows/desktop-mac-m1-test-pull.yml @@ -53,6 +53,8 @@ jobs: - name: Run tauri unit tests uses: nick-fields/retry@v3 + id: macM1RunUnit + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -60,6 +62,8 @@ jobs: - name: Run tauri integration tests uses: nick-fields/retry@v3 + id: macM1RunIntegration + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -67,6 +71,8 @@ jobs: - name: Run tauri mainview tests uses: nick-fields/retry@v3 + id: macM1RunMainview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -74,6 +80,8 @@ jobs: - name: Run tauri livepreview tests uses: nick-fields/retry@v3 + id: macM1RunLivepreview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -81,7 +89,31 @@ jobs: - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v3 + id: macM1RunLegacyInteg + continue-on-error: true with: timeout_minutes: 30 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + + - name: Fail on test runs failed in Mac M1 + if: steps.macM1RunUnit.outcome == 'failure' || steps.macM1RunIntegration.outcome == 'failure' || steps.macM1RunMainview.outcome == 'failure' || steps.macM1RunLivepreview.outcome == 'failure' || steps.macM1RunLegacyInteg.outcome == 'failure' + run: | + echo "Mac M1 tests failed, marking step as failed" + echo "Failed tests:" + if [ "${{ steps.macM1RunUnit.outcome }}" == "failure" ]; then + echo "- Run tauri unit tests" + fi + if [ "${{ steps.macM1RunIntegration.outcome }}" == "failure" ]; then + echo "- Run tauri integration tests" + fi + if [ "${{ steps.macM1RunMainview.outcome }}" == "failure" ]; then + echo "- Run tauri mainview tests" + fi + if [ "${{ steps.macM1RunLivepreview.outcome }}" == "failure" ]; then + echo "- Run tauri livepreview tests" + fi + if [ "${{ steps.macM1RunLegacyInteg.outcome }}" == "failure" ]; then + echo "- Run tauri LegacyInteg tests" + fi + exit 1 diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 340c6cef..4cbbe2ff 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -51,6 +51,8 @@ jobs: - name: Run tauri unit tests uses: nick-fields/retry@v3 + id: macRunUnit + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -58,6 +60,8 @@ jobs: - name: Run tauri integration tests uses: nick-fields/retry@v3 + id: macRunIntegration + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -65,6 +69,8 @@ jobs: - name: Run tauri mainview tests uses: nick-fields/retry@v3 + id: macRunMainview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -72,6 +78,8 @@ jobs: - name: Run tauri livepreview tests uses: nick-fields/retry@v3 + id: macRunLivepreview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -79,7 +87,31 @@ jobs: - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v3 + id: macRunLegacyInteg + continue-on-error: true with: timeout_minutes: 30 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + + - name: Fail on test runs failed in Mac + if: steps.macRunUnit.outcome == 'failure' || steps.macRunIntegration.outcome == 'failure' || steps.macRunMainview.outcome == 'failure' || steps.macRunLivepreview.outcome == 'failure' || steps.macRunLegacyInteg.outcome == 'failure' + run: | + echo "Mac tests failed, marking step as failed" + echo "Failed tests:" + if [ "${{ steps.macRunUnit.outcome }}" == "failure" ]; then + echo "- Run tauri unit tests" + fi + if [ "${{ steps.macRunIntegration.outcome }}" == "failure" ]; then + echo "- Run tauri integration tests" + fi + if [ "${{ steps.macRunMainview.outcome }}" == "failure" ]; then + echo "- Run tauri mainview tests" + fi + if [ "${{ steps.macRunLivepreview.outcome }}" == "failure" ]; then + echo "- Run tauri livepreview tests" + fi + if [ "${{ steps.macRunLegacyInteg.outcome }}" == "failure" ]; then + echo "- Run tauri LegacyInteg tests" + fi + exit 1 diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index 3cdefaf0..d36b3a76 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -56,6 +56,8 @@ jobs: - name: Run tauri unit tests uses: nick-fields/retry@v3 + id: linuxRunUnit + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -63,6 +65,8 @@ jobs: - name: Run tauri integration tests uses: nick-fields/retry@v3 + id: linuxRunIntegration + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -70,6 +74,8 @@ jobs: - name: Run tauri mainview tests uses: nick-fields/retry@v3 + id: linuxRunMainview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -77,6 +83,8 @@ jobs: - name: Run tauri livepreview tests uses: nick-fields/retry@v3 + id: linuxRunLivepreview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -84,11 +92,35 @@ jobs: - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v3 + id: linuxRunLegacyInteg + continue-on-error: true with: timeout_minutes: 20 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + - name: Fail on test runs failed in Linux (prod) + if: steps.linuxRunUnit.outcome == 'failure' || steps.linuxRunIntegration.outcome == 'failure' || steps.linuxRunMainview.outcome == 'failure' || steps.linuxRunLivepreview.outcome == 'failure' || steps.linuxRunLegacyInteg.outcome == 'failure' + run: | + echo "Linux (prod) tests failed, marking step as failed" + echo "Failed tests:" + if [ "${{ steps.linuxRunUnit.outcome }}" == "failure" ]; then + echo "- Run tauri unit tests" + fi + if [ "${{ steps.linuxRunIntegration.outcome }}" == "failure" ]; then + echo "- Run tauri integration tests" + fi + if [ "${{ steps.linuxRunMainview.outcome }}" == "failure" ]; then + echo "- Run tauri mainview tests" + fi + if [ "${{ steps.linuxRunLivepreview.outcome }}" == "failure" ]; then + echo "- Run tauri livepreview tests" + fi + if [ "${{ steps.linuxRunLegacyInteg.outcome }}" == "failure" ]; then + echo "- Run tauri LegacyInteg tests" + fi + exit 1 + testDesktopMac: runs-on: macos-15 timeout-minutes: 90 @@ -132,6 +164,8 @@ jobs: - name: Run tauri unit tests uses: nick-fields/retry@v3 + id: macRunUnit + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -139,6 +173,8 @@ jobs: - name: Run tauri integration tests uses: nick-fields/retry@v3 + id: macRunIntegration + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -146,6 +182,8 @@ jobs: - name: Run tauri mainview tests uses: nick-fields/retry@v3 + id: macRunMainview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -153,6 +191,8 @@ jobs: - name: Run tauri livepreview tests uses: nick-fields/retry@v3 + id: macRunLivepreview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -160,11 +200,35 @@ jobs: - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v3 + id: macRunLegacyInteg + continue-on-error: true with: timeout_minutes: 30 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + - name: Fail on test runs failed in Mac (prod) + if: steps.macRunUnit.outcome == 'failure' || steps.macRunIntegration.outcome == 'failure' || steps.macRunMainview.outcome == 'failure' || steps.macRunLivepreview.outcome == 'failure' || steps.macRunLegacyInteg.outcome == 'failure' + run: | + echo "Mac (prod) tests failed, marking step as failed" + echo "Failed tests:" + if [ "${{ steps.macRunUnit.outcome }}" == "failure" ]; then + echo "- Run tauri unit tests" + fi + if [ "${{ steps.macRunIntegration.outcome }}" == "failure" ]; then + echo "- Run tauri integration tests" + fi + if [ "${{ steps.macRunMainview.outcome }}" == "failure" ]; then + echo "- Run tauri mainview tests" + fi + if [ "${{ steps.macRunLivepreview.outcome }}" == "failure" ]; then + echo "- Run tauri livepreview tests" + fi + if [ "${{ steps.macRunLegacyInteg.outcome }}" == "failure" ]; then + echo "- Run tauri LegacyInteg tests" + fi + exit 1 + testDesktopWindows: runs-on: windows-latest timeout-minutes: 90 diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index 5cd743b3..5089812f 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -56,6 +56,8 @@ jobs: - name: Run tauri unit tests uses: nick-fields/retry@v3 + id: linuxRunUnit + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -63,6 +65,8 @@ jobs: - name: Run tauri integration tests uses: nick-fields/retry@v3 + id: linuxRunIntegration + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -70,6 +74,8 @@ jobs: - name: Run tauri mainview tests uses: nick-fields/retry@v3 + id: linuxRunMainview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -77,11 +83,32 @@ jobs: - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v3 + id: linuxRunLegacyInteg + continue-on-error: true with: timeout_minutes: 20 max_attempts: 3 command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + - name: Fail on test runs failed in Linux (staging) + if: steps.linuxRunUnit.outcome == 'failure' || steps.linuxRunIntegration.outcome == 'failure' || steps.linuxRunMainview.outcome == 'failure' || steps.linuxRunLegacyInteg.outcome == 'failure' + run: | + echo "Linux (staging) tests failed, marking step as failed" + echo "Failed tests:" + if [ "${{ steps.linuxRunUnit.outcome }}" == "failure" ]; then + echo "- Run tauri unit tests" + fi + if [ "${{ steps.linuxRunIntegration.outcome }}" == "failure" ]; then + echo "- Run tauri integration tests" + fi + if [ "${{ steps.linuxRunMainview.outcome }}" == "failure" ]; then + echo "- Run tauri mainview tests" + fi + if [ "${{ steps.linuxRunLegacyInteg.outcome }}" == "failure" ]; then + echo "- Run tauri LegacyInteg tests" + fi + exit 1 + testDesktopMac: runs-on: macos-15 timeout-minutes: 90 @@ -125,6 +152,8 @@ jobs: - name: Run tauri unit tests uses: nick-fields/retry@v3 + id: macRunUnit + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -132,6 +161,8 @@ jobs: - name: Run tauri integration tests uses: nick-fields/retry@v3 + id: macRunIntegration + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -139,6 +170,8 @@ jobs: - name: Run tauri mainview tests uses: nick-fields/retry@v3 + id: macRunMainview + continue-on-error: true with: timeout_minutes: 12 max_attempts: 3 @@ -146,11 +179,32 @@ jobs: - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v3 + id: macRunLegacyInteg + continue-on-error: true with: timeout_minutes: 30 max_attempts: 3 command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + - name: Fail on test runs failed in Mac (staging) + if: steps.macRunUnit.outcome == 'failure' || steps.macRunIntegration.outcome == 'failure' || steps.macRunMainview.outcome == 'failure' || steps.macRunLegacyInteg.outcome == 'failure' + run: | + echo "Mac (staging) tests failed, marking step as failed" + echo "Failed tests:" + if [ "${{ steps.macRunUnit.outcome }}" == "failure" ]; then + echo "- Run tauri unit tests" + fi + if [ "${{ steps.macRunIntegration.outcome }}" == "failure" ]; then + echo "- Run tauri integration tests" + fi + if [ "${{ steps.macRunMainview.outcome }}" == "failure" ]; then + echo "- Run tauri mainview tests" + fi + if [ "${{ steps.macRunLegacyInteg.outcome }}" == "failure" ]; then + echo "- Run tauri LegacyInteg tests" + fi + exit 1 + testDesktopWindows: runs-on: windows-latest timeout-minutes: 90 From b47d4f65b9464c119bd1b7c7c608647a2bd477d4 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Dec 2025 12:40:48 +0530 Subject: [PATCH 704/864] docs: update banner notification docs --- docs/appNotifications/readme.md | 52 ++------------------------------- 1 file changed, 3 insertions(+), 49 deletions(-) diff --git a/docs/appNotifications/readme.md b/docs/appNotifications/readme.md index 99feb09e..5d82acea 100644 --- a/docs/appNotifications/readme.md +++ b/docs/appNotifications/readme.md @@ -25,6 +25,7 @@ A sample json is as follows: { "SAMPLE_NOTIFICATION_NAME": { "DANGER_SHOW_ON_EVERY_BOOT" : false, + "PRO_EDITION_ONLY" : false, "HTML_CONTENT": "", "FOR_VERSIONS": "1.x || >=2.5.0 || 5.0.0 - 7.2.3", "PLATFORM" : "allDesktop" @@ -37,6 +38,8 @@ A sample json is as follows: or there is an html element with class `notification_ack`. 1. `SAMPLE_NOTIFICATION_NAME` : This is a unique ID. It is used to check if the notification was shown to user. +2. `PRO_EDITION_ONLY` : (Default false) Setting this to true will not show the notification on community editions. + Only works in versions > 5.0.0 - so combine it with that is must! 2. `DANGER_SHOW_ON_EVERY_BOOT` : (Default false) Setting this to true will cause the notification to be shown on every boot. This is bad ux and only be used if there is a critical security issue that we want the version not to be used. @@ -48,52 +51,3 @@ A sample json is as follows: The notification will be shown to all versions satisfying this. 5. `PLATFORM`: A comma seperated list(no spaces) of all platforms in which the message will be shown. allowed values are: `mac,win,linux,allDesktop,firefox,chrome,safari,allBrowser,all` - - -## toast notifications - `toast.json` - -Toast notifications are shown at the side on the general notification area. Multiple toast notifications -can be shown at the same time. Format is similar to banner notification. - -By default, a notification is shown only once and auto close after 25 seconds. -If there is an html element with class `notification_ack` it must be clicked to be dismissed, -else it will come up after every boot till it is acknowledged or the close button clicked. - -### Format of `/root/toast.json` - -> - -`` can be `staging` or `prod`. (`dev` stage is directly in phoenix codebase for ease of development.) - -A sample json is as follows: -```json -{ - "SAMPLE_NOTIFICATION_NAME": { - "TRIGGER" : "MENU_CLICK:file.newFolder,HTML_ELEMENT:#project-files-container", - "TYPE": "ERROR/WARN/INFO/SUCCESS", - "HTML_CONTENT": "", - "FOR_VERSIONS": "1.x || >=2.5.0 || 5.0.0 - 7.2.3", - "PLATFORM" : "allDesktop", - "autoCloseTimeS": 25 - }, - "ANOTHER_SAMPLE_NOTIFICATION_NAME": {...} -} -``` - -1. `SAMPLE_NOTIFICATION_NAME` : This is a unique ID. It is used to check if the notification was shown to user. -2. `TRIGGER` : The trigger to show the notification. Can be a comma seperated list of one of the following - `APP_START/MENU_CLICK:/KEYBOARD_SHORTCUT:/OTHER:/HTML_ELEMENT:<.class/#id>` - 1. `APP_START` : notification will be shown on app start. - 2. `MENU_CLICK:` : When a command is executed by clicking on a ui menu item. - 3. `KEYBOARD_SHORTCUT:` : When a command is executed by keyboard shortcut. - 4. `HTML_ELEMENT:` : On click on the given html element with jquery selector. -3. `TYPE` : Can be one of `ERROR/WARN/INFO/SUCCESS`. -4. `HTML_CONTENT`: The actual html content to show to the user. It can have an optional `notification_ack` class. - Setting this class in any child html node will cause the notification to be shown once a day until the user explicitly clicks - on any html element with class `notification_ack` or explicitly click the close button. - If such a class is not present, then the notification is shown only once ever. -4. `FOR_VERSIONS` : [Semver compatible version filter](https://www.npmjs.com/package/semver). - The notification will be shown to all versions satisfying this. -5. `PLATFORM`: A comma seperated list(no spaces) of all platforms in which the message will be shown. - allowed values are: `mac,win,linux,allDesktop,firefox,chrome,safari,allBrowser,all` -6. `autoCloseTimeS`: Time to auto close the popup in seconds \ No newline at end of file From 2f4e5abb369bb1226e26f7e639a3cbffc95589de Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Dec 2025 13:30:58 +0530 Subject: [PATCH 705/864] refactor: remove unused toast.json --- docs/appNotifications/prod/de/toast.json | 2 -- docs/appNotifications/prod/fr/toast.json | 2 -- docs/appNotifications/prod/it/toast.json | 2 -- docs/appNotifications/prod/ja/toast.json | 2 -- docs/appNotifications/prod/ko/toast.json | 2 -- docs/appNotifications/prod/pt-BR/toast.json | 2 -- docs/appNotifications/prod/root/toast.json | 2 -- docs/appNotifications/staging/root/toast.json | 2 -- 8 files changed, 16 deletions(-) delete mode 100644 docs/appNotifications/prod/de/toast.json delete mode 100644 docs/appNotifications/prod/fr/toast.json delete mode 100644 docs/appNotifications/prod/it/toast.json delete mode 100644 docs/appNotifications/prod/ja/toast.json delete mode 100644 docs/appNotifications/prod/ko/toast.json delete mode 100644 docs/appNotifications/prod/pt-BR/toast.json delete mode 100644 docs/appNotifications/prod/root/toast.json delete mode 100644 docs/appNotifications/staging/root/toast.json diff --git a/docs/appNotifications/prod/de/toast.json b/docs/appNotifications/prod/de/toast.json deleted file mode 100644 index 7a73a41b..00000000 --- a/docs/appNotifications/prod/de/toast.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/docs/appNotifications/prod/fr/toast.json b/docs/appNotifications/prod/fr/toast.json deleted file mode 100644 index 7a73a41b..00000000 --- a/docs/appNotifications/prod/fr/toast.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/docs/appNotifications/prod/it/toast.json b/docs/appNotifications/prod/it/toast.json deleted file mode 100644 index 7a73a41b..00000000 --- a/docs/appNotifications/prod/it/toast.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/docs/appNotifications/prod/ja/toast.json b/docs/appNotifications/prod/ja/toast.json deleted file mode 100644 index 7a73a41b..00000000 --- a/docs/appNotifications/prod/ja/toast.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/docs/appNotifications/prod/ko/toast.json b/docs/appNotifications/prod/ko/toast.json deleted file mode 100644 index 7a73a41b..00000000 --- a/docs/appNotifications/prod/ko/toast.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/docs/appNotifications/prod/pt-BR/toast.json b/docs/appNotifications/prod/pt-BR/toast.json deleted file mode 100644 index 7a73a41b..00000000 --- a/docs/appNotifications/prod/pt-BR/toast.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/docs/appNotifications/prod/root/toast.json b/docs/appNotifications/prod/root/toast.json deleted file mode 100644 index 7a73a41b..00000000 --- a/docs/appNotifications/prod/root/toast.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/docs/appNotifications/staging/root/toast.json b/docs/appNotifications/staging/root/toast.json deleted file mode 100644 index 7a73a41b..00000000 --- a/docs/appNotifications/staging/root/toast.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file From 53ee271650585754bf777162a610fb7cfd2e323a Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Dec 2025 17:00:43 +0530 Subject: [PATCH 706/864] chore: update notificatiojn docs --- docs/appNotifications/readme.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/appNotifications/readme.md b/docs/appNotifications/readme.md index 5d82acea..fb01c29b 100644 --- a/docs/appNotifications/readme.md +++ b/docs/appNotifications/readme.md @@ -25,10 +25,10 @@ A sample json is as follows: { "SAMPLE_NOTIFICATION_NAME": { "DANGER_SHOW_ON_EVERY_BOOT" : false, - "PRO_EDITION_ONLY" : false, "HTML_CONTENT": "", "FOR_VERSIONS": "1.x || >=2.5.0 || 5.0.0 - 7.2.3", - "PLATFORM" : "allDesktop" + "PLATFORM" : "allDesktop", + "USER_TYPE" : "all" }, "ANOTHER_SAMPLE_NOTIFICATION_NAME": {...} } @@ -38,8 +38,6 @@ A sample json is as follows: or there is an html element with class `notification_ack`. 1. `SAMPLE_NOTIFICATION_NAME` : This is a unique ID. It is used to check if the notification was shown to user. -2. `PRO_EDITION_ONLY` : (Default false) Setting this to true will not show the notification on community editions. - Only works in versions > 5.0.0 - so combine it with that is must! 2. `DANGER_SHOW_ON_EVERY_BOOT` : (Default false) Setting this to true will cause the notification to be shown on every boot. This is bad ux and only be used if there is a critical security issue that we want the version not to be used. @@ -51,3 +49,6 @@ A sample json is as follows: The notification will be shown to all versions satisfying this. 5. `PLATFORM`: A comma seperated list(no spaces) of all platforms in which the message will be shown. allowed values are: `mac,win,linux,allDesktop,firefox,chrome,safari,allBrowser,all` +6. `USER_TYPE`: A comma seperated list(no spaces) of all user types in which the message will be shown. + allowed values are: [`all`, `notLoggedIn`, `loggedIn`, `trial`, `paidSubscriber`]. This filter is only available + in versions > 5, else it is ignored in older versions. combine with `FOR_VERSIONS` to filter based on user type. From 54fb12dcc84ebfc52a1dd48f07559c1992ca4a48 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 29 Dec 2025 17:04:08 +0530 Subject: [PATCH 707/864] chore: update notificatiojn docs --- docs/appNotifications/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/appNotifications/readme.md b/docs/appNotifications/readme.md index fb01c29b..7d22285f 100644 --- a/docs/appNotifications/readme.md +++ b/docs/appNotifications/readme.md @@ -28,7 +28,7 @@ A sample json is as follows: "HTML_CONTENT": "", "FOR_VERSIONS": "1.x || >=2.5.0 || 5.0.0 - 7.2.3", "PLATFORM" : "allDesktop", - "USER_TYPE" : "all" + "USER_TYPE" : ["paidSubscriber", "loggedIn"] }, "ANOTHER_SAMPLE_NOTIFICATION_NAME": {...} } @@ -49,6 +49,6 @@ A sample json is as follows: The notification will be shown to all versions satisfying this. 5. `PLATFORM`: A comma seperated list(no spaces) of all platforms in which the message will be shown. allowed values are: `mac,win,linux,allDesktop,firefox,chrome,safari,allBrowser,all` -6. `USER_TYPE`: A comma seperated list(no spaces) of all user types in which the message will be shown. +6. `USER_TYPE`: An array of all user types in which the message will be shown. allowed values are: [`all`, `notLoggedIn`, `loggedIn`, `trial`, `paidSubscriber`]. This filter is only available in versions > 5, else it is ignored in older versions. combine with `FOR_VERSIONS` to filter based on user type. From 5a7998329b48094f103de4b112d5f6d50a58d9b6 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 1 Jan 2026 16:39:37 +0530 Subject: [PATCH 708/864] chore: phoenix license agreement --- src-tauri/Cargo.lock | 2 +- src-tauri/license/phoenix-eula | 546 ++++++++++++++++++++++++++++++ src-tauri/license/phoenix-eula.md | 453 +++++++++++++++++++++++++ src-tauri/tauri.conf.json | 6 +- 4 files changed, 1003 insertions(+), 4 deletions(-) create mode 100644 src-tauri/license/phoenix-eula create mode 100644 src-tauri/license/phoenix-eula.md diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 548ab58f..948d6931 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3407,7 +3407,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "4.1.0" +version = "4.1.1" dependencies = [ "aes-gcm", "backtrace", diff --git a/src-tauri/license/phoenix-eula b/src-tauri/license/phoenix-eula new file mode 100644 index 00000000..f17e659d --- /dev/null +++ b/src-tauri/license/phoenix-eula @@ -0,0 +1,546 @@ +PHOENIX CODE USER AGREEMENT +Effective Date: 1-Jan-2026 + +Thank you for choosing Phoenix Code! + +This is a license agreement between you and CORE.AI Scientific +Technologies Private Limited (the "Company", "we", "us") that governs +your use of Phoenix Code (the "Product"), unless other terms accompany +the Product. + +---------------------------------------------------------------------- +THIS IS A LEGAL AGREEMENT +---------------------------------------------------------------------- + +By clicking "I Agree", or by downloading, installing, accessing, or +using the Product, you confirm that you have the legal capacity to +enter into this Agreement and that you agree to be bound by its terms. + +If you do not agree, do not install or use the Product. + +---------------------------------------------------------------------- +PLAIN-ENGLISH SUMMARY (NON-BINDING) +---------------------------------------------------------------------- + +This summary is provided for convenience only. The full legal terms +below control. + +- You always own your own code and content. +- We do not use your code, files, or content to train AI models unless + you explicitly grant permission. +- Phoenix Code includes free Community features and paid Pro features + in the same application distribution. +- You can use Community Edition features without payment. +- Pro features require an active Phoenix Pro plan (trial or paid plan). +- When Pro access ends, the app automatically switches back to + Community Edition. +- Your files and data are not deleted when this happens. +- Phoenix Code can send anonymous usage statistics and error reports + ("Health Reports"). You can opt out in Help > Health Report, and view + a preview of what would be sent. +- Some features depend on online services (ours or third parties). + Those services may change, be limited, or be discontinued over time. +- If you purchase a Lifetime Plan, you can keep using eligible + on-device Pro features perpetually, but updates and service-backed + features may only be included through the Lifetime Update Period + stated at purchase. + +---------------------------------------------------------------------- +1. OVERVIEW AND SCOPE +---------------------------------------------------------------------- + +This Agreement governs your installation and use of the Product, +including: + +- Desktop applications +- Web-based applications +- Installers and binaries +- Updates, upgrades, patches, and related services (including online + services) + +The Product may include both Community Edition (free) features and Pro +Edition (paid) features within the same application. + +Your ability to use certain features depends on whether you have an +active Phoenix Pro Plan or other entitlement. + +---------------------------------------------------------------------- +2. DEFINITIONS +---------------------------------------------------------------------- + +- Product: Phoenix Code, including desktop applications, web-based + applications, installers, updates, and related services +- Installer: The installation package distributed by the Company +- Documentation: Official Phoenix Code documentation and materials +- Community Edition: Functionality made available at no charge +- Pro Edition: Paid, commercial functionality of Phoenix Code +- Phoenix Pro Plan: Any Company-authorized plan that grants access to + Pro Edition features, including trials or paid plans +- Lifetime Plan: A one-time paid plan that grants long-term access to + certain Pro Edition features, subject to Section 4.4 +- Lifetime Update Period: The specific update/service access period + stated at purchase for a Lifetime Plan +- Online Services: Services operated by the Company or third parties + that support some features (for example hosted libraries, cloud + features, account services, licensing/activation, AI services) +- Third-Party Software: Software or services provided by third parties, + governed by separate terms +- AI Features: Features that use artificial intelligence services + (Company-operated or third-party) +- Your Content: Your code, files, text, prompts, inputs, projects, and + other content you create or provide +- Health Reports: Anonymous usage statistics and error/diagnostic + reports sent by the Product to improve stability, usability, and + prioritization (Section 9) + +---------------------------------------------------------------------- +3. LICENSE STRUCTURE AND EDITIONS +---------------------------------------------------------------------- + +3.1 Unified Application License + +The Installer and distributed application binary are licensed under +this Agreement. + +This Agreement governs use of: + +- Phoenix Code as distributed by the Company +- Both Community Edition and Pro Edition functionality contained within + the same application + +Feature availability depends on your plan/entitlements. + +3.2 Community Edition and Open-Source Components + +Certain components may be made available under open-source licenses +(including the GNU Affero General Public License (AGPL)) when the +Company separately distributes specific source code under those +licenses. + +Open-source components are governed solely by the applicable open-source +license. + +This Agreement does not replace or override applicable open-source +licenses for source code expressly released under them. + +The compiled binaries and Installer provided by the Company are not +distributed under AGPL. + +3.3 Pro Edition (Commercial) + +Pro Edition features are proprietary and licensed under this Agreement +only. + +- Pro Edition is not open source +- Open-source licenses do not apply to Pro Edition features unless + explicitly stated + +---------------------------------------------------------------------- +4. PRO ACCESS, TRIALS, LIFETIME PLANS, AND DOWNGRADES +---------------------------------------------------------------------- + +4.1 Pro Access + +Access to Pro Edition features requires an active Phoenix Pro Plan or +other entitlement. + +The scope, duration, eligibility, and limits of Pro access are +determined by the Company and described at purchase, in-app, or in +Documentation. + +4.2 Automatic Downgrade + +If your Phoenix Pro Plan expires, is cancelled, or otherwise ends, the +Product automatically reverts to Community Edition functionality. No +additional notice is required. + +4.3 No Data Deletion + +Downgrading does not delete Your Content. Some Pro features and related +data formats/outputs may become unavailable or restricted. + +4.4 Lifetime Plan Terms + +A Lifetime Plan grants long-term access to eligible Pro Edition features +that run entirely on your device, subject to this Agreement and your +compliance with it. + +Lifetime does not mean we must provide updates, support, or Online +Services forever. + +1. Perpetual use of eligible on-device features: + You may continue using the last Pro-enabled version you are entitled + to indefinitely for eligible on-device Pro features. + +2. Updates and service-backed features limited by Lifetime Update Period: + Your entitlement to updates, upgrades, support, and any Pro features + that rely on Online Services may be limited to the Lifetime Update + Period stated at purchase. + +3. Online Services may change: + Online Services (including hosted libraries, cloud features, + licensing, AI, or other service-backed features) may be modified, + limited, or discontinued as described in Section 6. + +4. Feature classification reference: + The Company may publish which Pro features are on-device vs + service-backed in the Phoenix Pro feature set/Documentation. + +4.5 Activation, License Checks, and Internet Requirements + +Some Pro features (including trial, subscription, and Lifetime Plan +entitlements) may require: + +- Sign-in to your account (if applicable) +- Periodic license verification +- Internet access for activation, verification, or Online Services + +If verification cannot be completed for a period of time, Pro features +may be temporarily unavailable until verification succeeds. Community +Edition features may remain available. + +4.6 Pro Activation and Credential Sharing + +Pro Edition access is granted through a Phoenix Pro Plan entitlement +(for example via account sign-in, license key, or other activation +method described in the applicable plan terms). Unless your plan terms +expressly allow otherwise, Pro entitlements are personal to the +purchaser/authorized user, and you may not share or make Pro access +available to others (including by sharing credentials, keys, tokens, or +activated copies). + +---------------------------------------------------------------------- +5. LICENSE GRANT +---------------------------------------------------------------------- + +Subject to your compliance with this Agreement, the Company grants you a +limited, non-exclusive, non-transferable, revocable license to install +and use the Product for your internal personal or business purposes. + +Unless the Company’s plan terms specify otherwise: + +- You may install and use the Product on devices you own or control. +- You may copy and redistribute the Installer and Community Edition + freely. However, you may not share, sell, transfer, sublicense, rent, + or lease any Phoenix Pro Plan access, activation method, license key, + entitlement, or account credentials, except where your plan terms + expressly allow it or where prohibited by law. + +All rights not expressly granted are reserved by the Company. + +---------------------------------------------------------------------- +6. UPDATES, ONLINE SERVICES, AND AVAILABILITY +---------------------------------------------------------------------- + +6.1 Updates and Changes + +The Company may provide updates, upgrades, patches, or feature changes. +Some updates may be required to maintain security, compatibility, or +continued operation. + +We may add, modify, limit, or discontinue features at any time, +including Pro features and Online Services. + +6.2 Online Services + +Some features rely on Online Services operated by the Company or third +parties. The Company will use commercially reasonable efforts to operate +Online Services in a reliable manner, but Online Services may from time +to time be unavailable due to maintenance, upgrades, outages, security +issues, capacity limits, third-party service failures, or events beyond +our reasonable control. + +We may add, modify, limit, or discontinue Online Services (including +related features), and may change eligibility, limits, or access +requirements. + +For paid Phoenix Pro Plans, if we elect to discontinue an Online Service +(or a paid feature that materially depends on that Online Service), we +will use commercially reasonable efforts to provide at least thirty (30) +days’ advance notice where reasonably practicable. We may discontinue or +suspend Online Services immediately (or with shorter notice) if required +by law, to address security, fraud, or abuse, or to prevent material +harm to the Company, users, or third parties. + +If an Online Service is discontinued, you may still be able to use +Product features that do not depend on that Online Service. Mandatory +consumer rights remain unaffected. + +---------------------------------------------------------------------- +7. RESTRICTIONS +---------------------------------------------------------------------- + +You may not: + +- Reverse engineer, decompile, or disassemble Pro Edition features, + except to the extent such restriction is prohibited by applicable law +- Circumvent, disable, or interfere with licensing, payments, feature + controls, usage limits, or security mechanisms +- Provide access to Pro Edition features to third parties as a hosted + service, time-share, service bureau, or similar arrangement unless + expressly authorized +- Use the Product to develop or offer a product or service that + substantially replicates Phoenix Code’s Pro Edition core functionality +- Remove or alter proprietary notices, trademarks, or license notices + included in the Product + +---------------------------------------------------------------------- +8. YOUR CONTENT AND OWNERSHIP +---------------------------------------------------------------------- + +8.1 You Own Your Content + +You retain ownership of Your Content. The Company does not claim +ownership of your code, files, or projects. + +8.2 Access to Your Content + +To provide Product features (including sync, collaboration, AI Features, +or Online Services), the Product may process or transmit Your Content as +needed to perform the requested function. + +---------------------------------------------------------------------- +9. PRIVACY, HEALTH REPORTS, AND AI DATA USE +---------------------------------------------------------------------- + +9.1 Privacy Policy + +Our privacy practices are described in the Company’s Privacy Policy: +https://phcode.io/privacy + +9.2 Health Reports (Anonymous Usage Statistics and Error Reports) + +Phoenix Code provides optional Health Reports that collect anonymous +usage statistics and error/diagnostic reports to help us prioritize +features, find bugs, and improve usability and stability. + +1. No personally identifiable information in Health Reports: + Health Reports are designed so that the Company does not collect or + process personally identifiable information through Health Reports. + +2. Install ID (random): + Health Reports may include a randomly generated Install ID created on + installation to measure anonymous counts and trends over time. The + Install ID is not derived from device hardware identifiers and is not + intended to identify you. We do not use the Install ID to directly + identify you, and it is not your account identifier. + +3. Preview and control: + You can view what would be sent and enable/disable Health Reports in + the Product (for example, Help > Health Report). + +4. Necessary anonymous health indicators: + Certain anonymous measurements may be collected as necessary app + health indicators, such as: + - security/app update status checks, + - analytics library initialization, + - anonymous user counts, and + - anonymous usage time, which are aggregate statistics and do not + include personal data. + +5. Support submissions: + If you choose to send support materials, logs, screenshots, or files, + those materials may include content you provide voluntarily and will + be used to assist you and improve the Product. + +9.3 No AI Training + +By default, the Company does not use Your Content (including code, +files, or prompts) to train AI models, unless you explicitly opt in or +otherwise grant permission in a manner that clearly indicates your +intent. + +9.4 AI Feature Processing + +If you use AI Features: + +- Your input (which may include Your Content) may be processed to + generate output. +- AI outputs may be similar or identical for other users. +- You are responsible for reviewing and verifying AI output before + relying on it. +- The Company does not claim ownership of AI-generated output produced + for you. + +If AI Features involve Third-Party Software or third-party AI services, +those providers may process data under their own terms, and details may +be described in the Privacy Policy or Documentation. + +9.5 Account and Subscription Data (Separate from Health Reports) + +If you create an account or purchase a Phoenix Pro Plan, the Company may +process account and subscription information (such as email address and +plan status) to provide authentication, billing, entitlement management, +fraud prevention, and customer support. This processing is governed by +the Privacy Policy. + +---------------------------------------------------------------------- +10. THIRD-PARTY SOFTWARE +---------------------------------------------------------------------- + +The Product may include or depend on third-party software components, +libraries, and services ("Third-Party Software") that are governed by +their own licenses or terms. Your use of Third-Party Software is subject +to those third-party licenses and terms. + +Third-Party Software license notices and attributions are provided with +the Product and/or made available at: + +- In the source repository: + https://github.com/phcode-dev/phoenix/tree/main/src/thirdparty/licences +- Within the installed Product distribution (for example, in a + "Third-Party Licenses" or similar notices location, where provided) + +If there is a conflict between this Agreement and a Third-Party Software +license regarding that Third-Party Software, the Third-Party Software +license will control for that component. Third-Party Software is +provided by its respective owners, and the Company does not make any +warranties on behalf of third-party licensors. + +---------------------------------------------------------------------- +11. DISCLAIMER OF WARRANTIES +---------------------------------------------------------------------- + +To the maximum extent permitted by law, the Product and Online Services +are provided "as is" and "as available." + +The Company disclaims all warranties, whether express, implied, or +statutory, including but not limited to warranties of merchantability, +fitness for a particular purpose, title, and non-infringement. + +We do not warrant that the Product will meet your requirements, operate +without interruption, be secure, or be error-free, or that defects will +be corrected. + +---------------------------------------------------------------------- +12. LIMITATION OF LIABILITY +---------------------------------------------------------------------- + +To the maximum extent permitted by law: + +1. The Company is not liable for any indirect, incidental, special, + consequential, or punitive damages, or for loss of profits, revenue, + data, goodwill, or business interruption, arising out of or related + to the Product or this Agreement. + +2. The Company’s total aggregate liability arising out of or relating to + this Agreement will not exceed: + - for subscription plans: the amount you paid to the Company for the + Product in the 12 months immediately before the event giving rise + to the claim, and + - for Lifetime Plans: the one-time amount paid for the Lifetime Plan, + - and for free users: no liability (except to the extent liability + cannot be excluded under applicable law), + in each case whichever is applicable. + +Some jurisdictions do not allow certain limitations, so some of the +above may not apply to you. Mandatory consumer protection laws remain +unaffected. + +---------------------------------------------------------------------- +13. TERM, TERMINATION, AND SURVIVAL +---------------------------------------------------------------------- + +13.1 Term + +This Agreement applies while you use the Product. + +13.2 Termination + +You may stop using the Product at any time. + +The Company may terminate or suspend your rights to use the Product +(including Pro features or Online Services) if you breach this +Agreement, if required for legal compliance, or if the Product is +discontinued. + +13.3 Effect of Termination + +Upon termination, you must stop using the Product. However, if you +purchased a Lifetime Plan and we terminate solely due to Product +discontinuation (not your breach), you may retain the right to use the +last entitled version for eligible on-device features, subject to +applicable law. + +13.4 Survival + +Sections that by their nature should survive termination will survive, +including Sections on ownership, privacy/AI data use (as applicable), +disclaimers, limitation of liability, governing law, and dispute +provisions. + +---------------------------------------------------------------------- +14. EXPORT AND SANCTIONS COMPLIANCE +---------------------------------------------------------------------- + +You must comply with applicable export control and sanctions laws. You +may not use or export the Product in violation of such laws. + +---------------------------------------------------------------------- +15. GOVERNING LAW, JURISDICTION, AND COMPANY INFORMATION +---------------------------------------------------------------------- + +This Agreement is governed by the laws of India, without regard to +conflict of laws principles. + +Subject to applicable consumer protection laws, the courts located in +Ernakulam, Kerala, India will have exclusive jurisdiction over disputes +arising from or relating to this Agreement. + +Mandatory consumer rights available under applicable law remain +unaffected. + +Company Information + +CORE.AI SCIENTIFIC TECHNOLOGIES PRIVATE LIMITED +(CIN: U72501KL2020PTC063362) + +Registered Office: +No. 6/858-M, 2nd Floor, Suite No. 695 Valamkottil Towers, +Judgemukku Kakkanad, Ernakulam, Kerala - 682021 India + +Contact: legal@core.ai + +---------------------------------------------------------------------- +16. CHANGES TO THIS AGREEMENT +---------------------------------------------------------------------- + +We may update this Agreement from time to time. + +Unless otherwise required by applicable law, we are not obligated to +provide notice of updates to this Agreement. However, if (a) you have a +paid Phoenix Pro Plan and a change would materially reduce your paid +entitlements during an active paid term, or (b) we make a material +change to our privacy practices, we will use commercially reasonable +efforts to provide notice through reasonable means (for example, in-app +notice, on our website, or via email associated with your account). Any +updated Agreement will apply prospectively from its effective date. + +By continuing to use the Product after the effective date of an updated +Agreement, you accept the updated terms. If you do not agree, you must +stop using the Product. + +---------------------------------------------------------------------- +17. ENTIRE AGREEMENT +---------------------------------------------------------------------- + +This Agreement constitutes the entire agreement between you and the +Company regarding the Product and supersedes all prior agreements or +understandings relating to the Product. + +If any provision of this Agreement is held unenforceable, the remaining +provisions remain in full force and effect. + +The Company’s failure to enforce any right or provision does not +constitute a waiver. + +You may not assign this Agreement without the Company’s prior written +consent. The Company may assign this Agreement as part of a merger, +acquisition, or sale of assets. + +---------------------------------------------------------------------- +REFERENCE LINKS +---------------------------------------------------------------------- + +Privacy Policy: https://phcode.io/privacy +Phoenix Pro Features: https://phcode.io/ diff --git a/src-tauri/license/phoenix-eula.md b/src-tauri/license/phoenix-eula.md new file mode 100644 index 00000000..fda05e15 --- /dev/null +++ b/src-tauri/license/phoenix-eula.md @@ -0,0 +1,453 @@ +# PHOENIX CODE USER AGREEMENT + +**Version: 1.3.1** **Effective Date: 1-Jan-2026** + +**Thank you for choosing Phoenix Code!** + +This is a license agreement between you and **CORE.AI Scientific Technologies Private Limited** (the **“Company”**, +**“we”**, **“us”**) that governs your use of **Phoenix Code** (the **“Product”**), unless other terms accompany the +Product. + +--- + +## **THIS IS A LEGAL AGREEMENT** + +By clicking **“I Agree”**, or by downloading, installing, accessing, or using the Product, you confirm that you have the +legal capacity to enter into this Agreement and that you agree to be bound by its terms. + +If you do not agree, do not install or use the Product. + +--- + +## PLAIN-ENGLISH SUMMARY (NON-BINDING) + +This summary is provided for convenience only. The full legal terms below control. + +- **You always own your own code and content.** +- We **do not use your code, files, or content to train AI models** unless you **explicitly grant permission**. +- Phoenix Code includes **free Community features** and **paid Pro features** in the same application distribution. +- You can use Community Edition features without payment. +- Pro features require an **active Phoenix Pro plan** (trial or paid plan). +- When Pro access ends, the app automatically switches back to Community Edition. +- Your files and data are **not deleted** when this happens. +- Phoenix Code can send **anonymous** usage statistics and error reports (“Health Reports”). You can **opt out** in + **Help > Health Report**, and view a preview of what would be sent. +- Some features depend on **online services** (ours or third parties). Those services may change, be limited, or be + discontinued over time. +- If you purchase a **Lifetime Plan**, you can keep using eligible on-device Pro features **perpetually**, but **updates + and service-backed features** may only be included **through the Lifetime Update Period** stated at purchase. + +--- + +## 1. OVERVIEW AND SCOPE + +This Agreement governs your installation and use of the Product, including: + +- Desktop applications +- Web-based applications +- Installers and binaries +- Updates, upgrades, patches, and related services (including online services) + +The Product may include both **Community Edition** (free) features and **Pro Edition** (paid) features within the same +application. + +Your ability to use certain features depends on whether you have an **active Phoenix Pro Plan** or other entitlement. + +--- + +## 2. DEFINITIONS + +- **Product**: Phoenix Code, including desktop applications, web-based applications, installers, updates, and related + services +- **Installer**: The installation package distributed by the Company +- **Documentation**: Official Phoenix Code documentation and materials +- **Community Edition**: Functionality made available at no charge +- **Pro Edition**: Paid, commercial functionality of Phoenix Code +- **Phoenix Pro Plan**: Any Company-authorized plan that grants access to Pro Edition features, including trials or paid + plans +- **Lifetime Plan**: A one-time paid plan that grants long-term access to certain Pro Edition features, subject to + Section 4.4 +- **Lifetime Update Period**: The specific update/service access period stated at purchase for a Lifetime Plan +- **Online Services**: Services operated by the Company or third parties that support some features (for example hosted + libraries, cloud features, account services, licensing/activation, AI services) +- **Third-Party Software**: Software or services provided by third parties, governed by separate terms +- **AI Features**: Features that use artificial intelligence services (Company-operated or third-party) +- **Your Content**: Your code, files, text, prompts, inputs, projects, and other content you create or provide +- **Health Reports**: Anonymous usage statistics and error/diagnostic reports sent by the Product to improve stability, + usability, and prioritization (Section 9) + +--- + +## 3. LICENSE STRUCTURE AND EDITIONS + +### 3.1 Unified Application License + +The Installer and distributed application binary are licensed under this Agreement. + +This Agreement governs use of: + +- Phoenix Code as distributed by the Company +- Both Community Edition and Pro Edition functionality contained within the same application + +Feature availability depends on your plan/entitlements. + +--- + +### 3.2 Community Edition and Open-Source Components + +Certain components may be made available under open-source licenses (including the **GNU Affero General Public License +(AGPL)**) when the Company separately distributes specific source code under those licenses. + +Open-source components are governed **solely** by the applicable open-source license. + +This Agreement does **not** replace or override applicable open-source licenses for source code expressly released under +them. + +The **compiled binaries and Installer** provided by the Company are **not distributed under AGPL**. + +--- + +### 3.3 Pro Edition (Commercial) + +Pro Edition features are proprietary and licensed under this Agreement only. + +- Pro Edition is not open source +- Open-source licenses do not apply to Pro Edition features unless explicitly stated + +--- + +## 4. PRO ACCESS, TRIALS, LIFETIME PLANS, AND DOWNGRADES + +### 4.1 Pro Access + +Access to Pro Edition features requires an **active Phoenix Pro Plan** or other entitlement. + +The scope, duration, eligibility, and limits of Pro access are determined by the Company and described at purchase, +in-app, or in Documentation. + +--- + +### 4.2 Automatic Downgrade + +If your Phoenix Pro Plan expires, is cancelled, or otherwise ends, the Product automatically reverts to Community +Edition functionality. No additional notice is required. + +--- + +### 4.3 No Data Deletion + +Downgrading does not delete Your Content. Some Pro features and related data formats/outputs may become unavailable or +restricted. + +--- + +### 4.4 Lifetime Plan Terms + +A **Lifetime Plan** grants long-term access to eligible Pro Edition features that run **entirely on your device**, +subject to this Agreement and your compliance with it. + +**Lifetime does not mean** we must provide updates, support, or Online Services forever. + +1. **Perpetual use of eligible on-device features:** You may continue using the last Pro-enabled version you are + entitled to **indefinitely** for eligible on-device Pro features. +2. **Updates and service-backed features limited by Lifetime Update Period:** Your entitlement to **updates, upgrades, + support, and any Pro features that rely on Online Services** may be limited to the **Lifetime Update Period** stated + at purchase. +3. **Online Services may change:** Online Services (including hosted libraries, cloud features, licensing, AI, or other + service-backed features) may be modified, limited, or discontinued as described in Section 6. +4. **Feature classification reference:** The Company may publish which Pro features are on-device vs service-backed in + the Phoenix Pro feature set/Documentation. + +--- + +### 4.5 Activation, License Checks, and Internet Requirements + +Some Pro features (including trial, subscription, and Lifetime Plan entitlements) may require: + +- Sign-in to your account (if applicable) +- Periodic license verification +- Internet access for activation, verification, or Online Services + +If verification cannot be completed for a period of time, Pro features may be temporarily unavailable until verification +succeeds. Community Edition features may remain available. + +--- + +### 4.6 Pro Activation and Credential Sharing + +Pro Edition access is granted through a Phoenix Pro Plan entitlement (for example via account sign-in, license key, or +other activation method described in the applicable plan terms). Unless your plan terms expressly allow otherwise, Pro +entitlements are personal to the purchaser/authorized user, and you may not share or make Pro access available to others +(including by sharing credentials, keys, tokens, or activated copies). + +--- + +## 5. LICENSE GRANT + +Subject to your compliance with this Agreement, the Company grants you a **limited, non-exclusive, non-transferable, +revocable** license to install and use the Product for your internal personal or business purposes. + +Unless the Company’s plan terms specify otherwise: + +- You may install and use the Product on devices you own or control. +- You may **copy and redistribute the Installer and Community Edition freely**. However, you may not share, sell, + transfer, sublicense, rent, or lease any **Phoenix Pro Plan access, activation method, license key, entitlement, or + account credentials**, except where your plan terms expressly allow it or where prohibited by law. + +All rights not expressly granted are reserved by the Company. + +--- + +## 6. UPDATES, ONLINE SERVICES, AND AVAILABILITY + +### 6.1 Updates and Changes + +The Company may provide updates, upgrades, patches, or feature changes. Some updates may be required to maintain +security, compatibility, or continued operation. + +We may add, modify, limit, or discontinue features at any time, including Pro features and Online Services. + +--- + +### 6.2 Online Services + +Some features rely on Online Services operated by the Company or third parties. The Company will use **commercially +reasonable efforts** to operate Online Services in a reliable manner, but Online Services may from time to time be +unavailable due to maintenance, upgrades, outages, security issues, capacity limits, third-party service failures, or +events beyond our reasonable control. + +We may add, modify, limit, or discontinue Online Services (including related features), and may change eligibility, +limits, or access requirements. + +**For paid Phoenix Pro Plans**, if we elect to discontinue an Online Service (or a paid feature that materially depends +on that Online Service), we will use commercially reasonable efforts to provide at least **thirty (30) days’** advance +notice where reasonably practicable. We may discontinue or suspend Online Services immediately (or with shorter notice) +if required by law, to address security, fraud, or abuse, or to prevent material harm to the Company, users, or third +parties. + +If an Online Service is discontinued, you may still be able to use Product features that do not depend on that Online +Service. Mandatory consumer rights remain unaffected. + +--- + +## 7. RESTRICTIONS + +You may not: + +- Reverse engineer, decompile, or disassemble Pro Edition features, except to the extent such restriction is prohibited + by applicable law +- Circumvent, disable, or interfere with licensing, payments, feature controls, usage limits, or security mechanisms +- Provide access to Pro Edition features to third parties as a hosted service, time-share, service bureau, or similar + arrangement unless expressly authorized +- Use the Product to develop or offer a product or service that **substantially replicates** Phoenix Code’s Pro Edition + core functionality +- Remove or alter proprietary notices, trademarks, or license notices included in the Product + +--- + +## 8. YOUR CONTENT AND OWNERSHIP + +### 8.1 You Own Your Content + +You retain ownership of Your Content. The Company does not claim ownership of your code, files, or projects. + +### 8.2 Access to Your Content + +To provide Product features (including sync, collaboration, AI Features, or Online Services), the Product may process or +transmit Your Content as needed to perform the requested function. + +--- + +## 9. PRIVACY, HEALTH REPORTS, AND AI DATA USE + +### 9.1 Privacy Policy + +Our privacy practices are described in the Company’s Privacy Policy: +**[https://phcode.io/privacy](https://phcode.io/privacy)**. + +### 9.2 Health Reports (Anonymous Usage Statistics and Error Reports) + +Phoenix Code provides optional **Health Reports** that collect **anonymous usage statistics** and **error/diagnostic +reports** to help us prioritize features, find bugs, and improve usability and stability. + +1. **No personally identifiable information in Health Reports:** Health Reports are designed so that the Company **does + not collect or process personally identifiable information** through Health Reports. +2. **Install ID (random):** Health Reports may include a **randomly generated Install ID** created on installation to + measure anonymous counts and trends over time. The Install ID is **not derived from device hardware identifiers** and + is **not intended to identify you**. **We do not use the Install ID to directly identify you, and it is not your + account identifier.** +3. **Preview and control:** You can view what would be sent and enable/disable Health Reports in the Product (for + example, **Help > Health Report**). +4. **Necessary anonymous health indicators:** Certain anonymous measurements may be collected as **necessary app health + indicators**, such as: + + - security/app update status checks, + - analytics library initialization, + - anonymous user counts, and + - anonymous usage time, which are aggregate statistics and do not include personal data. + +5. **Support submissions:** If you choose to send support materials, logs, screenshots, or files, those materials may + include content you provide voluntarily and will be used to assist you and improve the Product. + +### 9.3 No AI Training + +**By default, the Company does not use Your Content (including code, files, or prompts) to train AI models**, unless you +**explicitly opt in** or otherwise grant permission in a manner that clearly indicates your intent. + +### 9.4 AI Feature Processing + +If you use AI Features: + +- Your input (which may include Your Content) may be processed to generate output. +- AI outputs may be similar or identical for other users. +- You are responsible for reviewing and verifying AI output before relying on it. +- The Company does not claim ownership of AI-generated output produced for you. + +If AI Features involve Third-Party Software or third-party AI services, those providers may process data under their own +terms, and details may be described in the Privacy Policy or Documentation. + +### 9.5 Account and Subscription Data (Separate from Health Reports) + +If you create an account or purchase a Phoenix Pro Plan, the Company may process account and subscription information +(such as email address and plan status) to provide authentication, billing, entitlement management, fraud prevention, +and customer support. This processing is governed by the Privacy Policy. + +--- + +## 10. THIRD-PARTY SOFTWARE + +The Product may include or depend on third-party software components, libraries, and services (“Third-Party Software”) +that are governed by their own licenses or terms. Your use of Third-Party Software is subject to those third-party +licenses and terms. + +Third-Party Software license notices and attributions are provided with the Product and/or made available at: + +- In the source repository: `https://github.com/phcode-dev/phoenix/tree/main/src/thirdparty/licences` +- Within the installed Product distribution (for example, in a “Third-Party Licenses” or similar notices location, where + provided) + +If there is a conflict between this Agreement and a Third-Party Software license regarding that Third-Party Software, +the Third-Party Software license will control for that component. Third-Party Software is provided by its respective +owners, and the Company does not make any warranties on behalf of third-party licensors. + +--- + +## 11. DISCLAIMER OF WARRANTIES + +To the maximum extent permitted by law, the Product and Online Services are provided **“as is”** and **“as available.”** + +The Company disclaims all warranties, whether express, implied, or statutory, including but not limited to warranties of +merchantability, fitness for a particular purpose, title, and non-infringement. + +We do not warrant that the Product will meet your requirements, operate without interruption, be secure, or be +error-free, or that defects will be corrected. + +--- + +## 12. LIMITATION OF LIABILITY + +To the maximum extent permitted by law: + +1. The Company is not liable for any indirect, incidental, special, consequential, or punitive damages, or for loss of + profits, revenue, data, goodwill, or business interruption, arising out of or related to the Product or this + Agreement. +2. The Company’s total aggregate liability arising out of or relating to this Agreement will not exceed: + + - for subscription plans: the amount you paid to the Company for the Product in the **12 months** immediately before + the event giving rise to the claim, and + - for Lifetime Plans: the **one-time amount paid** for the Lifetime Plan, + - and for free users: **no liability (except to the extent liability cannot be excluded under applicable law)**, + + in each case **whichever is applicable**. + +Some jurisdictions do not allow certain limitations, so some of the above may not apply to you. Mandatory consumer +protection laws remain unaffected. + +--- + +## 13. TERM, TERMINATION, AND SURVIVAL + +### 13.1 Term + +This Agreement applies while you use the Product. + +### 13.2 Termination + +You may stop using the Product at any time. + +The Company may terminate or suspend your rights to use the Product (including Pro features or Online Services) if you +breach this Agreement, if required for legal compliance, or if the Product is discontinued. + +### 13.3 Effect of Termination + +Upon termination, you must stop using the Product. However, if you purchased a Lifetime Plan and we terminate solely due +to Product discontinuation (not your breach), you may retain the right to use the last entitled version for eligible +on-device features, subject to applicable law. + +### 13.4 Survival + +Sections that by their nature should survive termination will survive, including Sections on ownership, privacy/AI data +use (as applicable), disclaimers, limitation of liability, governing law, and dispute provisions. + +--- + +## 14. EXPORT AND SANCTIONS COMPLIANCE + +You must comply with applicable export control and sanctions laws. You may not use or export the Product in violation of +such laws. + +--- + +## 15. GOVERNING LAW, JURISDICTION, AND COMPANY INFORMATION + +This Agreement is governed by the laws of **India**, without regard to conflict of laws principles. + +Subject to applicable consumer protection laws, the courts located in **Ernakulam, Kerala, India** will have exclusive +jurisdiction over disputes arising from or relating to this Agreement. + +Mandatory consumer rights available under applicable law remain unaffected. + +**Company Information** + +CORE.AI SCIENTIFIC TECHNOLOGIES PRIVATE LIMITED (CIN: **U72501KL2020PTC063362**) + +Registered Office: No. 6/858-M, 2nd Floor, Suite No. 695 Valamkottil Towers, Judgemukku Kakkanad, Ernakulam, Kerala – +682021 India + +Contact: **[legal@core.ai](mailto:legal@core.ai)** + +--- + +## 16. CHANGES TO THIS AGREEMENT + +We may update this Agreement from time to time. + +Unless otherwise required by applicable law, we are not obligated to provide notice of updates to this Agreement. +However, if (a) you have a **paid Phoenix Pro Plan** and a change would **materially reduce your paid entitlements** +during an active paid term, or (b) we make a **material change to our privacy practices**, we will use commercially +reasonable efforts to provide notice through reasonable means (for example, in-app notice, on our website, or via email +associated with your account). Any updated Agreement will apply **prospectively** from its effective date. + +By continuing to use the Product after the effective date of an updated Agreement, you accept the updated terms. If you +do not agree, you must stop using the Product. + +--- + +## 17. ENTIRE AGREEMENT + +This Agreement constitutes the entire agreement between you and the Company regarding the Product and supersedes all +prior agreements or understandings relating to the Product. + +If any provision of this Agreement is held unenforceable, the remaining provisions remain in full force and effect. + +The Company’s failure to enforce any right or provision does not constitute a waiver. + +You may not assign this Agreement without the Company’s prior written consent. The Company may assign this Agreement as +part of a merger, acquisition, or sale of assets. + +--- + +## Reference Links + +* Privacy Policy: **[https://phcode.io/privacy](https://phcode.io/privacy)** +* Phoenix Pro Features: **[https://phcode.io/](https://phcode.io/)** diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ec8ed338..add01d52 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -192,7 +192,7 @@ "frameworks": [], "providerShortName": null, "signingIdentity": null, - "license": "./license/agpl" + "license": "./license/phoenix-eula" }, "resources": [ "src-node/*" @@ -210,7 +210,7 @@ "timestampUrl": "http://timestamp.globalsign.com/tsa/advanced", "nsis": { "displayLanguageSelector": true, - "license": "./license/agpl", + "license": "./license/phoenix-eula", "template": "./src/bundle/windows/nsis/installer.nsi", "languages": [ "English", @@ -484,4 +484,4 @@ } ] } -} \ No newline at end of file +} From d10b16060b19edabcbe25a3c3b9f8842e8ab4a14 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 1 Jan 2026 16:44:59 +0530 Subject: [PATCH 709/864] chore: license version --- src-tauri/license/phoenix-eula | 2 +- src-tauri/license/phoenix-eula.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-tauri/license/phoenix-eula b/src-tauri/license/phoenix-eula index f17e659d..7afa39d5 100644 --- a/src-tauri/license/phoenix-eula +++ b/src-tauri/license/phoenix-eula @@ -1,5 +1,5 @@ PHOENIX CODE USER AGREEMENT -Effective Date: 1-Jan-2026 +Effective Date: 1-Jan-2026 Version: 5 Thank you for choosing Phoenix Code! diff --git a/src-tauri/license/phoenix-eula.md b/src-tauri/license/phoenix-eula.md index fda05e15..7ff54d5c 100644 --- a/src-tauri/license/phoenix-eula.md +++ b/src-tauri/license/phoenix-eula.md @@ -1,6 +1,6 @@ # PHOENIX CODE USER AGREEMENT -**Version: 1.3.1** **Effective Date: 1-Jan-2026** +**Effective Date: 1-Jan-2026** **Version: 5** **Thank you for choosing Phoenix Code!** From 573e07426e9ae78ddc8949e9a5e435d51427f603 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 1 Jan 2026 17:00:58 +0530 Subject: [PATCH 710/864] chore: wording changes --- src-tauri/license/phoenix-eula | 25 +++++++++++++------------ src-tauri/license/phoenix-eula.md | 15 ++++++--------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src-tauri/license/phoenix-eula b/src-tauri/license/phoenix-eula index 7afa39d5..122f5d16 100644 --- a/src-tauri/license/phoenix-eula +++ b/src-tauri/license/phoenix-eula @@ -416,7 +416,9 @@ be corrected. 12. LIMITATION OF LIABILITY ---------------------------------------------------------------------- -To the maximum extent permitted by law: +We are not responsible for indirect or consequential losses, such as +lost profits, lost data, or business interruption. To the maximum +extent permitted by law: 1. The Company is not liable for any indirect, incidental, special, consequential, or punitive damages, or for loss of profits, revenue, @@ -425,17 +427,16 @@ To the maximum extent permitted by law: 2. The Company’s total aggregate liability arising out of or relating to this Agreement will not exceed: - - for subscription plans: the amount you paid to the Company for the - Product in the 12 months immediately before the event giving rise - to the claim, and - - for Lifetime Plans: the one-time amount paid for the Lifetime Plan, - - and for free users: no liability (except to the extent liability - cannot be excluded under applicable law), - in each case whichever is applicable. - -Some jurisdictions do not allow certain limitations, so some of the -above may not apply to you. Mandatory consumer protection laws remain -unaffected. + + - for paid plans: the total amount you paid to the Company for the + subscription during the most recent paid billing period or term + immediately before the event giving rise to the claim; if you paid + for an annual term in advance, this amount will be calculated on a + pro-rata basis for the portion of the annual term that elapsed + before the event giving rise to the claim, and + + - for free users: no liability (except to the extent liability cannot + be excluded under applicable law). ---------------------------------------------------------------------- 13. TERM, TERMINATION, AND SURVIVAL diff --git a/src-tauri/license/phoenix-eula.md b/src-tauri/license/phoenix-eula.md index 7ff54d5c..85363bb9 100644 --- a/src-tauri/license/phoenix-eula.md +++ b/src-tauri/license/phoenix-eula.md @@ -346,6 +346,7 @@ error-free, or that defects will be corrected. ## 12. LIMITATION OF LIABILITY +We are not responsible for indirect or consequential losses, such as lost profits, lost data, or business interruption. To the maximum extent permitted by law: 1. The Company is not liable for any indirect, incidental, special, consequential, or punitive damages, or for loss of @@ -353,15 +354,11 @@ To the maximum extent permitted by law: Agreement. 2. The Company’s total aggregate liability arising out of or relating to this Agreement will not exceed: - - for subscription plans: the amount you paid to the Company for the Product in the **12 months** immediately before - the event giving rise to the claim, and - - for Lifetime Plans: the **one-time amount paid** for the Lifetime Plan, - - and for free users: **no liability (except to the extent liability cannot be excluded under applicable law)**, - - in each case **whichever is applicable**. - -Some jurisdictions do not allow certain limitations, so some of the above may not apply to you. Mandatory consumer -protection laws remain unaffected. + - for paid plans: the total amount you paid to the Company for the subscription during the **most recent paid + billing period or term** immediately before the event giving rise to the claim; if you paid for an annual term + in advance, this amount will be **calculated on a pro-rata basis** for the portion of the annual term that + elapsed before the event giving rise to the claim, and + - for free users: **no liability (except to the extent liability cannot be excluded under applicable law)**, --- From 935aea227c2177856a7ebd8b9a4fed9e0af36e81 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 3 Jan 2026 18:36:54 +0530 Subject: [PATCH 711/864] chore: update eula and remove md file as its tracked in legal --- src-tauri/license/phoenix-eula | 357 ++++++++++++++---------- src-tauri/license/phoenix-eula.md | 450 ------------------------------ src-tauri/license/readme.md | 2 + 3 files changed, 219 insertions(+), 590 deletions(-) delete mode 100644 src-tauri/license/phoenix-eula.md create mode 100644 src-tauri/license/readme.md diff --git a/src-tauri/license/phoenix-eula b/src-tauri/license/phoenix-eula index 122f5d16..9f2d092a 100644 --- a/src-tauri/license/phoenix-eula +++ b/src-tauri/license/phoenix-eula @@ -1,26 +1,41 @@ PHOENIX CODE USER AGREEMENT -Effective Date: 1-Jan-2026 Version: 5 + +Effective Date: 1-Jan-2026 Version: 5.0 Thank you for choosing Phoenix Code! This is a license agreement between you and CORE.AI Scientific -Technologies Private Limited (the "Company", "we", "us") that governs -your use of Phoenix Code (the "Product"), unless other terms accompany +Technologies Private Limited (the “Company”, “we”, “us”) that governs +your use of Phoenix Code (the “Product”), unless other terms accompany the Product. ----------------------------------------------------------------------- +This Agreement applies only to official Phoenix Code builds distributed +by the Company (including installers, binaries, updates, and +Company-operated online services). + +If you obtain Phoenix Code source code from +https://github.com/phcode-dev/phoenix, that source code is licensed +under the GNU Affero General Public License (AGPL) and is not governed +by this Agreement except for any separate proprietary components the +Company distributes outside the AGPL repository. + +------------------------------------------------------------------------ + THIS IS A LEGAL AGREEMENT ----------------------------------------------------------------------- -By clicking "I Agree", or by downloading, installing, accessing, or -using the Product, you confirm that you have the legal capacity to -enter into this Agreement and that you agree to be bound by its terms. +------------------------------------------------------------------------ + +By clicking “I Agree”, or by downloading, installing, accessing, or +using the Product, you confirm that you have the legal capacity to enter +into this Agreement and that you agree to be bound by its terms. If you do not agree, do not install or use the Product. ----------------------------------------------------------------------- +------------------------------------------------------------------------ + PLAIN-ENGLISH SUMMARY (NON-BINDING) ----------------------------------------------------------------------- + +------------------------------------------------------------------------ This summary is provided for convenience only. The full legal terms below control. @@ -28,26 +43,28 @@ below control. - You always own your own code and content. - We do not use your code, files, or content to train AI models unless you explicitly grant permission. -- Phoenix Code includes free Community features and paid Pro features - in the same application distribution. +- Phoenix Code includes free Community features and paid Pro features in + the same application distribution. - You can use Community Edition features without payment. - Pro features require an active Phoenix Pro plan (trial or paid plan). -- When Pro access ends, the app automatically switches back to - Community Edition. +- When Pro access ends, the app automatically switches back to Community + Edition. - Your files and data are not deleted when this happens. - Phoenix Code can send anonymous usage statistics and error reports - ("Health Reports"). You can opt out in Help > Health Report, and view + (“Health Reports”). You can opt out in Help > Health Report, and view a preview of what would be sent. -- Some features depend on online services (ours or third parties). - Those services may change, be limited, or be discontinued over time. -- If you purchase a Lifetime Plan, you can keep using eligible - on-device Pro features perpetually, but updates and service-backed - features may only be included through the Lifetime Update Period - stated at purchase. - ----------------------------------------------------------------------- +- Some features depend on online services (ours or third parties). Those + services may change, be limited, or be discontinued over time. +- If you purchase a Lifetime Plan, you can keep using eligible on-device + Pro features perpetually, but updates and service-backed features may + only be included through the Lifetime Update Period stated at + purchase. + +------------------------------------------------------------------------ + 1. OVERVIEW AND SCOPE ----------------------------------------------------------------------- + +------------------------------------------------------------------------ This Agreement governs your installation and use of the Product, including: @@ -64,9 +81,18 @@ Edition (paid) features within the same application. Your ability to use certain features depends on whether you have an active Phoenix Pro Plan or other entitlement. ----------------------------------------------------------------------- +Online Services: If you use Company-operated online services (accounts, +publishing/preview, AI features, or other service-backed features), +those services may also be governed by our Terms of Service: +https://phcode.io/terms-of-service.html. If there is a conflict, the +Privacy Policy controls for privacy/data processing, the EULA controls +for the Product, and the Terms of Service control for the Services. + +------------------------------------------------------------------------ + 2. DEFINITIONS ----------------------------------------------------------------------- + +------------------------------------------------------------------------ - Product: Phoenix Code, including desktop applications, web-based applications, installers, updates, and related services @@ -93,14 +119,16 @@ active Phoenix Pro Plan or other entitlement. reports sent by the Product to improve stability, usability, and prioritization (Section 9) ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 3. LICENSE STRUCTURE AND EDITIONS ----------------------------------------------------------------------- + +------------------------------------------------------------------------ 3.1 Unified Application License -The Installer and distributed application binary are licensed under -this Agreement. +The Installer and distributed application binary are licensed under this +Agreement. This Agreement governs use of: @@ -135,18 +163,21 @@ only. - Open-source licenses do not apply to Pro Edition features unless explicitly stated ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 4. PRO ACCESS, TRIALS, LIFETIME PLANS, AND DOWNGRADES ----------------------------------------------------------------------- + +------------------------------------------------------------------------ 4.1 Pro Access Access to Pro Edition features requires an active Phoenix Pro Plan or other entitlement. -The scope, duration, eligibility, and limits of Pro access are -determined by the Company and described at purchase, in-app, or in -Documentation. +Plan details, eligibility, feature availability, and usage limits +(including any quotas or exclusions for specific plan types such as +educational plans) are described at purchase, in-product, and/or in the +Phoenix Pro Plan Terms. https://phcode.io/phoenix-pro-plan-terms.html. 4.2 Automatic Downgrade @@ -168,23 +199,20 @@ compliance with it. Lifetime does not mean we must provide updates, support, or Online Services forever. -1. Perpetual use of eligible on-device features: - You may continue using the last Pro-enabled version you are entitled - to indefinitely for eligible on-device Pro features. - -2. Updates and service-backed features limited by Lifetime Update Period: - Your entitlement to updates, upgrades, support, and any Pro features - that rely on Online Services may be limited to the Lifetime Update - Period stated at purchase. - -3. Online Services may change: - Online Services (including hosted libraries, cloud features, - licensing, AI, or other service-backed features) may be modified, - limited, or discontinued as described in Section 6. - -4. Feature classification reference: - The Company may publish which Pro features are on-device vs - service-backed in the Phoenix Pro feature set/Documentation. +1. Perpetual use of eligible on-device features: You may continue using + the last Pro-enabled version you are entitled to indefinitely for + eligible on-device Pro features. +2. Updates and service-backed features limited by Lifetime Update + Period: Your entitlement to updates, upgrades, support, and any Pro + features that rely on Online Services may be limited to the Lifetime + Update Period stated at purchase. +3. Online Services may change: Online Services (including hosted + libraries, cloud features, licensing, AI, or other service-backed + features) may be modified, limited, or discontinued as described in + Section 6. +4. Feature classification reference: The Company may publish which Pro + features are on-device vs service-backed in the Phoenix Pro feature + set/Documentation. 4.5 Activation, License Checks, and Internet Requirements @@ -209,9 +237,11 @@ purchaser/authorized user, and you may not share or make Pro access available to others (including by sharing credentials, keys, tokens, or activated copies). ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 5. LICENSE GRANT ----------------------------------------------------------------------- + +------------------------------------------------------------------------ Subject to your compliance with this Agreement, the Company grants you a limited, non-exclusive, non-transferable, revocable license to install @@ -228,9 +258,11 @@ Unless the Company’s plan terms specify otherwise: All rights not expressly granted are reserved by the Company. ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 6. UPDATES, ONLINE SERVICES, AND AVAILABILITY ----------------------------------------------------------------------- + +------------------------------------------------------------------------ 6.1 Updates and Changes @@ -266,9 +298,11 @@ If an Online Service is discontinued, you may still be able to use Product features that do not depend on that Online Service. Mandatory consumer rights remain unaffected. ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 7. RESTRICTIONS ----------------------------------------------------------------------- + +------------------------------------------------------------------------ You may not: @@ -284,9 +318,11 @@ You may not: - Remove or alter proprietary notices, trademarks, or license notices included in the Product ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 8. YOUR CONTENT AND OWNERSHIP ----------------------------------------------------------------------- + +------------------------------------------------------------------------ 8.1 You Own Your Content @@ -295,18 +331,30 @@ ownership of your code, files, or projects. 8.2 Access to Your Content +By default, we do not see or have access to Your data in the Product. + To provide Product features (including sync, collaboration, AI Features, or Online Services), the Product may process or transmit Your Content as -needed to perform the requested function. +needed to perform the function you request. + +When a feature first requires transmitting Your Content, the Product +will notify you and ask for your permission before sending any data. +After you grant permission for that feature, similar transmissions for +the same feature may occur without additional prompts to improve +usability. You can withdraw consent for future transmissions by +disabling the relevant feature or changing the applicable settings (if +available). + +------------------------------------------------------------------------ ----------------------------------------------------------------------- 9. PRIVACY, HEALTH REPORTS, AND AI DATA USE ----------------------------------------------------------------------- + +------------------------------------------------------------------------ 9.1 Privacy Policy Our privacy practices are described in the Company’s Privacy Policy: -https://phcode.io/privacy +https://phcode.io/privacy.html. 9.2 Health Reports (Anonymous Usage Statistics and Error Reports) @@ -314,34 +362,35 @@ Phoenix Code provides optional Health Reports that collect anonymous usage statistics and error/diagnostic reports to help us prioritize features, find bugs, and improve usability and stability. -1. No personally identifiable information in Health Reports: - Health Reports are designed so that the Company does not collect or - process personally identifiable information through Health Reports. - -2. Install ID (random): - Health Reports may include a randomly generated Install ID created on - installation to measure anonymous counts and trends over time. The - Install ID is not derived from device hardware identifiers and is not - intended to identify you. We do not use the Install ID to directly - identify you, and it is not your account identifier. - -3. Preview and control: - You can view what would be sent and enable/disable Health Reports in - the Product (for example, Help > Health Report). - -4. Necessary anonymous health indicators: - Certain anonymous measurements may be collected as necessary app - health indicators, such as: - - security/app update status checks, - - analytics library initialization, - - anonymous user counts, and - - anonymous usage time, which are aggregate statistics and do not - include personal data. - -5. Support submissions: - If you choose to send support materials, logs, screenshots, or files, - those materials may include content you provide voluntarily and will - be used to assist you and improve the Product. +1. No personally identifiable information in Health Reports: Health + Reports are designed so that the Company does not collect or process + personally identifiable information through Health Reports. + +2. Install ID (random): Health Reports may include a randomly generated + Install ID created on installation to measure anonymous counts and + trends over time. The Install ID is not derived from device hardware + identifiers and is not intended to identify you. We do not use the + Install ID to directly identify you, and it is not your account + identifier. + +3. Preview and control: You can view what would be sent and + enable/disable Health Reports in the Product (for example, Help > + Health Report). + +4. Necessary anonymous health indicators: Certain anonymous + measurements may be collected as necessary app health indicators, + such as: + + - security/app update status checks, + - analytics library initialization, + - anonymous user counts, and + - anonymous usage time, which are aggregate statistics and do not + include personal data. + +5. Support submissions: If you choose to send support materials, logs, + screenshots, or files, those materials may include content you + provide voluntarily and will be used to assist you and improve the + Product. 9.3 No AI Training @@ -374,12 +423,14 @@ plan status) to provide authentication, billing, entitlement management, fraud prevention, and customer support. This processing is governed by the Privacy Policy. ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 10. THIRD-PARTY SOFTWARE ----------------------------------------------------------------------- + +------------------------------------------------------------------------ The Product may include or depend on third-party software components, -libraries, and services ("Third-Party Software") that are governed by +libraries, and services (“Third-Party Software”) that are governed by their own licenses or terms. Your use of Third-Party Software is subject to those third-party licenses and terms. @@ -389,7 +440,7 @@ the Product and/or made available at: - In the source repository: https://github.com/phcode-dev/phoenix/tree/main/src/thirdparty/licences - Within the installed Product distribution (for example, in a - "Third-Party Licenses" or similar notices location, where provided) + “Third-Party Licenses” or similar notices location, where provided) If there is a conflict between this Agreement and a Third-Party Software license regarding that Third-Party Software, the Third-Party Software @@ -397,12 +448,14 @@ license will control for that component. Third-Party Software is provided by its respective owners, and the Company does not make any warranties on behalf of third-party licensors. ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 11. DISCLAIMER OF WARRANTIES ----------------------------------------------------------------------- + +------------------------------------------------------------------------ To the maximum extent permitted by law, the Product and Online Services -are provided "as is" and "as available." +are provided “as is” and “as available.” The Company disclaims all warranties, whether express, implied, or statutory, including but not limited to warranties of merchantability, @@ -412,35 +465,46 @@ We do not warrant that the Product will meet your requirements, operate without interruption, be secure, or be error-free, or that defects will be corrected. ----------------------------------------------------------------------- -12. LIMITATION OF LIABILITY ----------------------------------------------------------------------- - -We are not responsible for indirect or consequential losses, such as -lost profits, lost data, or business interruption. To the maximum -extent permitted by law: +------------------------------------------------------------------------ -1. The Company is not liable for any indirect, incidental, special, - consequential, or punitive damages, or for loss of profits, revenue, - data, goodwill, or business interruption, arising out of or related - to the Product or this Agreement. - -2. The Company’s total aggregate liability arising out of or relating to - this Agreement will not exceed: +12. LIMITATION OF LIABILITY - - for paid plans: the total amount you paid to the Company for the - subscription during the most recent paid billing period or term - immediately before the event giving rise to the claim; if you paid - for an annual term in advance, this amount will be calculated on a - pro-rata basis for the portion of the annual term that elapsed - before the event giving rise to the claim, and +------------------------------------------------------------------------ - - for free users: no liability (except to the extent liability cannot - be excluded under applicable law). +We are not responsible for indirect or consequential losses, such as +lost profits, lost data, or business interruption. To the maximum extent +permitted by law: + +1. The Company is not liable for any indirect, incidental, special, + consequential, or punitive damages, or for loss of profits, revenue, + data, goodwill, or business interruption, arising out of or related + to the Product or this Agreement. + +2. The Company’s total aggregate liability arising out of or relating + to this Agreement will not exceed: + + - for paid plans: the total amount you paid to the Company for the + subscription during the most recent paid billing period or term + immediately before the event giving rise to the claim; if you paid + for an annual term in advance, this amount will be calculated on a + pro-rata basis for the portion of the annual term that elapsed + before the event giving rise to the claim, and + - for free users: no liability (except to the extent liability + cannot be excluded under applicable law), + +3. You agree that the limits in this Section are the maximum amounts + the Company will be responsible for, and you will not seek + compensation for any loss or damage in excess of those limits. These + limitations apply even if we have been advised of the possibility of + such damages and even if any remedy fails of its essential purpose. + Nothing in this Agreement limits liability where it cannot be + limited under applicable law. + +------------------------------------------------------------------------ ----------------------------------------------------------------------- 13. TERM, TERMINATION, AND SURVIVAL ----------------------------------------------------------------------- + +------------------------------------------------------------------------ 13.1 Term @@ -470,16 +534,20 @@ including Sections on ownership, privacy/AI data use (as applicable), disclaimers, limitation of liability, governing law, and dispute provisions. ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 14. EXPORT AND SANCTIONS COMPLIANCE ----------------------------------------------------------------------- + +------------------------------------------------------------------------ You must comply with applicable export control and sanctions laws. You may not use or export the Product in violation of such laws. ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 15. GOVERNING LAW, JURISDICTION, AND COMPANY INFORMATION ----------------------------------------------------------------------- + +------------------------------------------------------------------------ This Agreement is governed by the laws of India, without regard to conflict of laws principles. @@ -493,18 +561,19 @@ unaffected. Company Information -CORE.AI SCIENTIFIC TECHNOLOGIES PRIVATE LIMITED -(CIN: U72501KL2020PTC063362) +CORE.AI SCIENTIFIC TECHNOLOGIES PRIVATE LIMITED (CIN: +U72501KL2020PTC063362) -Registered Office: -No. 6/858-M, 2nd Floor, Suite No. 695 Valamkottil Towers, -Judgemukku Kakkanad, Ernakulam, Kerala - 682021 India +Registered Office: No. 6/858-M, 2nd Floor, Suite No. 695 Valamkottil +Towers, Judgemukku Kakkanad, Ernakulam, Kerala – 682021 India Contact: legal@core.ai ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 16. CHANGES TO THIS AGREEMENT ----------------------------------------------------------------------- + +------------------------------------------------------------------------ We may update this Agreement from time to time. @@ -521,9 +590,11 @@ By continuing to use the Product after the effective date of an updated Agreement, you accept the updated terms. If you do not agree, you must stop using the Product. ----------------------------------------------------------------------- +------------------------------------------------------------------------ + 17. ENTIRE AGREEMENT ----------------------------------------------------------------------- + +------------------------------------------------------------------------ This Agreement constitutes the entire agreement between you and the Company regarding the Product and supersedes all prior agreements or @@ -539,9 +610,15 @@ You may not assign this Agreement without the Company’s prior written consent. The Company may assign this Agreement as part of a merger, acquisition, or sale of assets. ----------------------------------------------------------------------- +------------------------------------------------------------------------ + REFERENCE LINKS ----------------------------------------------------------------------- -Privacy Policy: https://phcode.io/privacy -Phoenix Pro Features: https://phcode.io/ +------------------------------------------------------------------------ + +- Terms of Service: https://phcode.io/terms-of-service.html +- Phoenix Code User Agreement (EULA): + https://phcode.io/phoenix-code-eula.html +- Privacy Policy: https://phcode.io/privacy.html +- Phoenix Pro Plan Terms: https://phcode.io/phoenix-pro-plan-terms.html +- Cancellation and Refund Policy: https://phcode.io/cancellation.html diff --git a/src-tauri/license/phoenix-eula.md b/src-tauri/license/phoenix-eula.md deleted file mode 100644 index 85363bb9..00000000 --- a/src-tauri/license/phoenix-eula.md +++ /dev/null @@ -1,450 +0,0 @@ -# PHOENIX CODE USER AGREEMENT - -**Effective Date: 1-Jan-2026** **Version: 5** - -**Thank you for choosing Phoenix Code!** - -This is a license agreement between you and **CORE.AI Scientific Technologies Private Limited** (the **“Company”**, -**“we”**, **“us”**) that governs your use of **Phoenix Code** (the **“Product”**), unless other terms accompany the -Product. - ---- - -## **THIS IS A LEGAL AGREEMENT** - -By clicking **“I Agree”**, or by downloading, installing, accessing, or using the Product, you confirm that you have the -legal capacity to enter into this Agreement and that you agree to be bound by its terms. - -If you do not agree, do not install or use the Product. - ---- - -## PLAIN-ENGLISH SUMMARY (NON-BINDING) - -This summary is provided for convenience only. The full legal terms below control. - -- **You always own your own code and content.** -- We **do not use your code, files, or content to train AI models** unless you **explicitly grant permission**. -- Phoenix Code includes **free Community features** and **paid Pro features** in the same application distribution. -- You can use Community Edition features without payment. -- Pro features require an **active Phoenix Pro plan** (trial or paid plan). -- When Pro access ends, the app automatically switches back to Community Edition. -- Your files and data are **not deleted** when this happens. -- Phoenix Code can send **anonymous** usage statistics and error reports (“Health Reports”). You can **opt out** in - **Help > Health Report**, and view a preview of what would be sent. -- Some features depend on **online services** (ours or third parties). Those services may change, be limited, or be - discontinued over time. -- If you purchase a **Lifetime Plan**, you can keep using eligible on-device Pro features **perpetually**, but **updates - and service-backed features** may only be included **through the Lifetime Update Period** stated at purchase. - ---- - -## 1. OVERVIEW AND SCOPE - -This Agreement governs your installation and use of the Product, including: - -- Desktop applications -- Web-based applications -- Installers and binaries -- Updates, upgrades, patches, and related services (including online services) - -The Product may include both **Community Edition** (free) features and **Pro Edition** (paid) features within the same -application. - -Your ability to use certain features depends on whether you have an **active Phoenix Pro Plan** or other entitlement. - ---- - -## 2. DEFINITIONS - -- **Product**: Phoenix Code, including desktop applications, web-based applications, installers, updates, and related - services -- **Installer**: The installation package distributed by the Company -- **Documentation**: Official Phoenix Code documentation and materials -- **Community Edition**: Functionality made available at no charge -- **Pro Edition**: Paid, commercial functionality of Phoenix Code -- **Phoenix Pro Plan**: Any Company-authorized plan that grants access to Pro Edition features, including trials or paid - plans -- **Lifetime Plan**: A one-time paid plan that grants long-term access to certain Pro Edition features, subject to - Section 4.4 -- **Lifetime Update Period**: The specific update/service access period stated at purchase for a Lifetime Plan -- **Online Services**: Services operated by the Company or third parties that support some features (for example hosted - libraries, cloud features, account services, licensing/activation, AI services) -- **Third-Party Software**: Software or services provided by third parties, governed by separate terms -- **AI Features**: Features that use artificial intelligence services (Company-operated or third-party) -- **Your Content**: Your code, files, text, prompts, inputs, projects, and other content you create or provide -- **Health Reports**: Anonymous usage statistics and error/diagnostic reports sent by the Product to improve stability, - usability, and prioritization (Section 9) - ---- - -## 3. LICENSE STRUCTURE AND EDITIONS - -### 3.1 Unified Application License - -The Installer and distributed application binary are licensed under this Agreement. - -This Agreement governs use of: - -- Phoenix Code as distributed by the Company -- Both Community Edition and Pro Edition functionality contained within the same application - -Feature availability depends on your plan/entitlements. - ---- - -### 3.2 Community Edition and Open-Source Components - -Certain components may be made available under open-source licenses (including the **GNU Affero General Public License -(AGPL)**) when the Company separately distributes specific source code under those licenses. - -Open-source components are governed **solely** by the applicable open-source license. - -This Agreement does **not** replace or override applicable open-source licenses for source code expressly released under -them. - -The **compiled binaries and Installer** provided by the Company are **not distributed under AGPL**. - ---- - -### 3.3 Pro Edition (Commercial) - -Pro Edition features are proprietary and licensed under this Agreement only. - -- Pro Edition is not open source -- Open-source licenses do not apply to Pro Edition features unless explicitly stated - ---- - -## 4. PRO ACCESS, TRIALS, LIFETIME PLANS, AND DOWNGRADES - -### 4.1 Pro Access - -Access to Pro Edition features requires an **active Phoenix Pro Plan** or other entitlement. - -The scope, duration, eligibility, and limits of Pro access are determined by the Company and described at purchase, -in-app, or in Documentation. - ---- - -### 4.2 Automatic Downgrade - -If your Phoenix Pro Plan expires, is cancelled, or otherwise ends, the Product automatically reverts to Community -Edition functionality. No additional notice is required. - ---- - -### 4.3 No Data Deletion - -Downgrading does not delete Your Content. Some Pro features and related data formats/outputs may become unavailable or -restricted. - ---- - -### 4.4 Lifetime Plan Terms - -A **Lifetime Plan** grants long-term access to eligible Pro Edition features that run **entirely on your device**, -subject to this Agreement and your compliance with it. - -**Lifetime does not mean** we must provide updates, support, or Online Services forever. - -1. **Perpetual use of eligible on-device features:** You may continue using the last Pro-enabled version you are - entitled to **indefinitely** for eligible on-device Pro features. -2. **Updates and service-backed features limited by Lifetime Update Period:** Your entitlement to **updates, upgrades, - support, and any Pro features that rely on Online Services** may be limited to the **Lifetime Update Period** stated - at purchase. -3. **Online Services may change:** Online Services (including hosted libraries, cloud features, licensing, AI, or other - service-backed features) may be modified, limited, or discontinued as described in Section 6. -4. **Feature classification reference:** The Company may publish which Pro features are on-device vs service-backed in - the Phoenix Pro feature set/Documentation. - ---- - -### 4.5 Activation, License Checks, and Internet Requirements - -Some Pro features (including trial, subscription, and Lifetime Plan entitlements) may require: - -- Sign-in to your account (if applicable) -- Periodic license verification -- Internet access for activation, verification, or Online Services - -If verification cannot be completed for a period of time, Pro features may be temporarily unavailable until verification -succeeds. Community Edition features may remain available. - ---- - -### 4.6 Pro Activation and Credential Sharing - -Pro Edition access is granted through a Phoenix Pro Plan entitlement (for example via account sign-in, license key, or -other activation method described in the applicable plan terms). Unless your plan terms expressly allow otherwise, Pro -entitlements are personal to the purchaser/authorized user, and you may not share or make Pro access available to others -(including by sharing credentials, keys, tokens, or activated copies). - ---- - -## 5. LICENSE GRANT - -Subject to your compliance with this Agreement, the Company grants you a **limited, non-exclusive, non-transferable, -revocable** license to install and use the Product for your internal personal or business purposes. - -Unless the Company’s plan terms specify otherwise: - -- You may install and use the Product on devices you own or control. -- You may **copy and redistribute the Installer and Community Edition freely**. However, you may not share, sell, - transfer, sublicense, rent, or lease any **Phoenix Pro Plan access, activation method, license key, entitlement, or - account credentials**, except where your plan terms expressly allow it or where prohibited by law. - -All rights not expressly granted are reserved by the Company. - ---- - -## 6. UPDATES, ONLINE SERVICES, AND AVAILABILITY - -### 6.1 Updates and Changes - -The Company may provide updates, upgrades, patches, or feature changes. Some updates may be required to maintain -security, compatibility, or continued operation. - -We may add, modify, limit, or discontinue features at any time, including Pro features and Online Services. - ---- - -### 6.2 Online Services - -Some features rely on Online Services operated by the Company or third parties. The Company will use **commercially -reasonable efforts** to operate Online Services in a reliable manner, but Online Services may from time to time be -unavailable due to maintenance, upgrades, outages, security issues, capacity limits, third-party service failures, or -events beyond our reasonable control. - -We may add, modify, limit, or discontinue Online Services (including related features), and may change eligibility, -limits, or access requirements. - -**For paid Phoenix Pro Plans**, if we elect to discontinue an Online Service (or a paid feature that materially depends -on that Online Service), we will use commercially reasonable efforts to provide at least **thirty (30) days’** advance -notice where reasonably practicable. We may discontinue or suspend Online Services immediately (or with shorter notice) -if required by law, to address security, fraud, or abuse, or to prevent material harm to the Company, users, or third -parties. - -If an Online Service is discontinued, you may still be able to use Product features that do not depend on that Online -Service. Mandatory consumer rights remain unaffected. - ---- - -## 7. RESTRICTIONS - -You may not: - -- Reverse engineer, decompile, or disassemble Pro Edition features, except to the extent such restriction is prohibited - by applicable law -- Circumvent, disable, or interfere with licensing, payments, feature controls, usage limits, or security mechanisms -- Provide access to Pro Edition features to third parties as a hosted service, time-share, service bureau, or similar - arrangement unless expressly authorized -- Use the Product to develop or offer a product or service that **substantially replicates** Phoenix Code’s Pro Edition - core functionality -- Remove or alter proprietary notices, trademarks, or license notices included in the Product - ---- - -## 8. YOUR CONTENT AND OWNERSHIP - -### 8.1 You Own Your Content - -You retain ownership of Your Content. The Company does not claim ownership of your code, files, or projects. - -### 8.2 Access to Your Content - -To provide Product features (including sync, collaboration, AI Features, or Online Services), the Product may process or -transmit Your Content as needed to perform the requested function. - ---- - -## 9. PRIVACY, HEALTH REPORTS, AND AI DATA USE - -### 9.1 Privacy Policy - -Our privacy practices are described in the Company’s Privacy Policy: -**[https://phcode.io/privacy](https://phcode.io/privacy)**. - -### 9.2 Health Reports (Anonymous Usage Statistics and Error Reports) - -Phoenix Code provides optional **Health Reports** that collect **anonymous usage statistics** and **error/diagnostic -reports** to help us prioritize features, find bugs, and improve usability and stability. - -1. **No personally identifiable information in Health Reports:** Health Reports are designed so that the Company **does - not collect or process personally identifiable information** through Health Reports. -2. **Install ID (random):** Health Reports may include a **randomly generated Install ID** created on installation to - measure anonymous counts and trends over time. The Install ID is **not derived from device hardware identifiers** and - is **not intended to identify you**. **We do not use the Install ID to directly identify you, and it is not your - account identifier.** -3. **Preview and control:** You can view what would be sent and enable/disable Health Reports in the Product (for - example, **Help > Health Report**). -4. **Necessary anonymous health indicators:** Certain anonymous measurements may be collected as **necessary app health - indicators**, such as: - - - security/app update status checks, - - analytics library initialization, - - anonymous user counts, and - - anonymous usage time, which are aggregate statistics and do not include personal data. - -5. **Support submissions:** If you choose to send support materials, logs, screenshots, or files, those materials may - include content you provide voluntarily and will be used to assist you and improve the Product. - -### 9.3 No AI Training - -**By default, the Company does not use Your Content (including code, files, or prompts) to train AI models**, unless you -**explicitly opt in** or otherwise grant permission in a manner that clearly indicates your intent. - -### 9.4 AI Feature Processing - -If you use AI Features: - -- Your input (which may include Your Content) may be processed to generate output. -- AI outputs may be similar or identical for other users. -- You are responsible for reviewing and verifying AI output before relying on it. -- The Company does not claim ownership of AI-generated output produced for you. - -If AI Features involve Third-Party Software or third-party AI services, those providers may process data under their own -terms, and details may be described in the Privacy Policy or Documentation. - -### 9.5 Account and Subscription Data (Separate from Health Reports) - -If you create an account or purchase a Phoenix Pro Plan, the Company may process account and subscription information -(such as email address and plan status) to provide authentication, billing, entitlement management, fraud prevention, -and customer support. This processing is governed by the Privacy Policy. - ---- - -## 10. THIRD-PARTY SOFTWARE - -The Product may include or depend on third-party software components, libraries, and services (“Third-Party Software”) -that are governed by their own licenses or terms. Your use of Third-Party Software is subject to those third-party -licenses and terms. - -Third-Party Software license notices and attributions are provided with the Product and/or made available at: - -- In the source repository: `https://github.com/phcode-dev/phoenix/tree/main/src/thirdparty/licences` -- Within the installed Product distribution (for example, in a “Third-Party Licenses” or similar notices location, where - provided) - -If there is a conflict between this Agreement and a Third-Party Software license regarding that Third-Party Software, -the Third-Party Software license will control for that component. Third-Party Software is provided by its respective -owners, and the Company does not make any warranties on behalf of third-party licensors. - ---- - -## 11. DISCLAIMER OF WARRANTIES - -To the maximum extent permitted by law, the Product and Online Services are provided **“as is”** and **“as available.”** - -The Company disclaims all warranties, whether express, implied, or statutory, including but not limited to warranties of -merchantability, fitness for a particular purpose, title, and non-infringement. - -We do not warrant that the Product will meet your requirements, operate without interruption, be secure, or be -error-free, or that defects will be corrected. - ---- - -## 12. LIMITATION OF LIABILITY - -We are not responsible for indirect or consequential losses, such as lost profits, lost data, or business interruption. -To the maximum extent permitted by law: - -1. The Company is not liable for any indirect, incidental, special, consequential, or punitive damages, or for loss of - profits, revenue, data, goodwill, or business interruption, arising out of or related to the Product or this - Agreement. -2. The Company’s total aggregate liability arising out of or relating to this Agreement will not exceed: - - - for paid plans: the total amount you paid to the Company for the subscription during the **most recent paid - billing period or term** immediately before the event giving rise to the claim; if you paid for an annual term - in advance, this amount will be **calculated on a pro-rata basis** for the portion of the annual term that - elapsed before the event giving rise to the claim, and - - for free users: **no liability (except to the extent liability cannot be excluded under applicable law)**, - ---- - -## 13. TERM, TERMINATION, AND SURVIVAL - -### 13.1 Term - -This Agreement applies while you use the Product. - -### 13.2 Termination - -You may stop using the Product at any time. - -The Company may terminate or suspend your rights to use the Product (including Pro features or Online Services) if you -breach this Agreement, if required for legal compliance, or if the Product is discontinued. - -### 13.3 Effect of Termination - -Upon termination, you must stop using the Product. However, if you purchased a Lifetime Plan and we terminate solely due -to Product discontinuation (not your breach), you may retain the right to use the last entitled version for eligible -on-device features, subject to applicable law. - -### 13.4 Survival - -Sections that by their nature should survive termination will survive, including Sections on ownership, privacy/AI data -use (as applicable), disclaimers, limitation of liability, governing law, and dispute provisions. - ---- - -## 14. EXPORT AND SANCTIONS COMPLIANCE - -You must comply with applicable export control and sanctions laws. You may not use or export the Product in violation of -such laws. - ---- - -## 15. GOVERNING LAW, JURISDICTION, AND COMPANY INFORMATION - -This Agreement is governed by the laws of **India**, without regard to conflict of laws principles. - -Subject to applicable consumer protection laws, the courts located in **Ernakulam, Kerala, India** will have exclusive -jurisdiction over disputes arising from or relating to this Agreement. - -Mandatory consumer rights available under applicable law remain unaffected. - -**Company Information** - -CORE.AI SCIENTIFIC TECHNOLOGIES PRIVATE LIMITED (CIN: **U72501KL2020PTC063362**) - -Registered Office: No. 6/858-M, 2nd Floor, Suite No. 695 Valamkottil Towers, Judgemukku Kakkanad, Ernakulam, Kerala – -682021 India - -Contact: **[legal@core.ai](mailto:legal@core.ai)** - ---- - -## 16. CHANGES TO THIS AGREEMENT - -We may update this Agreement from time to time. - -Unless otherwise required by applicable law, we are not obligated to provide notice of updates to this Agreement. -However, if (a) you have a **paid Phoenix Pro Plan** and a change would **materially reduce your paid entitlements** -during an active paid term, or (b) we make a **material change to our privacy practices**, we will use commercially -reasonable efforts to provide notice through reasonable means (for example, in-app notice, on our website, or via email -associated with your account). Any updated Agreement will apply **prospectively** from its effective date. - -By continuing to use the Product after the effective date of an updated Agreement, you accept the updated terms. If you -do not agree, you must stop using the Product. - ---- - -## 17. ENTIRE AGREEMENT - -This Agreement constitutes the entire agreement between you and the Company regarding the Product and supersedes all -prior agreements or understandings relating to the Product. - -If any provision of this Agreement is held unenforceable, the remaining provisions remain in full force and effect. - -The Company’s failure to enforce any right or provision does not constitute a waiver. - -You may not assign this Agreement without the Company’s prior written consent. The Company may assign this Agreement as -part of a merger, acquisition, or sale of assets. - ---- - -## Reference Links - -* Privacy Policy: **[https://phcode.io/privacy](https://phcode.io/privacy)** -* Phoenix Pro Features: **[https://phcode.io/](https://phcode.io/)** diff --git a/src-tauri/license/readme.md b/src-tauri/license/readme.md new file mode 100644 index 00000000..7591f57c --- /dev/null +++ b/src-tauri/license/readme.md @@ -0,0 +1,2 @@ +To update any licenses, please follow the instructions in the legal-docs repo. +Licenses for Phoenix Code are tracked in this repo: https://github.com/phcode-dev/legal-docs From 04e7e91b7cb5d0006ace2126a849111d70fefe44 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 10 Jan 2026 20:31:50 +0530 Subject: [PATCH 712/864] chore: short license --- src-tauri/license/phoenix-eula | 628 +-------------------------------- 1 file changed, 7 insertions(+), 621 deletions(-) diff --git a/src-tauri/license/phoenix-eula b/src-tauri/license/phoenix-eula index 9f2d092a..4e7bb7b9 100644 --- a/src-tauri/license/phoenix-eula +++ b/src-tauri/license/phoenix-eula @@ -1,624 +1,10 @@ -PHOENIX CODE USER AGREEMENT +By installing Phoenix Code, you agree to the +Phoenix Code License Agreement and Privacy Policy. -Effective Date: 1-Jan-2026 Version: 5.0 +License Agreement: +https://phcode.io/phoenix-code-license.html -Thank you for choosing Phoenix Code! +Privacy Policy: +https://phcode.io/privacy.html -This is a license agreement between you and CORE.AI Scientific -Technologies Private Limited (the “Company”, “we”, “us”) that governs -your use of Phoenix Code (the “Product”), unless other terms accompany -the Product. - -This Agreement applies only to official Phoenix Code builds distributed -by the Company (including installers, binaries, updates, and -Company-operated online services). - -If you obtain Phoenix Code source code from -https://github.com/phcode-dev/phoenix, that source code is licensed -under the GNU Affero General Public License (AGPL) and is not governed -by this Agreement except for any separate proprietary components the -Company distributes outside the AGPL repository. - ------------------------------------------------------------------------- - -THIS IS A LEGAL AGREEMENT - ------------------------------------------------------------------------- - -By clicking “I Agree”, or by downloading, installing, accessing, or -using the Product, you confirm that you have the legal capacity to enter -into this Agreement and that you agree to be bound by its terms. - -If you do not agree, do not install or use the Product. - ------------------------------------------------------------------------- - -PLAIN-ENGLISH SUMMARY (NON-BINDING) - ------------------------------------------------------------------------- - -This summary is provided for convenience only. The full legal terms -below control. - -- You always own your own code and content. -- We do not use your code, files, or content to train AI models unless - you explicitly grant permission. -- Phoenix Code includes free Community features and paid Pro features in - the same application distribution. -- You can use Community Edition features without payment. -- Pro features require an active Phoenix Pro plan (trial or paid plan). -- When Pro access ends, the app automatically switches back to Community - Edition. -- Your files and data are not deleted when this happens. -- Phoenix Code can send anonymous usage statistics and error reports - (“Health Reports”). You can opt out in Help > Health Report, and view - a preview of what would be sent. -- Some features depend on online services (ours or third parties). Those - services may change, be limited, or be discontinued over time. -- If you purchase a Lifetime Plan, you can keep using eligible on-device - Pro features perpetually, but updates and service-backed features may - only be included through the Lifetime Update Period stated at - purchase. - ------------------------------------------------------------------------- - -1. OVERVIEW AND SCOPE - ------------------------------------------------------------------------- - -This Agreement governs your installation and use of the Product, -including: - -- Desktop applications -- Web-based applications -- Installers and binaries -- Updates, upgrades, patches, and related services (including online - services) - -The Product may include both Community Edition (free) features and Pro -Edition (paid) features within the same application. - -Your ability to use certain features depends on whether you have an -active Phoenix Pro Plan or other entitlement. - -Online Services: If you use Company-operated online services (accounts, -publishing/preview, AI features, or other service-backed features), -those services may also be governed by our Terms of Service: -https://phcode.io/terms-of-service.html. If there is a conflict, the -Privacy Policy controls for privacy/data processing, the EULA controls -for the Product, and the Terms of Service control for the Services. - ------------------------------------------------------------------------- - -2. DEFINITIONS - ------------------------------------------------------------------------- - -- Product: Phoenix Code, including desktop applications, web-based - applications, installers, updates, and related services -- Installer: The installation package distributed by the Company -- Documentation: Official Phoenix Code documentation and materials -- Community Edition: Functionality made available at no charge -- Pro Edition: Paid, commercial functionality of Phoenix Code -- Phoenix Pro Plan: Any Company-authorized plan that grants access to - Pro Edition features, including trials or paid plans -- Lifetime Plan: A one-time paid plan that grants long-term access to - certain Pro Edition features, subject to Section 4.4 -- Lifetime Update Period: The specific update/service access period - stated at purchase for a Lifetime Plan -- Online Services: Services operated by the Company or third parties - that support some features (for example hosted libraries, cloud - features, account services, licensing/activation, AI services) -- Third-Party Software: Software or services provided by third parties, - governed by separate terms -- AI Features: Features that use artificial intelligence services - (Company-operated or third-party) -- Your Content: Your code, files, text, prompts, inputs, projects, and - other content you create or provide -- Health Reports: Anonymous usage statistics and error/diagnostic - reports sent by the Product to improve stability, usability, and - prioritization (Section 9) - ------------------------------------------------------------------------- - -3. LICENSE STRUCTURE AND EDITIONS - ------------------------------------------------------------------------- - -3.1 Unified Application License - -The Installer and distributed application binary are licensed under this -Agreement. - -This Agreement governs use of: - -- Phoenix Code as distributed by the Company -- Both Community Edition and Pro Edition functionality contained within - the same application - -Feature availability depends on your plan/entitlements. - -3.2 Community Edition and Open-Source Components - -Certain components may be made available under open-source licenses -(including the GNU Affero General Public License (AGPL)) when the -Company separately distributes specific source code under those -licenses. - -Open-source components are governed solely by the applicable open-source -license. - -This Agreement does not replace or override applicable open-source -licenses for source code expressly released under them. - -The compiled binaries and Installer provided by the Company are not -distributed under AGPL. - -3.3 Pro Edition (Commercial) - -Pro Edition features are proprietary and licensed under this Agreement -only. - -- Pro Edition is not open source -- Open-source licenses do not apply to Pro Edition features unless - explicitly stated - ------------------------------------------------------------------------- - -4. PRO ACCESS, TRIALS, LIFETIME PLANS, AND DOWNGRADES - ------------------------------------------------------------------------- - -4.1 Pro Access - -Access to Pro Edition features requires an active Phoenix Pro Plan or -other entitlement. - -Plan details, eligibility, feature availability, and usage limits -(including any quotas or exclusions for specific plan types such as -educational plans) are described at purchase, in-product, and/or in the -Phoenix Pro Plan Terms. https://phcode.io/phoenix-pro-plan-terms.html. - -4.2 Automatic Downgrade - -If your Phoenix Pro Plan expires, is cancelled, or otherwise ends, the -Product automatically reverts to Community Edition functionality. No -additional notice is required. - -4.3 No Data Deletion - -Downgrading does not delete Your Content. Some Pro features and related -data formats/outputs may become unavailable or restricted. - -4.4 Lifetime Plan Terms - -A Lifetime Plan grants long-term access to eligible Pro Edition features -that run entirely on your device, subject to this Agreement and your -compliance with it. - -Lifetime does not mean we must provide updates, support, or Online -Services forever. - -1. Perpetual use of eligible on-device features: You may continue using - the last Pro-enabled version you are entitled to indefinitely for - eligible on-device Pro features. -2. Updates and service-backed features limited by Lifetime Update - Period: Your entitlement to updates, upgrades, support, and any Pro - features that rely on Online Services may be limited to the Lifetime - Update Period stated at purchase. -3. Online Services may change: Online Services (including hosted - libraries, cloud features, licensing, AI, or other service-backed - features) may be modified, limited, or discontinued as described in - Section 6. -4. Feature classification reference: The Company may publish which Pro - features are on-device vs service-backed in the Phoenix Pro feature - set/Documentation. - -4.5 Activation, License Checks, and Internet Requirements - -Some Pro features (including trial, subscription, and Lifetime Plan -entitlements) may require: - -- Sign-in to your account (if applicable) -- Periodic license verification -- Internet access for activation, verification, or Online Services - -If verification cannot be completed for a period of time, Pro features -may be temporarily unavailable until verification succeeds. Community -Edition features may remain available. - -4.6 Pro Activation and Credential Sharing - -Pro Edition access is granted through a Phoenix Pro Plan entitlement -(for example via account sign-in, license key, or other activation -method described in the applicable plan terms). Unless your plan terms -expressly allow otherwise, Pro entitlements are personal to the -purchaser/authorized user, and you may not share or make Pro access -available to others (including by sharing credentials, keys, tokens, or -activated copies). - ------------------------------------------------------------------------- - -5. LICENSE GRANT - ------------------------------------------------------------------------- - -Subject to your compliance with this Agreement, the Company grants you a -limited, non-exclusive, non-transferable, revocable license to install -and use the Product for your internal personal or business purposes. - -Unless the Company’s plan terms specify otherwise: - -- You may install and use the Product on devices you own or control. -- You may copy and redistribute the Installer and Community Edition - freely. However, you may not share, sell, transfer, sublicense, rent, - or lease any Phoenix Pro Plan access, activation method, license key, - entitlement, or account credentials, except where your plan terms - expressly allow it or where prohibited by law. - -All rights not expressly granted are reserved by the Company. - ------------------------------------------------------------------------- - -6. UPDATES, ONLINE SERVICES, AND AVAILABILITY - ------------------------------------------------------------------------- - -6.1 Updates and Changes - -The Company may provide updates, upgrades, patches, or feature changes. -Some updates may be required to maintain security, compatibility, or -continued operation. - -We may add, modify, limit, or discontinue features at any time, -including Pro features and Online Services. - -6.2 Online Services - -Some features rely on Online Services operated by the Company or third -parties. The Company will use commercially reasonable efforts to operate -Online Services in a reliable manner, but Online Services may from time -to time be unavailable due to maintenance, upgrades, outages, security -issues, capacity limits, third-party service failures, or events beyond -our reasonable control. - -We may add, modify, limit, or discontinue Online Services (including -related features), and may change eligibility, limits, or access -requirements. - -For paid Phoenix Pro Plans, if we elect to discontinue an Online Service -(or a paid feature that materially depends on that Online Service), we -will use commercially reasonable efforts to provide at least thirty (30) -days’ advance notice where reasonably practicable. We may discontinue or -suspend Online Services immediately (or with shorter notice) if required -by law, to address security, fraud, or abuse, or to prevent material -harm to the Company, users, or third parties. - -If an Online Service is discontinued, you may still be able to use -Product features that do not depend on that Online Service. Mandatory -consumer rights remain unaffected. - ------------------------------------------------------------------------- - -7. RESTRICTIONS - ------------------------------------------------------------------------- - -You may not: - -- Reverse engineer, decompile, or disassemble Pro Edition features, - except to the extent such restriction is prohibited by applicable law -- Circumvent, disable, or interfere with licensing, payments, feature - controls, usage limits, or security mechanisms -- Provide access to Pro Edition features to third parties as a hosted - service, time-share, service bureau, or similar arrangement unless - expressly authorized -- Use the Product to develop or offer a product or service that - substantially replicates Phoenix Code’s Pro Edition core functionality -- Remove or alter proprietary notices, trademarks, or license notices - included in the Product - ------------------------------------------------------------------------- - -8. YOUR CONTENT AND OWNERSHIP - ------------------------------------------------------------------------- - -8.1 You Own Your Content - -You retain ownership of Your Content. The Company does not claim -ownership of your code, files, or projects. - -8.2 Access to Your Content - -By default, we do not see or have access to Your data in the Product. - -To provide Product features (including sync, collaboration, AI Features, -or Online Services), the Product may process or transmit Your Content as -needed to perform the function you request. - -When a feature first requires transmitting Your Content, the Product -will notify you and ask for your permission before sending any data. -After you grant permission for that feature, similar transmissions for -the same feature may occur without additional prompts to improve -usability. You can withdraw consent for future transmissions by -disabling the relevant feature or changing the applicable settings (if -available). - ------------------------------------------------------------------------- - -9. PRIVACY, HEALTH REPORTS, AND AI DATA USE - ------------------------------------------------------------------------- - -9.1 Privacy Policy - -Our privacy practices are described in the Company’s Privacy Policy: -https://phcode.io/privacy.html. - -9.2 Health Reports (Anonymous Usage Statistics and Error Reports) - -Phoenix Code provides optional Health Reports that collect anonymous -usage statistics and error/diagnostic reports to help us prioritize -features, find bugs, and improve usability and stability. - -1. No personally identifiable information in Health Reports: Health - Reports are designed so that the Company does not collect or process - personally identifiable information through Health Reports. - -2. Install ID (random): Health Reports may include a randomly generated - Install ID created on installation to measure anonymous counts and - trends over time. The Install ID is not derived from device hardware - identifiers and is not intended to identify you. We do not use the - Install ID to directly identify you, and it is not your account - identifier. - -3. Preview and control: You can view what would be sent and - enable/disable Health Reports in the Product (for example, Help > - Health Report). - -4. Necessary anonymous health indicators: Certain anonymous - measurements may be collected as necessary app health indicators, - such as: - - - security/app update status checks, - - analytics library initialization, - - anonymous user counts, and - - anonymous usage time, which are aggregate statistics and do not - include personal data. - -5. Support submissions: If you choose to send support materials, logs, - screenshots, or files, those materials may include content you - provide voluntarily and will be used to assist you and improve the - Product. - -9.3 No AI Training - -By default, the Company does not use Your Content (including code, -files, or prompts) to train AI models, unless you explicitly opt in or -otherwise grant permission in a manner that clearly indicates your -intent. - -9.4 AI Feature Processing - -If you use AI Features: - -- Your input (which may include Your Content) may be processed to - generate output. -- AI outputs may be similar or identical for other users. -- You are responsible for reviewing and verifying AI output before - relying on it. -- The Company does not claim ownership of AI-generated output produced - for you. - -If AI Features involve Third-Party Software or third-party AI services, -those providers may process data under their own terms, and details may -be described in the Privacy Policy or Documentation. - -9.5 Account and Subscription Data (Separate from Health Reports) - -If you create an account or purchase a Phoenix Pro Plan, the Company may -process account and subscription information (such as email address and -plan status) to provide authentication, billing, entitlement management, -fraud prevention, and customer support. This processing is governed by -the Privacy Policy. - ------------------------------------------------------------------------- - -10. THIRD-PARTY SOFTWARE - ------------------------------------------------------------------------- - -The Product may include or depend on third-party software components, -libraries, and services (“Third-Party Software”) that are governed by -their own licenses or terms. Your use of Third-Party Software is subject -to those third-party licenses and terms. - -Third-Party Software license notices and attributions are provided with -the Product and/or made available at: - -- In the source repository: - https://github.com/phcode-dev/phoenix/tree/main/src/thirdparty/licences -- Within the installed Product distribution (for example, in a - “Third-Party Licenses” or similar notices location, where provided) - -If there is a conflict between this Agreement and a Third-Party Software -license regarding that Third-Party Software, the Third-Party Software -license will control for that component. Third-Party Software is -provided by its respective owners, and the Company does not make any -warranties on behalf of third-party licensors. - ------------------------------------------------------------------------- - -11. DISCLAIMER OF WARRANTIES - ------------------------------------------------------------------------- - -To the maximum extent permitted by law, the Product and Online Services -are provided “as is” and “as available.” - -The Company disclaims all warranties, whether express, implied, or -statutory, including but not limited to warranties of merchantability, -fitness for a particular purpose, title, and non-infringement. - -We do not warrant that the Product will meet your requirements, operate -without interruption, be secure, or be error-free, or that defects will -be corrected. - ------------------------------------------------------------------------- - -12. LIMITATION OF LIABILITY - ------------------------------------------------------------------------- - -We are not responsible for indirect or consequential losses, such as -lost profits, lost data, or business interruption. To the maximum extent -permitted by law: - -1. The Company is not liable for any indirect, incidental, special, - consequential, or punitive damages, or for loss of profits, revenue, - data, goodwill, or business interruption, arising out of or related - to the Product or this Agreement. - -2. The Company’s total aggregate liability arising out of or relating - to this Agreement will not exceed: - - - for paid plans: the total amount you paid to the Company for the - subscription during the most recent paid billing period or term - immediately before the event giving rise to the claim; if you paid - for an annual term in advance, this amount will be calculated on a - pro-rata basis for the portion of the annual term that elapsed - before the event giving rise to the claim, and - - for free users: no liability (except to the extent liability - cannot be excluded under applicable law), - -3. You agree that the limits in this Section are the maximum amounts - the Company will be responsible for, and you will not seek - compensation for any loss or damage in excess of those limits. These - limitations apply even if we have been advised of the possibility of - such damages and even if any remedy fails of its essential purpose. - Nothing in this Agreement limits liability where it cannot be - limited under applicable law. - ------------------------------------------------------------------------- - -13. TERM, TERMINATION, AND SURVIVAL - ------------------------------------------------------------------------- - -13.1 Term - -This Agreement applies while you use the Product. - -13.2 Termination - -You may stop using the Product at any time. - -The Company may terminate or suspend your rights to use the Product -(including Pro features or Online Services) if you breach this -Agreement, if required for legal compliance, or if the Product is -discontinued. - -13.3 Effect of Termination - -Upon termination, you must stop using the Product. However, if you -purchased a Lifetime Plan and we terminate solely due to Product -discontinuation (not your breach), you may retain the right to use the -last entitled version for eligible on-device features, subject to -applicable law. - -13.4 Survival - -Sections that by their nature should survive termination will survive, -including Sections on ownership, privacy/AI data use (as applicable), -disclaimers, limitation of liability, governing law, and dispute -provisions. - ------------------------------------------------------------------------- - -14. EXPORT AND SANCTIONS COMPLIANCE - ------------------------------------------------------------------------- - -You must comply with applicable export control and sanctions laws. You -may not use or export the Product in violation of such laws. - ------------------------------------------------------------------------- - -15. GOVERNING LAW, JURISDICTION, AND COMPANY INFORMATION - ------------------------------------------------------------------------- - -This Agreement is governed by the laws of India, without regard to -conflict of laws principles. - -Subject to applicable consumer protection laws, the courts located in -Ernakulam, Kerala, India will have exclusive jurisdiction over disputes -arising from or relating to this Agreement. - -Mandatory consumer rights available under applicable law remain -unaffected. - -Company Information - -CORE.AI SCIENTIFIC TECHNOLOGIES PRIVATE LIMITED (CIN: -U72501KL2020PTC063362) - -Registered Office: No. 6/858-M, 2nd Floor, Suite No. 695 Valamkottil -Towers, Judgemukku Kakkanad, Ernakulam, Kerala – 682021 India - -Contact: legal@core.ai - ------------------------------------------------------------------------- - -16. CHANGES TO THIS AGREEMENT - ------------------------------------------------------------------------- - -We may update this Agreement from time to time. - -Unless otherwise required by applicable law, we are not obligated to -provide notice of updates to this Agreement. However, if (a) you have a -paid Phoenix Pro Plan and a change would materially reduce your paid -entitlements during an active paid term, or (b) we make a material -change to our privacy practices, we will use commercially reasonable -efforts to provide notice through reasonable means (for example, in-app -notice, on our website, or via email associated with your account). Any -updated Agreement will apply prospectively from its effective date. - -By continuing to use the Product after the effective date of an updated -Agreement, you accept the updated terms. If you do not agree, you must -stop using the Product. - ------------------------------------------------------------------------- - -17. ENTIRE AGREEMENT - ------------------------------------------------------------------------- - -This Agreement constitutes the entire agreement between you and the -Company regarding the Product and supersedes all prior agreements or -understandings relating to the Product. - -If any provision of this Agreement is held unenforceable, the remaining -provisions remain in full force and effect. - -The Company’s failure to enforce any right or provision does not -constitute a waiver. - -You may not assign this Agreement without the Company’s prior written -consent. The Company may assign this Agreement as part of a merger, -acquisition, or sale of assets. - ------------------------------------------------------------------------- - -REFERENCE LINKS - ------------------------------------------------------------------------- - -- Terms of Service: https://phcode.io/terms-of-service.html -- Phoenix Code User Agreement (EULA): - https://phcode.io/phoenix-code-eula.html -- Privacy Policy: https://phcode.io/privacy.html -- Phoenix Pro Plan Terms: https://phcode.io/phoenix-pro-plan-terms.html -- Cancellation and Refund Policy: https://phcode.io/cancellation.html +Please accept the agreement to continue. From 4e141cf07d8a41e1c69cffc6d70e8fd7e8b45d2b Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 12 Jan 2026 09:04:36 +0000 Subject: [PATCH 713/864] ci: update phcode version to 5.0.0 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 4f144293..a9a3a149 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "4.1.1", + "version": "5.0.0", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "a24e0b5d37a989818c2d37560fa31038556a8e17" + "commit": "c9b089b185175d566b05edf000cbd9194c11032d" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c6ac1445..16d16718 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "4.1.1" +version = "5.0.0" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index add01d52..28fc70bd 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "4.1.1" + "version": "5.0.0" }, "tauri": { "allowlist": { @@ -484,4 +484,4 @@ } ] } -} +} \ No newline at end of file From 380ec56f9321e99870d9f62574c9f62e40b39df6 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 12 Jan 2026 10:33:10 +0000 Subject: [PATCH 714/864] ci: update phcode version to 5.0.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index a9a3a149..5bdcfd8f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.0.0", + "version": "5.0.1", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "c9b089b185175d566b05edf000cbd9194c11032d" + "commit": "e6945c8aa71062f9120aa040b0d348e3dcb75222" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 16d16718..b266402a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.0.0" +version = "5.0.1" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 28fc70bd..8467d66a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.0.0" + "version": "5.0.1" }, "tauri": { "allowlist": { From ab718e17a47454df8e38f7cf8cf32b2a921f9ac5 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 14 Jan 2026 17:21:26 +0530 Subject: [PATCH 715/864] chore: show new user survery 20>35 minutes. power 35>45 days --- docs/surveys.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/surveys.json b/docs/surveys.json index 6f50e5b1..2c7f1643 100644 --- a/docs/surveys.json +++ b/docs/surveys.json @@ -1,12 +1,12 @@ { "newUser": "https://s.surveyplanet.com/jssqbld8", "powerUser": "https://s.surveyplanet.com/v3j59a7z", - "newUserShowDelayMS": 1200000, - "powerUserShowIntervalDays": 35, + "newUserShowDelayMS": 2100000, + "powerUserShowIntervalDays": 45, "browser": { "newUser": "https://s.surveyplanet.com/5lrpp9ud", "powerUser": "https://s.surveyplanet.com/wtohpj8x", - "newUserShowDelayMS": 1200000, - "powerUserShowIntervalDays": 35 + "newUserShowDelayMS": 2100000, + "powerUserShowIntervalDays": 45 } } From 154d4d5369da01f824efe3737da8ea8be0e712ee Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 16 Jan 2026 03:21:40 +0000 Subject: [PATCH 716/864] ci: update phcode version to 5.0.2 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 5bdcfd8f..d7e82a9a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.0.1", + "version": "5.0.2", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "e6945c8aa71062f9120aa040b0d348e3dcb75222" + "commit": "065031b0984bfcf0ab5dfc1a2753b74a35222645" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b266402a..86df4cf9 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.0.1" +version = "5.0.2" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8467d66a..222d8073 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.0.1" + "version": "5.0.2" }, "tauri": { "allowlist": { From 318e1701e84e6bbe2e0431d8a8740603a91b701e Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sun, 18 Jan 2026 08:45:39 +0000 Subject: [PATCH 717/864] ci: update phcode version to 5.0.3 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index d7e82a9a..b7e81395 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.0.2", + "version": "5.0.3", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "065031b0984bfcf0ab5dfc1a2753b74a35222645" + "commit": "29fa0a4dac75e9484f050f7c7febcfb244703bbd" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 86df4cf9..a2668723 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.0.2" +version = "5.0.3" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 222d8073..4c1a5d09 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.0.2" + "version": "5.0.3" }, "tauri": { "allowlist": { From f77691ac0bc4a5235dffd5330dd6858480007186 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 18 Jan 2026 19:23:30 +0530 Subject: [PATCH 718/864] chore: remove ubuntu 20 as its deprected by github, will build manually --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index d9a1e48b..3bc19fe7 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -280,7 +280,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ ubuntu-20.04, ubuntu-22.04] + platform: [ ubuntu-22.04] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 0ee9c993..897d0636 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -329,7 +329,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ ubuntu-20.04, ubuntu-22.04] + platform: [ ubuntu-22.04] runs-on: ${{ matrix.platform }} steps: diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index ad7aff0c..fdbb2535 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -280,7 +280,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [ ubuntu-20.04, ubuntu-22.04] + platform: [ ubuntu-22.04] runs-on: ${{ matrix.platform }} steps: From 870c613546209c8e47f8762d867ee4dde309dabd Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 19 Jan 2026 19:11:04 +0530 Subject: [PATCH 719/864] chore: new survey urls --- docs/surveys.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/surveys.json b/docs/surveys.json index 2c7f1643..2d97d7b6 100644 --- a/docs/surveys.json +++ b/docs/surveys.json @@ -1,11 +1,11 @@ { - "newUser": "https://s.surveyplanet.com/jssqbld8", - "powerUser": "https://s.surveyplanet.com/v3j59a7z", + "newUser": "https://s.surveyplanet.com/9y5p5azy", + "powerUser": "https://s.surveyplanet.com/dfy15wgk", "newUserShowDelayMS": 2100000, "powerUserShowIntervalDays": 45, "browser": { - "newUser": "https://s.surveyplanet.com/5lrpp9ud", - "powerUser": "https://s.surveyplanet.com/wtohpj8x", + "newUser": "https://s.surveyplanet.com/d7vk6wq5", + "powerUser": "https://s.surveyplanet.com/e3r7fm8c", "newUserShowDelayMS": 2100000, "powerUserShowIntervalDays": 45 } From 97e402e130fcb210d29c5ff9ec4956058626e9d7 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 19 Jan 2026 15:26:22 +0000 Subject: [PATCH 720/864] ci: update phcode version to 5.0.5 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b7e81395..863999fb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.0.3", + "version": "5.0.5", "type": "module", "scripts": { "tauri": "tauri", @@ -54,6 +54,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "29fa0a4dac75e9484f050f7c7febcfb244703bbd" + "commit": "23987dad9240266fd297cbb99202178a3f68a6b2" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a2668723..f6c6fca2 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.0.3" +version = "5.0.5" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 4c1a5d09..f3a08375 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -9,7 +9,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.0.3" + "version": "5.0.5" }, "tauri": { "allowlist": { From 275fed2d1ea155df981307aa6f230ef57bfaaf61 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 19 Jan 2026 17:37:04 +0000 Subject: [PATCH 721/864] ci: tauri release update notification json --- docs/install.json | 6 ++--- docs/tauri/update-latest-stable-prod.json | 30 ++++++++++++++++------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/docs/install.json b/docs/install.json index 6b66eecc..fa11c15b 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,8 +1,8 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_4.0.3_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_4.0.3_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_4.0.3_x64.dmg", + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_x64.dmg", "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 61ab8b87..389dba8c 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,19 +1,31 @@ { - "version": "4.0.3", - "notes": "2025 January release(4.0) of Phoenix Code is now available for download at [phcode.io](https://phcode.io).\r\n\r\nThis is the largest release we had in a while, and we are happy to announce the next phase of Phoenix Code with\r\na major version bump to 4.0.\r\n\r\n## The legacy of Brackets - Continued\r\nA decade-long journey of pushing web development forward: The Brackets story continues with Phoenix Code.\r\n[Read more about the story of Brackets and the journey to build Phoenix Code and the Brackets community.](https://docs.phcode.dev/blog/Blog-Legacy)\r\n\r\nThis release's core theme is `Git, Color previews, UX imporovements and stability`.\r\n\r\n## Git for Desktop\r\n\r\nGit is finally here. Integrated Git source control with a clean, intuitive interface. Stage changes, commit, and sync with a single click while keeping your focus on the code. Now available in the Windows, Mac and Linux desktop apps of Phoenix code. [Read More...](https://docs.phcode.dev/docs/Features/git)\r\n\r\nOur Git integration is built upon the incredible work of the developers behind [Brackets-Git](https://github.com/brackets-userland/brackets-git), whose contributions made this possible. Thank you!\r\n\r\n![Image](https://github.com/user-attachments/assets/aeacc7c0-3ee3-4a80-9b05-f2b48140bcdd)\r\n\r\n![Image](https://github.com/user-attachments/assets/6e7b9faf-d57b-448b-a5bb-a111c67489b5)\r\n\r\n## Color Previews\r\n\r\nPreview the color(s) used in the file in the gutter area. Hovering over a color box highlights the corresponding color text in the editor to quickly jump to editing that color. [Read More...](https://docs.phcode.dev/docs/editing-colors#color-preview)\r\n\r\n![image](https://github.com/user-attachments/assets/bedecc32-761b-448e-aced-61828ad3fec6)\r\n\r\n## Open in Terminal and File Explorer\r\n\r\nNew \"Open In\" feature lets you instantly open directories and files in the system Terminal or File Explorer across Windows, macOS, and Linux desktop apps!\r\n\r\n![Image](https://github.com/user-attachments/assets/710330ae-8b34-4a51-a1f9-4c02736ed9bd)\r\n\r\n## Better Translations\r\n\r\nWe've moved to an LLM-assisted translation framework, delivering higher-quality translations for non-English locales.\r\n\r\n## Notable changes and fixes\r\n\r\n- We've removed some inconsistent and rarely used keyboard shortcuts to free up more key combinations for customization.\r\n [Easily configure your own keyboard shortcuts through the UI.](https://docs.phcode.dev/docs/Features/keyboard-shortcuts)\r\n- Fixed `Option-[shift]-left` and `option-[shift]-right` keyboard shortcuts not working in mac to select/move words.\r\n- Survey popups are now less intrusive, appearing as notifications without disrupting your workflow.\r\n- Moved back `line:ch` status to left of statusbar. Go to line will accept `:ln:col` format along with `:ln,col`. ![Image](https://github.com/user-attachments/assets/7429ae42-cb56-444c-8546-6d565bedaaf9)\r\n- [Remove specific files from Recent Files](https://github.com/phcode-dev/phoenix/pull/2035)\r\n- Fixes [holding ctrl key in windows should not ui overlay mode.](https://github.com/phcode-dev/phoenix/pull/2015)\r\n- [fix: `cmd-click` in mac app and safari didn't open context menu.](https://github.com/phcode-dev/phoenix/pull/1994)\r\n- [Switching between Ctrl+F and Ctrl+Shift+F now correctly updates the search box with the latest selection.](https://github.com/phcode-dev/phoenix/pull/1999)\r\n- [fix: clicking on prevent defaulted A tags in desktop live preview opens browser tab.](https://github.com/phcode-dev/phoenix/pull/1997)\r\n \r\n## Performance & Stability Tweaks\r\n\r\n- [Faster boot times with extension compression and load changes](https://github.com/phcode-dev/phoenix/pull/2055)\r\n consistency and performance, especially on Safari and macOS.\r\n- [File recovery should only be shown on crash, and fix some file recovery issues.](https://github.com/phcode-dev/phoenix/pull/2082)\r\n\r\n## All changes\r\n\r\nPlease see [this link](https://github.com/phcode-dev/phoenix/commits/main/?since=2024-11-27&until=2025-01-30) for a full list of changes in GitHub.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n- [**Consider supporting us** on GitHub Sponsors](https://github.com/sponsors/phcode-dev). Every contribution helps us to keep improving Phoenix Code.\r\n\r\nWith gratitude,\r\n\r\nThe Phoenix Team\r\n", - "pub_date": "2025-01-31T06:06:16.997Z", + "version": "5.0.5", + "notes": "2026 January release (5.0) of Phoenix Code is now available for download at [phcode.io](https://phcode.io).\r\n\r\nOur biggest update yet - introducing `Phoenix Pro` and major upgrades like `Live Preview Edit`, `Emmet`, `Tab Bar`, and `Custom Snippets`.\r\n\r\n## Phoenix Pro - A Sustainable Future\r\n\r\nPhoenix Code has been free and open source from day one - and **everything you’ve used so far will remain free forever**, including **Live Preview**.\r\n\r\nWe’re a small, full-time indie team with **no VC backing**, building Phoenix Code because we believe the web deserves a code editor that’s genuinely **simple and joyful to use**. We tried to sustain development through community donations ([Open Collective](https://opencollective.com/phoenix-ide)), but over the last few years it hasn’t been enough to support full-time work - and we reached a hard choice: slow down drastically, or find a sustainable path that keeps Phoenix Code healthy.\r\n\r\nSo we’re introducing **Phoenix Pro** as an *optional* way to support Phoenix Code’s future - with **one Pro feature: Live Preview Edit**.\r\nIf Phoenix Code has helped you, Phoenix Pro is a way to help keep the project moving forward.\r\n\r\nStudents & educators get **Phoenix Pro for Education** at no cost, because we want classrooms to have easy access to modern, easy-to-use development tooling. [Read More](https://docs.phcode.dev/docs/phoenix-pro-school)\r\n\r\n## Live Preview Edit\r\n\r\n*Included with Phoenix Pro.*\r\n\r\n**Live Preview Edit** lets you make changes directly on your page — and updates your source code instantly.\r\n\r\nEdit text, links, and images. Drag & drop to rearrange elements. Cut, copy, paste, and use measurement tools to place things precisely.\r\n\r\nLearn more: [Live Preview Edit](https://docs.phcode.dev/docs/Pro%20Features/live-preview-edit), [Image Gallery](https://docs.phcode.dev/docs/Pro%20Features/image-gallery), [Measurements](https://docs.phcode.dev/docs/Pro%20Features/measurements).\r\n\r\n![image](https://github.com/user-attachments/assets/5ef26ba0-12bd-4145-9e30-d404aabe5092)\r\n\r\n## Emmet\r\n\r\n**Emmet** one of our most requested features is finally here.\r\n\r\nWrite Emmet abbreviations and Phoenix Code shows you hints. Select a hint to expand it into a full code snippet. Code faster than ever. [Read More](https://docs.phcode.dev/docs/Features/emmet)\r\n\r\n![emmet](https://github.com/user-attachments/assets/fe767274-cb03-491c-9cf8-bfbc560490d6)\r\n\r\n## Tab Bar\r\n\r\nTab Bar is here. View all your open files at the top of the editor and switch between them instantly.\r\n\r\nChoose what works for you - Tab Bar, Working Files, or both at the same time. [Read More](https://docs.phcode.dev/docs/file-management#tab-bar)\r\n\r\n![tab bar](https://github.com/user-attachments/assets/3febc149-d3e6-44a7-bbe6-f305e7726703)\r\n\r\n## Custom Snippets\r\n\r\nDefine your own code hints with Custom Snippets.\r\n\r\nCreate hints that expand into full code blocks. You can also add cursor positions so Phoenix Code places your cursor exactly where you need it after expansion. [Read More](https://docs.phcode.dev/docs/Features/custom-snippets)\r\n\r\n![snippets](https://github.com/user-attachments/assets/b3ff85db-82db-468b-ba65-c1878b371292)\r\n\r\n## Collapse Folders\r\n\r\nAfter working for some time, your project structure gets messy with lots of open and nested directories.\r\n\r\nBut no worries now. Phoenix Code supports Collapse All Folders, which lets you reset your view by collapsing all expanded folders to their root level in one click. [Read More](https://docs.phcode.dev/docs/file-management#collapse-all-folders)\r\n\r\n![collapse](https://github.com/user-attachments/assets/e230e87f-25da-4bd4-a43c-91f13398acee)\r\n\r\n## Notable changes and fixes\r\n\r\n- Improved Live Preview to support internal stylesheets and SVGs better than before.\r\n- Smarter color hints. Phoenix Code prioritizes your previously used colors. [Read More](https://docs.phcode.dev/docs/editing-colors#color-hints)\r\n- Git markers now appear in the scrollbar, making it easier to locate changes in a file.\r\n- Improved Git so that it doesn't show stale project status.\r\n- Reduced the number of popups shown when first installing Phoenix.\r\n- Fixed an issue where macOS/iOS and browser autocorrect or smart keyboards altered filenames during renames.\r\n- Added a dialog to notify users when they have security compromised extensions installed.\r\n- Slowed down the Quick View popup on hover as it was interfering with user workflows.\r\n- Fixed ghost image appearing in Safari when dragging from CodeMirror.\r\n- Long names in Working Files are now truncated for better readability.\r\n- Added Horizontal Scroll support. Use Shift + mouse scroll.\r\n\r\n## All changes\r\n\r\nPlease see [this link](https://github.com/phcode-dev/phoenix/commits/main/?since=2025-01-30&until=2026-01-18) for a full list of changes\r\nin GitHub.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n\r\nWith gratitude,\r\n\r\nThe Phoenix Team\r\n", + "pub_date": "2026-01-19T16:14:31.777Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmpZZHVoMXU4OUs5UWJKcE1jSFh3Tk5hVFdMbkNzaXd0WmV3cm5kcVJQWmZHb3FiZURjNUxXRnJLZUJZWmFvUkgvNmRXYUhMZFBXOGdaekZYM1VpM3dNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzM4Mjk0MDcwCWZpbGU6UGhvZW5peCBDb2RlXzQuMC4zX3g2NC1zZXR1cC5uc2lzLnppcAp3aWc1cnBWbVdpbGZmUk1iUU1DWTJLc2tBQ3lVclJMZFp2N1lqWjNqUzVwcjdHWmVDTzF3QVVPZDZMQUFDWUJNZXRMci92Q0lyOGpHeVNjWmE1NGhDZz09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_4.0.3_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5YL25INWhMOGpPd01XNTVNU0lYWHZsbWdTdTRISmdUQlMwb3pvMVJMWDl2OEkwMFRGczZadUhwN2RWMFBMeFBpU2ViYVJVQlFVSXNMYjNSMW5CZHdBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM3NDkyCWZpbGU6UGhvZW5peCBDb2RlXzUuMC41X3g2NC1zZXR1cC5uc2lzLnppcAo0VUxEMkt2OE1TMzFNdzMvYnNzakkxbnFuOFZhWTBuc3krN2dwcStjZVhRcm9zVk1SQ0xvVnR5bXpxZ2haaEh6S1hEaldpZGJLc2FtSXNCYU1laHhDZz09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_x64-setup.nsis.zip" + }, + "windows-x86_64-nsis": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5YL25INWhMOGpPd01XNTVNU0lYWHZsbWdTdTRISmdUQlMwb3pvMVJMWDl2OEkwMFRGczZadUhwN2RWMFBMeFBpU2ViYVJVQlFVSXNMYjNSMW5CZHdBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM3NDkyCWZpbGU6UGhvZW5peCBDb2RlXzUuMC41X3g2NC1zZXR1cC5uc2lzLnppcAo0VUxEMkt2OE1TMzFNdzMvYnNzakkxbnFuOFZhWTBuc3krN2dwcStjZVhRcm9zVk1SQ0xvVnR5bXpxZ2haaEh6S1hEaldpZGJLc2FtSXNCYU1laHhDZz09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhSVTJWSjlNaG43SU1HM3dRNk9yZDc3SDRnMlZzb3UxRllCazI3KzNTejU2S0Z3Mk1lb2t0dE1JMUl2akwwa2s5SnR2ZldDRmc0OVdGZHFocHREZEFvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzM4MzAyOTI0CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKOTNMTnpMZE9XcXhUV1haK1BZUDdUampBSU9UWmR4S3Y2eWRZemRqMzNNQ1pTeGd4VllhT2trQW55bFBleXBLSzhDRUI1Rzl6OXFIMDFCWmo4SDdKQ3c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRQYWlKenFodTRUTThzUDh2d3pqby9yTUFxQmRsSm5nOVRFazNQdHhDWHc4YXcwZWxMOVdjek00RDJqNTFSYWNNZ3VJOVUrUEkzbHJ5WXh2NWlWcXdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM4NzE1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKU2NYRGJKVWdnMzY2dWVjNGZ3YWpFZWhlUzZYeXAzTXN3NmM2bVAvYjFQb2t0OE1YNG9NV0o1NVlJMmZKSmdVVFllUkRkaGFlejVDUzlFY1NwTHRoQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_x64.app.tar.gz" + }, + "darwin-x86_64-app": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRQYWlKenFodTRUTThzUDh2d3pqby9yTUFxQmRsSm5nOVRFazNQdHhDWHc4YXcwZWxMOVdjek00RDJqNTFSYWNNZ3VJOVUrUEkzbHJ5WXh2NWlWcXdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM4NzE1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKU2NYRGJKVWdnMzY2dWVjNGZ3YWpFZWhlUzZYeXAzTXN3NmM2bVAvYjFQb2t0OE1YNG9NV0o1NVlJMmZKSmdVVFllUkRkaGFlejVDUzlFY1NwTHRoQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmd1Rm9SOWRndHBhbHN5MHFTckV3RzJ1SVlIdDhaY1FYakYxcWJrSnp2TTJFZUhmUHYvUDcvMk1yMVhxanRNZlJtTTlOeFJaVU1ZL1VEd0k3R1lxVmdjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzM4MzAzNTY4CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKcnJHOFBDdFRwZUtTY0h0c0JSSTVMT2RPM0s1aXlVcEdtYjVxK0VTVFNzZDlKRnJJZG14dkxtSkFmb0diNUZrZmJ2SjNkcm5HMDFpbFJzN2RacXB1QUE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v4.0.3/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnFwY0ZBWEZiWGtRcVVkOTZHMWY5K2hJMG1VVHA5OXFvRUlBbExXNTdWcUJabzluL0tGTXNkR2xjTDQxSlp4TXY2S015NGRmUmliRWZTaVI2ZDhvREFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM5MjYzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKanA4TVZqRHgycGpKVGJyZEk4WEtoMndOYmN3dnl0ZEdTeGpBTkZmVEx6R1o1bThIcVdHVlpROG1YamplVVpERHgyQkoxamt0TE9Ua3RhZ1RVU3VhQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_aarch64.app.tar.gz" + }, + "darwin-aarch64-app": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnFwY0ZBWEZiWGtRcVVkOTZHMWY5K2hJMG1VVHA5OXFvRUlBbExXNTdWcUJabzluL0tGTXNkR2xjTDQxSlp4TXY2S015NGRmUmliRWZTaVI2ZDhvREFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM5MjYzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKanA4TVZqRHgycGpKVGJyZEk4WEtoMndOYmN3dnl0ZEdTeGpBTkZmVEx6R1o1bThIcVdHVlpROG1YamplVVpERHgyQkoxamt0TE9Ua3RhZ1RVU3VhQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_aarch64.app.tar.gz" } } } \ No newline at end of file From 136291022a532db5967616be8e0453bb96b52cba Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 27 Jan 2026 19:53:08 +0530 Subject: [PATCH 722/864] feat: electron migration in linux scaffolding --- package.json | 6 +- src-build/serveForPlatform.js | 11 + src-electron/main-app-ipc.js | 124 +++++ src-electron/main-fs-ipc.js | 128 ++++++ src-electron/main.js | 89 ++++ src-electron/package-lock.json | 801 +++++++++++++++++++++++++++++++++ src-electron/package.json | 11 + src-electron/preload.js | 66 +++ 8 files changed, 1234 insertions(+), 2 deletions(-) create mode 100644 src-build/serveForPlatform.js create mode 100644 src-electron/main-app-ipc.js create mode 100644 src-electron/main-fs-ipc.js create mode 100644 src-electron/main.js create mode 100644 src-electron/package-lock.json create mode 100644 src-electron/package.json create mode 100644 src-electron/preload.js diff --git a/package.json b/package.json index 863999fb..24a5f899 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,9 @@ "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", "_ci-update-phcode-build": "node src-build/update-phcode-build.js", "_watch_src-node": "chokidar '../phoenix/src-node/**/*' --ignore '../phoenix/src-node/node_modules/**/*' -c 'npm run _make_src-node_debug_dev'", - "serve": "npm run _servePhoenix && npm run _make_src-node && tauri dev", + "serve": "node src-build/serveForPlatform.js", + "_serveTauri": "npm run _servePhoenix && npm run _make_src-node && tauri dev", + "_serveElectron": "npm run _servePhoenix && npm run _make_src-node && ./src-electron/node_modules/.bin/electron src-electron/main.js", "postinstall": "node ./src-build/downloadNodeBinary.js", "cleanNodeBinary": "node src-build/cleanNodeBinary.js", "installNodeArmDarwin": "node ./src-build/downloadNodeBinary.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", @@ -56,4 +58,4 @@ "branch": "tauri", "commit": "23987dad9240266fd297cbb99202178a3f68a6b2" } -} \ No newline at end of file +} diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js new file mode 100644 index 00000000..ac915d47 --- /dev/null +++ b/src-build/serveForPlatform.js @@ -0,0 +1,11 @@ +import {getPlatformDetails} from "./utils.js"; +import {execa} from "execa"; + +const {platform} = getPlatformDetails(); + +// Linux uses Electron, Windows/Mac use Tauri +const serveScript = (platform === "linux") ? "_serveElectron" : "_serveTauri"; + +console.log(`Platform: ${platform}, running: npm run ${serveScript}`); + +await execa("npm", ["run", serveScript], {stdio: "inherit"}); diff --git a/src-electron/main-app-ipc.js b/src-electron/main-app-ipc.js new file mode 100644 index 00000000..82b8a47c --- /dev/null +++ b/src-electron/main-app-ipc.js @@ -0,0 +1,124 @@ +const { app, ipcMain } = require('electron'); +const { spawn } = require('child_process'); +const readline = require('readline'); +const { productName } = require('./package.json'); + +let processInstanceId = 0; +// Map of instanceId -> { process, terminated } +const spawnedProcesses = new Map(); + +function waitForTrue(fn, timeout) { + return new Promise((resolve) => { + const startTime = Date.now(); + function check() { + if (fn()) { + resolve(true); + } else if (Date.now() - startTime > timeout) { + resolve(false); + } else { + setTimeout(check, 50); + } + } + check(); + }); +} + +async function terminateAllProcesses() { + for (const [, instance] of spawnedProcesses) { + if (!instance.terminated) { + try { + instance.process.kill(); + } catch (e) { + // Process may already be terminated + } + + await waitForTrue(() => instance.terminated, 1000); + } + } +} + +function registerAppIpcHandlers() { + // Spawn a child process and forward stdio to the calling renderer. + // Returns an instanceId so the renderer can target the correct process. + ipcMain.handle('spawn-process', async (event, command, args) => { + const instanceId = ++processInstanceId; + const sender = event.sender; + console.log(`Spawning: ${command} ${args.join(' ')} (instance ${instanceId})`); + + const childProcess = spawn(command, args, { + stdio: ['pipe', 'pipe', 'pipe'] + }); + + const instance = { process: childProcess, terminated: false }; + spawnedProcesses.set(instanceId, instance); + + const rl = readline.createInterface({ + input: childProcess.stdout, + crlfDelay: Infinity + }); + + rl.on('line', (line) => { + if (!sender.isDestroyed()) { + sender.send('process-stdout', instanceId, line); + } + }); + + childProcess.stderr.on('data', (data) => { + if (!sender.isDestroyed()) { + sender.send('process-stderr', instanceId, data.toString()); + } + }); + + childProcess.on('close', (code, signal) => { + instance.terminated = true; + console.log(`Process (instance ${instanceId}) exited with code ${code} and signal ${signal}`); + if (!sender.isDestroyed()) { + sender.send('process-close', instanceId, { code, signal }); + } + }); + + childProcess.on('error', (err) => { + console.error(`Failed to start process (instance ${instanceId}):`, err); + }); + + return instanceId; + }); + + // Write data to a specific spawned process stdin + ipcMain.handle('write-to-process', (event, instanceId, data) => { + const instance = spawnedProcesses.get(instanceId); + if (instance && !instance.terminated) { + instance.process.stdin.write(data); + } + }); + + ipcMain.handle('quit-app', (event, exitCode) => { + console.log('Quit requested with exit code:', exitCode); + // This will be handled by the main module's gracefulShutdown + app.emit('quit-requested', exitCode); + }); + + ipcMain.on('console-log', (event, message) => { + console.log('Renderer:', message); + }); + + // CLI args (mirrors Tauri's cli.getMatches for --quit-when-done / -q) + ipcMain.handle('get-cli-args', () => { + return process.argv; + }); + + // App path (repo root when running from source) + ipcMain.handle('get-app-path', () => { + return app.getAppPath(); + }); + + // App name from package.json + ipcMain.handle('get-app-name', () => { + return productName; + }); +} + +module.exports = { + registerAppIpcHandlers, + terminateAllProcesses +}; diff --git a/src-electron/main-fs-ipc.js b/src-electron/main-fs-ipc.js new file mode 100644 index 00000000..d2eeb6f2 --- /dev/null +++ b/src-electron/main-fs-ipc.js @@ -0,0 +1,128 @@ +const { ipcMain, dialog, BrowserWindow } = require('electron'); +const path = require('path'); +const fsp = require('fs/promises'); +const os = require('os'); +const { identifier: APP_IDENTIFIER } = require('./package.json'); + +// Electron IPC only preserves Error.message when errors cross the IPC boundary (see +// https://github.com/electron/electron/issues/24427). To preserve error.code for FS +// operations, we catch errors and return them as plain objects {error: {code, message}}. +// The preload layer unwraps these back into proper Error objects. +function fsResult(promise) { + return promise.catch(err => { + return { __fsError: true, code: err.code, message: err.message }; + }); +} + +/** + * Returns the app's local data directory path with trailing separator. + * Matches Tauri's appLocalDataDir which uses the bundle identifier. + * - Linux: ~/.local/share/{APP_IDENTIFIER}/ + * - macOS: ~/Library/Application Support/{APP_IDENTIFIER}/ + * - Windows: %LOCALAPPDATA%/{APP_IDENTIFIER}/ + */ +function getAppDataDir() { + const home = os.homedir(); + let appDataDir; + switch (process.platform) { + case 'darwin': + appDataDir = path.join(home, 'Library', 'Application Support', APP_IDENTIFIER); + break; + case 'win32': + appDataDir = path.join(process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local'), APP_IDENTIFIER); + break; + default: + appDataDir = path.join(process.env.XDG_DATA_HOME || path.join(home, '.local', 'share'), APP_IDENTIFIER); + } + return appDataDir + path.sep; +} + +function registerFsIpcHandlers() { + // Directory APIs + ipcMain.handle('get-documents-dir', () => { + // Match Tauri's documentDir which ends with a trailing slash + return path.join(os.homedir(), 'Documents') + path.sep; + }); + + ipcMain.handle('get-home-dir', () => { + // Match Tauri's homeDir which ends with a trailing slash + const home = os.homedir(); + return home.endsWith(path.sep) ? home : home + path.sep; + }); + + ipcMain.handle('get-temp-dir', () => { + return os.tmpdir(); + }); + + ipcMain.handle('get-app-data-dir', () => getAppDataDir()); + + // Get Windows drive letters (returns null on non-Windows platforms) + ipcMain.handle('get-windows-drives', async () => { + if (process.platform !== 'win32') { + return null; + } + // On Windows, check which drive letters exist by testing A-Z + const drives = []; + for (let i = 65; i <= 90; i++) { // A-Z + const letter = String.fromCharCode(i); + const drivePath = `${letter}:\\`; + try { + await fsp.access(drivePath); + drives.push(letter); + } catch { + // Drive doesn't exist + } + } + return drives.length > 0 ? drives : null; + }); + + // Dialogs + ipcMain.handle('show-open-dialog', async (event, options) => { + const win = BrowserWindow.fromWebContents(event.sender); + const result = await dialog.showOpenDialog(win, options); + return result.filePaths; + }); + + ipcMain.handle('show-save-dialog', async (event, options) => { + const win = BrowserWindow.fromWebContents(event.sender); + const result = await dialog.showSaveDialog(win, options); + return result.filePath; + }); + + // FS operations + ipcMain.handle('fs-readdir', async (event, dirPath) => { + return fsResult( + fsp.readdir(dirPath, { withFileTypes: true }) + .then(entries => entries.map(e => ({ name: e.name, isDirectory: e.isDirectory() }))) + ); + }); + + ipcMain.handle('fs-stat', async (event, filePath) => { + return fsResult( + fsp.stat(filePath).then(stats => ({ + isFile: stats.isFile(), + isDirectory: stats.isDirectory(), + isSymbolicLink: stats.isSymbolicLink(), + size: stats.size, + mode: stats.mode, + ctimeMs: stats.ctimeMs, + atimeMs: stats.atimeMs, + mtimeMs: stats.mtimeMs, + nlink: stats.nlink, + dev: stats.dev + })) + ); + }); + + ipcMain.handle('fs-mkdir', (event, dirPath, options) => fsResult(fsp.mkdir(dirPath, options))); + ipcMain.handle('fs-unlink', (event, filePath) => fsResult(fsp.unlink(filePath))); + ipcMain.handle('fs-rmdir', (event, dirPath, options) => fsResult(fsp.rm(dirPath, options))); + ipcMain.handle('fs-rename', (event, oldPath, newPath) => fsResult(fsp.rename(oldPath, newPath))); + ipcMain.handle('fs-read-file', (event, filePath) => fsResult(fsp.readFile(filePath))); + ipcMain.handle('fs-write-file', (event, filePath, data) => fsResult(fsp.writeFile(filePath, Buffer.from(data)))); +} + +module.exports = { + registerFsIpcHandlers, + getAppDataDir +}; diff --git a/src-electron/main.js b/src-electron/main.js new file mode 100644 index 00000000..161f5737 --- /dev/null +++ b/src-electron/main.js @@ -0,0 +1,89 @@ +const { app, BrowserWindow, protocol } = require('electron'); +const path = require('path'); + +const { registerAppIpcHandlers, terminateAllProcesses } = require('./main-app-ipc'); +const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); + +let mainWindow; + +async function createWindow() { + mainWindow = new BrowserWindow({ + width: 1200, + height: 800, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + contextIsolation: true, + nodeIntegration: false + }, + icon: path.join(__dirname, '..', 'src-tauri', 'icons', 'icon.png') + }); + + // Load the test page from the http-server + mainWindow.loadURL('http://localhost:8000/src/'); + + // Open DevTools for debugging + mainWindow.webContents.openDevTools(); + + mainWindow.on('closed', () => { + mainWindow = null; + }); +} + +async function gracefulShutdown(exitCode = 0) { + console.log('Initiating graceful shutdown...'); + await terminateAllProcesses(); + app.exit(exitCode); +} + +// Register all IPC handlers +registerAppIpcHandlers(); +registerFsIpcHandlers(); + +// Handle quit request from renderer +app.on('quit-requested', (exitCode) => { + gracefulShutdown(exitCode); +}); + +app.whenReady().then(async () => { + // Register asset:// protocol for serving local files from appLocalData/assets/ + const appDataDir = getAppDataDir(); + const assetsDir = path.join(appDataDir, 'assets'); + + protocol.registerFileProtocol('asset', (request, callback) => { + try { + const url = new URL(request.url); + // Decode the path from URL encoding + const requestedPath = decodeURIComponent(url.pathname.substring(1)); // Remove leading / + const normalizedRequested = path.normalize(requestedPath); + const normalizedAssetsDir = path.normalize(assetsDir); + + // Security: Ensure path is under assets directory (prevent directory traversal) + if (!normalizedRequested.startsWith(normalizedAssetsDir)) { + console.error('Asset access denied - path not under assets dir:', requestedPath); + callback({ error: -10 }); // net::ERR_ACCESS_DENIED + return; + } + + callback({ path: normalizedRequested }); + } catch (err) { + console.error('Asset protocol error:', err); + callback({ error: -2 }); // net::ERR_FAILED + } + }); + + await createWindow(); +}); + +app.on('window-all-closed', () => { + gracefulShutdown(0); +}); + +app.on('activate', () => { + if (BrowserWindow.getAllWindows().length === 0) { + createWindow(); + } +}); + +// Handle process termination signals +process.on('SIGINT', () => gracefulShutdown(0)); +process.on('SIGTERM', () => gracefulShutdown(0)); diff --git a/src-electron/package-lock.json b/src-electron/package-lock.json new file mode 100644 index 00000000..e8f4879d --- /dev/null +++ b/src-electron/package-lock.json @@ -0,0 +1,801 @@ +{ + "name": "phoenix-fs-electron-shell", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "phoenix-fs-electron-shell", + "version": "1.0.0", + "devDependencies": { + "electron": "^40.0.0" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "24.10.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz", + "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==", + "dev": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "optional": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "optional": true + }, + "node_modules/electron": { + "version": "40.0.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-40.0.0.tgz", + "integrity": "sha512-UyBy5yJ0/wm4gNugCtNPjvddjAknMTuXR2aCHioXicH7aKRKGDBPp4xqTEi/doVcB3R+MN3wfU9o8d/9pwgK2A==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^24.9.0", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "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, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true, + "optional": true + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "optional": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "dev": true + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "optional": true + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "dev": true, + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "dev": true, + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "optional": true + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "dev": true, + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "optional": true + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "dev": true, + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + } + } +} diff --git a/src-electron/package.json b/src-electron/package.json new file mode 100644 index 00000000..4ecda03d --- /dev/null +++ b/src-electron/package.json @@ -0,0 +1,11 @@ +{ + "name": "phoenix-code-electron-shell", + "identifier": "io.phcode.dev-electon-migration", + "version": "5.0.5", + "productName": "Phoenix Code Experimental Build", + "description": "Phoenix Code Experimental Build", + "main": "main.js", + "devDependencies": { + "electron": "^40.0.0" + } +} diff --git a/src-electron/preload.js b/src-electron/preload.js new file mode 100644 index 00000000..166ca2cf --- /dev/null +++ b/src-electron/preload.js @@ -0,0 +1,66 @@ +const { contextBridge, ipcRenderer } = require('electron'); + +contextBridge.exposeInMainWorld('electronAppAPI', { + // App info + getAppName: () => ipcRenderer.invoke('get-app-name'), + getAppPath: () => ipcRenderer.invoke('get-app-path'), + + // Process lifecycle + spawnProcess: (command, args) => ipcRenderer.invoke('spawn-process', command, args), + writeToProcess: (instanceId, data) => ipcRenderer.invoke('write-to-process', instanceId, data), + onProcessStdout: (callback) => ipcRenderer.on('process-stdout', (_event, instanceId, line) => callback(instanceId, line)), + onProcessStderr: (callback) => ipcRenderer.on('process-stderr', (_event, instanceId, line) => callback(instanceId, line)), + onProcessClose: (callback) => ipcRenderer.on('process-close', (_event, instanceId, data) => callback(instanceId, data)), + + // Quit the app with an exit code (for CI) + quitApp: (exitCode) => ipcRenderer.invoke('quit-app', exitCode), + + // Log to main process console + consoleLog: (message) => ipcRenderer.send('console-log', message), + + // Flag to identify Electron environment + isElectron: true, + + // CLI + getCliArgs: () => ipcRenderer.invoke('get-cli-args') +}); + +// the electronFSAPI is the fn that you need to copy to your election app impl for the fs to work. +contextBridge.exposeInMainWorld('electronFSAPI', { + // Path utilities + path: { + sep: process.platform === 'win32' ? '\\' : '/' + }, + documentDir: () => ipcRenderer.invoke('get-documents-dir'), + homeDir: () => ipcRenderer.invoke('get-home-dir'), + tempDir: () => ipcRenderer.invoke('get-temp-dir'), + appLocalDataDir: () => ipcRenderer.invoke('get-app-data-dir'), + getWindowsDrives: () => ipcRenderer.invoke('get-windows-drives'), + showOpenDialog: (options) => ipcRenderer.invoke('show-open-dialog', options), + showSaveDialog: (options) => ipcRenderer.invoke('show-save-dialog', options), + + // FS operations — results may be {__fsError, code, message} on failure since + // Electron IPC strips Error.code. The renderer (fslib_electron.js) handles unwrapping. + fsReaddir: (path) => ipcRenderer.invoke('fs-readdir', path), + fsStat: (path) => ipcRenderer.invoke('fs-stat', path), + fsMkdir: (path, options) => ipcRenderer.invoke('fs-mkdir', path, options), + fsUnlink: (path) => ipcRenderer.invoke('fs-unlink', path), + fsRmdir: (path, options) => ipcRenderer.invoke('fs-rmdir', path, options), + fsRename: (oldPath, newPath) => ipcRenderer.invoke('fs-rename', oldPath, newPath), + fsReadFile: (path) => ipcRenderer.invoke('fs-read-file', path), + fsWriteFile: (path, data) => ipcRenderer.invoke('fs-write-file', path, data) +}); + +// Phoenix-specific Electron APIs (not part of the copy-paste FS library) +contextBridge.exposeInMainWorld('electronAPI', { + // Asset URL conversion - converts platform path to asset:// URL + // Only allows paths under appLocalData/assets/ directory for security + // The actual path validation happens in the protocol handler in main.js + // Returns null if platformPath is falsy + convertToAssetURL: (platformPath) => { + if (!platformPath) return null; + // Normalize path separators to forward slashes for URL + const normalizedPath = platformPath.replace(/\\/g, '/'); + return `asset://localhost/${encodeURIComponent(normalizedPath)}`; + } +}); From 2b7442291a4d1ac3537f4621f16fa7a4623844c7 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 27 Jan 2026 20:11:44 +0530 Subject: [PATCH 723/864] chore: add electron apis needed by phoenix --- src-electron/main-app-ipc.js | 18 ++++++++++++++++++ src-electron/preload.js | 9 ++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src-electron/main-app-ipc.js b/src-electron/main-app-ipc.js index 82b8a47c..f85e5476 100644 --- a/src-electron/main-app-ipc.js +++ b/src-electron/main-app-ipc.js @@ -7,6 +7,10 @@ let processInstanceId = 0; // Map of instanceId -> { process, terminated } const spawnedProcesses = new Map(); +// In-memory key-value store shared across all windows (mirrors Tauri's put_item/get_all_items) +// Used for multi-window storage synchronization +const sharedStorageMap = new Map(); + function waitForTrue(fn, timeout) { return new Promise((resolve) => { const startTime = Date.now(); @@ -116,6 +120,20 @@ function registerAppIpcHandlers() { ipcMain.handle('get-app-name', () => { return productName; }); + + // Set zoom factor on the webview (mirrors Tauri's zoom_window) + ipcMain.handle('zoom-window', (event, scaleFactor) => { + event.sender.setZoomFactor(scaleFactor); + }); + + // In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) + ipcMain.handle('put-item', (event, key, value) => { + sharedStorageMap.set(key, value); + }); + + ipcMain.handle('get-all-items', () => { + return Object.fromEntries(sharedStorageMap); + }); } module.exports = { diff --git a/src-electron/preload.js b/src-electron/preload.js index 166ca2cf..9f9e29ea 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -62,5 +62,12 @@ contextBridge.exposeInMainWorld('electronAPI', { // Normalize path separators to forward slashes for URL const normalizedPath = platformPath.replace(/\\/g, '/'); return `asset://localhost/${encodeURIComponent(normalizedPath)}`; - } + }, + + // Set zoom factor on the webview (mirrors Tauri's zoom_window) + zoomWindow: (scaleFactor) => ipcRenderer.invoke('zoom-window', scaleFactor), + + // In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) + putItem: (key, value) => ipcRenderer.invoke('put-item', key, value), + getAllItems: () => ipcRenderer.invoke('get-all-items') }); From 9b5087863e80b8372bbd17e47554b30a9f4b5d5b Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 07:34:50 +0530 Subject: [PATCH 724/864] chore: remove linux tauri bundling scripts as we moving to electron in linux --- .github/workflows/tauri-build-dev.yml | 1 - .github/workflows/tauri-build-prod.yml | 1 - .github/workflows/tauri-build-staging.yml | 1 - package.json | 1 - src-build/ci-disableBundleConfig.js | 29 ----------------------- 5 files changed, 33 deletions(-) delete mode 100644 src-build/ci-disableBundleConfig.js diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 3bc19fe7..a40dba80 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -315,7 +315,6 @@ jobs: run: | npm ci npm run _ci-release:dev - npm run _ci-disableBundleConfig npm run tauri build ls -alh ./src-tauri/target/release mkdir ./src-tauri/target/release/phoenix-code diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 897d0636..bae17a32 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -363,7 +363,6 @@ jobs: run: | npm ci npm run _ci-release:prod - npm run _ci-disableBundleConfig npm run tauri build ls -alh ./src-tauri/target/release mkdir ./src-tauri/target/release/binDist diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index fdbb2535..1adcba82 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -314,7 +314,6 @@ jobs: run: | npm ci npm run _ci-release:staging - npm run _ci-disableBundleConfig npm run tauri build ls -alh ./src-tauri/target/release mkdir ./src-tauri/target/release/phoenix-code diff --git a/package.json b/package.json index 24a5f899..cf23d88f 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ "_createDistBundleReleaseConfig": "node src-build/createDistBundleReleaseConfig.js", "_createDistTestReleaseConfig": "node src-build/createDistTestReleaseConfig.js", "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", - "_ci-disableBundleConfig": "node src-build/ci-disableBundleConfig.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", "releaseSrc": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseSrcDebug": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug --verbose", diff --git a/src-build/ci-disableBundleConfig.js b/src-build/ci-disableBundleConfig.js deleted file mode 100644 index 84350a4b..00000000 --- a/src-build/ci-disableBundleConfig.js +++ /dev/null @@ -1,29 +0,0 @@ -import {dirname, join} from "path"; -import fs from "fs"; -import {fileURLToPath} from "url"; -import os from "os"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); -async function ciCreateDistReleaseConfig() { - const tauriConfigPath = join(__dirname, '..', 'src-tauri', 'tauri.conf.json'); - - console.log("remove bundle config in tauri.conf.json", tauriConfigPath); - const configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - configJson.tauri.bundle.active = false; - configJson.tauri.updater.active = false; - if(os.platform() === 'darwin'){ - // inject macos icons - configJson.tauri.bundle.icon = [ - "icons-mac/32x32.png", - "icons-mac/128x128.png", - "icons-mac/128x128@2x.png", - "icons-mac/icon.icns", - "icons-mac/icon.ico" - ]; - } - console.log("Product name is: ", configJson.package.productName); - fs.writeFileSync(tauriConfigPath, JSON.stringify(configJson, null, 4)); -} - -await ciCreateDistReleaseConfig(); From c333465d779f5ad397b2b08d71b0c63f0d538af8 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 07:45:07 +0530 Subject: [PATCH 725/864] chore: phnode for electron --- .gitignore | 3 +++ package-lock.json | 4 ++-- src-build/downloadNodeBinary.js | 18 ++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5b4c7492..e15fb558 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,9 @@ src-tauri/phnode-* src-tauri/tauri-local.conf.json phoenix +# Electron things +src-electron/bin + node_modules dist dist-ssr diff --git a/package-lock.json b/package-lock.json index 879eebf1..f9211511 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "4.0.3", + "version": "5.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "4.0.3", + "version": "5.0.5", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.3", diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index fdc47ab5..2568517e 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -239,6 +239,24 @@ async function copyLatestNodeForBuild(platform, arch) { console.log("Error Found:", err); throw new Error(err); } + + // Also copy to src-electron/bin folder + const electronBinDir = (platform === "win") ? `${__dirname}\\..\\src-electron\\bin` : `${__dirname}/../src-electron/bin`; + const electronBinName = (platform === "win") ? "phnode.exe" : "phnode"; + const electronDestNode = (platform === "win") ? `${electronBinDir}\\${electronBinName}` : `${electronBinDir}/${electronBinName}`; + + try { + // Ensure the directory exists + if (!fs.existsSync(electronBinDir)) { + fs.mkdirSync(electronBinDir, { recursive: true }); + } + fs.copyFileSync(srcNode, electronDestNode); + console.log("File copied to src-electron/bin successfully!"); + } catch (err) { + console.log("Error copying to src-electron/bin:", err); + throw new Error(err); + } + await removeDir(fullPathOfNode); } From 194cac10f178da89cd6bef5e9b91f8e2436bfdfc Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 08:11:01 +0530 Subject: [PATCH 726/864] chore: move to node 24 --- .github/workflows/desktop-linux-test-pull.yml | 2 +- .github/workflows/desktop-mac-m1-test-pull.yml | 2 +- .github/workflows/desktop-mac-test-pull.yml | 2 +- .github/workflows/desktop-windows-test-pull.yml | 2 +- .github/workflows/prod-desktop-tests-on-pull.yml | 6 +++--- .github/workflows/staging-desktop-tests-on-pull.yml | 6 +++--- .github/workflows/tauri-build-dev.yml | 8 ++++---- .github/workflows/tauri-build-prod.yml | 8 ++++---- .github/workflows/tauri-build-staging.yml | 8 ++++---- .github/workflows/update-phcode-build.yml | 2 +- src-tauri/Cargo.lock | 2 +- 11 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index dad96d70..f1a77ef0 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -16,7 +16,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/desktop-mac-m1-test-pull.yml b/.github/workflows/desktop-mac-m1-test-pull.yml index e24527be..e2f2ae7e 100644 --- a/.github/workflows/desktop-mac-m1-test-pull.yml +++ b/.github/workflows/desktop-mac-m1-test-pull.yml @@ -18,7 +18,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/desktop-mac-test-pull.yml b/.github/workflows/desktop-mac-test-pull.yml index 4cbbe2ff..314f3418 100644 --- a/.github/workflows/desktop-mac-test-pull.yml +++ b/.github/workflows/desktop-mac-test-pull.yml @@ -16,7 +16,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/desktop-windows-test-pull.yml b/.github/workflows/desktop-windows-test-pull.yml index fc641988..7a0d58d0 100644 --- a/.github/workflows/desktop-windows-test-pull.yml +++ b/.github/workflows/desktop-windows-test-pull.yml @@ -16,7 +16,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml index d36b3a76..f6b153c4 100644 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ b/.github/workflows/prod-desktop-tests-on-pull.yml @@ -14,7 +14,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: @@ -129,7 +129,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: @@ -237,7 +237,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml index 5089812f..f31d55df 100644 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ b/.github/workflows/staging-desktop-tests-on-pull.yml @@ -14,7 +14,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: @@ -117,7 +117,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: @@ -213,7 +213,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install Rust stable uses: dtolnay/rust-toolchain@stable with: diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index a40dba80..c978ff1f 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -17,7 +17,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: get version run: | echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV @@ -51,7 +51,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} @@ -91,7 +91,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: Download src-node built on mac arm (Mac only) if: matrix.platform == 'macos-15-intel' @@ -291,7 +291,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: GLIBC version run: | diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index bae17a32..840757f6 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -17,7 +17,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: get version run: | echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV @@ -51,7 +51,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} @@ -91,7 +91,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: Download src-node built on mac arm (Mac only) if: matrix.platform == 'macos-15-intel' @@ -339,7 +339,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: GLIBC version run: | diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 1adcba82..ca5d28f2 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -17,7 +17,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: get version run: | echo "PACKAGE_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV @@ -51,7 +51,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} @@ -91,7 +91,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: Download src-node built on mac arm (Mac only) if: matrix.platform == 'macos-15-intel' @@ -290,7 +290,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: GLIBC version run: | diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index fe960349..e06d6c88 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -20,7 +20,7 @@ jobs: - name: setup node uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 - name: Update phcode and version env: diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 948d6931..0960b6f6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3407,7 +3407,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "4.1.1" +version = "5.0.5" dependencies = [ "aes-gcm", "backtrace", From df616fda375753e72678445fa377b5c5dd74546f Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 10:47:37 +0530 Subject: [PATCH 727/864] build: src-node injection in elelectron dev stage --- .gitignore | 1 + package-lock.json | 1 + package.json | 10 +++----- src-build/makeSrcNode.js | 50 ++++++++++++++++++++++++++++++++++++++ src-build/setupElectron.js | 12 +++++++++ src-tauri/tauri.conf.json | 3 +-- 6 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 src-build/makeSrcNode.js create mode 100644 src-build/setupElectron.js diff --git a/.gitignore b/.gitignore index e15fb558..17e19c73 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ phoenix # Electron things src-electron/bin +src-electron/src-node node_modules dist diff --git a/package-lock.json b/package-lock.json index f9211511..485f7547 100644 --- a/package-lock.json +++ b/package-lock.json @@ -453,6 +453,7 @@ "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", diff --git a/package.json b/package.json index cf23d88f..33e6dbcf 100644 --- a/package.json +++ b/package.json @@ -19,11 +19,8 @@ "releaseDistDebug": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug --verbose", "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", - "_src-node_npm_install": "cd src-tauri/src-node && npm ci --production && cd ../../ && npm run _src-node_remove_unsupported_bin", - "_src-node_remove_unsupported_bin": "shx rm -f src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-linux-*/*.musl.node src-tauri/src-node/node_modules/@lmdb/lmdb-linux-*/*.musl.node", - "_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r ../phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", - "_make_src-node_debug_dev": "npm run _make_src-node && shx rm -rf src-tauri/target/debug/src-node && shx cp -r src-tauri/src-node src-tauri/target/debug/src-node", - "_ci_make_src-node": "shx rm -rf src-tauri/src-node && shx cp -r phoenix/src-node src-tauri/src-node && npm run _src-node_npm_install", + "_make_src-node": "node ./src-build/makeSrcNode.js ../phoenix/src-node", + "_ci_make_src-node": "node ./src-build/makeSrcNode.js phoenix/src-node", "_servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", "_ci-clonePhoenixForTests": "npm run _ci-env-warn && node ./src-build/clonePhoenixForTests.js", "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm ci && npm run build && cd ..", @@ -31,11 +28,10 @@ "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", "_ci-update-phcode-build": "node src-build/update-phcode-build.js", - "_watch_src-node": "chokidar '../phoenix/src-node/**/*' --ignore '../phoenix/src-node/node_modules/**/*' -c 'npm run _make_src-node_debug_dev'", "serve": "node src-build/serveForPlatform.js", "_serveTauri": "npm run _servePhoenix && npm run _make_src-node && tauri dev", "_serveElectron": "npm run _servePhoenix && npm run _make_src-node && ./src-electron/node_modules/.bin/electron src-electron/main.js", - "postinstall": "node ./src-build/downloadNodeBinary.js", + "postinstall": "node ./src-build/downloadNodeBinary.js && node ./src-build/setupElectron.js", "cleanNodeBinary": "node src-build/cleanNodeBinary.js", "installNodeArmDarwin": "node ./src-build/downloadNodeBinary.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", "getPackageVersion": "node ./src-build/getVersion.js" diff --git a/src-build/makeSrcNode.js b/src-build/makeSrcNode.js new file mode 100644 index 00000000..5d7f3f08 --- /dev/null +++ b/src-build/makeSrcNode.js @@ -0,0 +1,50 @@ +import { execSync } from 'child_process'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// Get source path from command line argument +const srcNodeSource = process.argv[2]; +if (!srcNodeSource) { + console.error('Usage: node makeSrcNode.js '); + console.error('Example: node makeSrcNode.js ../phoenix/src-node'); + process.exit(1); +} + +const targets = [ + join(__dirname, '..', 'src-tauri', 'src-node'), + join(__dirname, '..', 'src-electron', 'src-node') +]; + +function setupTarget(srcPath, destPath) { + console.log(`\nSetting up ${destPath}...`); + + // Remove existing and copy from source + execSync(`shx rm -rf ${destPath}`, { stdio: 'inherit' }); + execSync(`shx cp -r ${srcPath} ${destPath}`, { stdio: 'inherit' }); + + // Install production dependencies + console.log('Installing production dependencies...'); + execSync('npm ci --production', { cwd: destPath, stdio: 'inherit' }); + + // Remove unsupported musl binaries + console.log('Removing unsupported musl binaries...'); + execSync(`shx rm -f ${destPath}/node_modules/@msgpackr-extract/msgpackr-extract-linux-*/*.musl.node`, { stdio: 'pipe' }); + execSync(`shx rm -f ${destPath}/node_modules/@lmdb/lmdb-linux-*/*.musl.node`, { stdio: 'pipe' }); + + console.log(`${destPath} setup complete!`); +} + +function main() { + const absoluteSrc = join(process.cwd(), srcNodeSource); + + for (const target of targets) { + setupTarget(absoluteSrc, target); + } + + console.log('\nAll targets setup successfully!'); +} + +main(); diff --git a/src-build/setupElectron.js b/src-build/setupElectron.js new file mode 100644 index 00000000..a435e87d --- /dev/null +++ b/src-build/setupElectron.js @@ -0,0 +1,12 @@ +import { execSync } from 'child_process'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const electronDir = join(__dirname, '..', 'src-electron'); + +console.log('Installing src-electron dependencies...'); +execSync('npm ci', { cwd: electronDir, stdio: 'inherit' }); +console.log('src-electron dependencies installed successfully!'); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f3a08375..00a481cf 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -2,7 +2,6 @@ "$schema": "../node_modules/@tauri-apps/cli/schema.json", "build": { "beforeBuildCommand": "", - "beforeDevCommand": "npm run _watch_src-node", "devPath": "http://localhost:8000/src/", "distDir": "../src/", "withGlobalTauri": true @@ -484,4 +483,4 @@ } ] } -} \ No newline at end of file +} From 4fc1a0854cd5de8705f3695e476a015a40fc025f Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 11:04:16 +0530 Subject: [PATCH 728/864] build: npm run serve scripts auto detect tauri/electron based on platform --- package.json | 5 ++-- src-build/serveForPlatform.js | 54 ++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 33e6dbcf..6fec18be 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "_make_src-node": "node ./src-build/makeSrcNode.js ../phoenix/src-node", "_ci_make_src-node": "node ./src-build/makeSrcNode.js phoenix/src-node", - "_servePhoenix": "echo -e \"\nEnsure to start phoenix server at http://localhost:8000 for development.\n Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\"", "_ci-clonePhoenixForTests": "npm run _ci-env-warn && node ./src-build/clonePhoenixForTests.js", "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm ci && npm run build && cd ..", "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", @@ -29,8 +28,8 @@ "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", "_ci-update-phcode-build": "node src-build/update-phcode-build.js", "serve": "node src-build/serveForPlatform.js", - "_serveTauri": "npm run _servePhoenix && npm run _make_src-node && tauri dev", - "_serveElectron": "npm run _servePhoenix && npm run _make_src-node && ./src-electron/node_modules/.bin/electron src-electron/main.js", + "serve:tauri": "node src-build/serveForPlatform.js tauri", + "serve:electron": "node src-build/serveForPlatform.js electron", "postinstall": "node ./src-build/downloadNodeBinary.js && node ./src-build/setupElectron.js", "cleanNodeBinary": "node src-build/cleanNodeBinary.js", "installNodeArmDarwin": "node ./src-build/downloadNodeBinary.js '{\"platform\":\"darwin\",\"arch\":\"arm64\"}'", diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js index ac915d47..a1e1e211 100644 --- a/src-build/serveForPlatform.js +++ b/src-build/serveForPlatform.js @@ -1,11 +1,57 @@ import {getPlatformDetails} from "./utils.js"; import {execa} from "execa"; +import chalk from "chalk"; const {platform} = getPlatformDetails(); -// Linux uses Electron, Windows/Mac use Tauri -const serveScript = (platform === "linux") ? "_serveElectron" : "_serveTauri"; +// Get target from CLI arg, or detect from platform +const cliArg = process.argv[2]; +let target; -console.log(`Platform: ${platform}, running: npm run ${serveScript}`); +if (cliArg === 'tauri' || cliArg === 'electron') { + target = cliArg; +} else if (cliArg) { + console.error(`Unknown target: ${cliArg}`); + console.error('Usage: npm run serve [tauri|electron]'); + process.exit(1); +} else { + // Auto-detect: Linux uses Electron, Windows/Mac use Tauri + target = (platform === "linux") ? "electron" : "tauri"; +} -await execa("npm", ["run", serveScript], {stdio: "inherit"}); +// Warn about non-standard platform/target combinations +const recommendedTarget = (platform === "linux") ? "electron" : "tauri"; +if (target !== recommendedTarget) { + const y = chalk.yellow; + const b = chalk.bold.yellow; + const line1 = ` Running ${target} on ${platform} is not officially supported.`; + const line2 = ` Recommended: npm run serve (auto-detects ${recommendedTarget} for ${platform})`; + const width = Math.max(50, line1.length, line2.length) + 2; + const border = '═'.repeat(width); + const pad = (str) => str + ' '.repeat(width - str.length); + + console.warn(y(`\n╔${border}╗`)); + console.warn(y('║') + b(pad(' ⚠️ NON-STANDARD PLATFORM CONFIGURATION')) + y('║')); + console.warn(y(`╠${border}╣`)); + console.warn(y('║') + y(pad(line1)) + y('║')); + console.warn(y('║') + y(pad(line2)) + y('║')); + console.warn(y(`╚${border}╝\n`)); +} + +console.log(`Platform: ${platform}, target: ${target}`); + +// Run common setup +console.log('\nEnsure to start phoenix server at http://localhost:8000 for development.'); +console.log('Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\n'); + +console.log('Setting up src-node...'); +await execa("npm", ["run", "_make_src-node"], {stdio: "inherit"}); + +// Run platform-specific command +if (target === "tauri") { + console.log('Starting Tauri dev server...'); + await execa("npx", ["tauri", "dev"], {stdio: "inherit"}); +} else { + console.log('Starting Electron...'); + await execa("./src-electron/node_modules/.bin/electron", ["src-electron/main.js"], {stdio: "inherit"}); +} From d0b11bc044d8f067f32dd689adaf3f762305d4fc Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 28 Jan 2026 06:21:17 +0000 Subject: [PATCH 729/864] ci: update phcode version to 5.1.0 --- package.json | 6 +++--- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 6fec18be..05680f56 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.0.5", + "version": "5.1.0", "type": "module", "scripts": { "tauri": "tauri", @@ -50,6 +50,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "23987dad9240266fd297cbb99202178a3f68a6b2" + "commit": "ea4c212496edbb651bed31b2a3768d2223ead900" } -} +} \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f6c6fca2..c9234140 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.0.5" +version = "5.1.0" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 00a481cf..bd8130b1 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.0.5" + "version": "5.1.0" }, "tauri": { "allowlist": { @@ -483,4 +483,4 @@ } ] } -} +} \ No newline at end of file From c466c188210907bbfb7a0ac050080fd1d6fb22e2 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 11:33:54 +0530 Subject: [PATCH 730/864] build: src-node will be directly used from phoenix repo when development not needing rebuild on node changes --- src-build/serveForPlatform.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js index a1e1e211..bc4d92da 100644 --- a/src-build/serveForPlatform.js +++ b/src-build/serveForPlatform.js @@ -1,6 +1,7 @@ import {getPlatformDetails} from "./utils.js"; import {execa} from "execa"; import chalk from "chalk"; +import {resolve} from "path"; const {platform} = getPlatformDetails(); @@ -44,14 +45,18 @@ console.log(`Platform: ${platform}, target: ${target}`); console.log('\nEnsure to start phoenix server at http://localhost:8000 for development.'); console.log('Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\n'); -console.log('Setting up src-node...'); -await execa("npm", ["run", "_make_src-node"], {stdio: "inherit"}); - // Run platform-specific command if (target === "tauri") { + console.log('Setting up src-node...'); + await execa("npm", ["run", "_make_src-node"], {stdio: "inherit"}); + console.log('Starting Tauri dev server...'); await execa("npx", ["tauri", "dev"], {stdio: "inherit"}); } else { + const srcNodePath = resolve("../phoenix/src-node"); + console.log(`Running "npm ci" in ${srcNodePath}`); + await execa("npm", ["ci"], {cwd: srcNodePath, stdio: "inherit"}); + console.log('Starting Electron...'); await execa("./src-electron/node_modules/.bin/electron", ["src-electron/main.js"], {stdio: "inherit"}); } From a6256caf401d3cac6a820febd6fa14ecc7839699 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 11:42:20 +0530 Subject: [PATCH 731/864] chore: add getPhNodePath and getSrcNodePath electron api --- src-electron/main-app-ipc.js | 20 ++++++++++++++++++++ src-electron/preload.js | 9 ++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src-electron/main-app-ipc.js b/src-electron/main-app-ipc.js index f85e5476..e8724926 100644 --- a/src-electron/main-app-ipc.js +++ b/src-electron/main-app-ipc.js @@ -1,6 +1,8 @@ const { app, ipcMain } = require('electron'); const { spawn } = require('child_process'); const readline = require('readline'); +const path = require('path'); +const fs = require('fs'); const { productName } = require('./package.json'); let processInstanceId = 0; @@ -134,6 +136,24 @@ function registerAppIpcHandlers() { ipcMain.handle('get-all-items', () => { return Object.fromEntries(sharedStorageMap); }); + + // Get path to phnode binary + ipcMain.handle('get-phnode-path', () => { + const phNodePath = path.resolve(__dirname, 'bin', 'phnode'); + if (!fs.existsSync(phNodePath)) { + throw new Error(`phnode binary does not exist: ${phNodePath}`); + } + return phNodePath; + }); + + // Get path to src-node (for development) + ipcMain.handle('get-src-node-path', () => { + const srcNodePath = path.resolve(__dirname, '..', '..', 'phoenix', 'src-node'); + if (!fs.existsSync(srcNodePath)) { + throw new Error(`src-node path does not exist: ${srcNodePath}`); + } + return srcNodePath; + }); } module.exports = { diff --git a/src-electron/preload.js b/src-electron/preload.js index 9f9e29ea..b64f2564 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -69,5 +69,12 @@ contextBridge.exposeInMainWorld('electronAPI', { // In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) putItem: (key, value) => ipcRenderer.invoke('put-item', key, value), - getAllItems: () => ipcRenderer.invoke('get-all-items') + getAllItems: () => ipcRenderer.invoke('get-all-items'), + + // Path to phnode binary (src-electron/bin/phnode) + getPhNodePath: () => ipcRenderer.invoke('get-phnode-path'), + + // Path to src-node for development (../phoenix/src-node) + // Throws if path does not exist + getSrcNodePath: () => ipcRenderer.invoke('get-src-node-path') }); From d84baf566fa941356e2ea8f99abf262821ff2421 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 14:49:18 +0530 Subject: [PATCH 732/864] refacotor: put apis properly --- src-electron/main-app-ipc.js | 43 ++++------------------------ src-electron/main-fs-ipc.js | 5 ++++ src-electron/main.js | 55 +++++++++++++++++++++++++++++++++--- src-electron/preload.js | 3 ++ 4 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src-electron/main-app-ipc.js b/src-electron/main-app-ipc.js index e8724926..9e2664c3 100644 --- a/src-electron/main-app-ipc.js +++ b/src-electron/main-app-ipc.js @@ -1,18 +1,17 @@ +/** + * IPC handlers for electronAppAPI + * Preload location: contextBridge.exposeInMainWorld('electronAppAPI', { ... }) + */ + const { app, ipcMain } = require('electron'); const { spawn } = require('child_process'); const readline = require('readline'); -const path = require('path'); -const fs = require('fs'); const { productName } = require('./package.json'); let processInstanceId = 0; // Map of instanceId -> { process, terminated } const spawnedProcesses = new Map(); -// In-memory key-value store shared across all windows (mirrors Tauri's put_item/get_all_items) -// Used for multi-window storage synchronization -const sharedStorageMap = new Map(); - function waitForTrue(fn, timeout) { return new Promise((resolve) => { const startTime = Date.now(); @@ -122,38 +121,6 @@ function registerAppIpcHandlers() { ipcMain.handle('get-app-name', () => { return productName; }); - - // Set zoom factor on the webview (mirrors Tauri's zoom_window) - ipcMain.handle('zoom-window', (event, scaleFactor) => { - event.sender.setZoomFactor(scaleFactor); - }); - - // In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) - ipcMain.handle('put-item', (event, key, value) => { - sharedStorageMap.set(key, value); - }); - - ipcMain.handle('get-all-items', () => { - return Object.fromEntries(sharedStorageMap); - }); - - // Get path to phnode binary - ipcMain.handle('get-phnode-path', () => { - const phNodePath = path.resolve(__dirname, 'bin', 'phnode'); - if (!fs.existsSync(phNodePath)) { - throw new Error(`phnode binary does not exist: ${phNodePath}`); - } - return phNodePath; - }); - - // Get path to src-node (for development) - ipcMain.handle('get-src-node-path', () => { - const srcNodePath = path.resolve(__dirname, '..', '..', 'phoenix', 'src-node'); - if (!fs.existsSync(srcNodePath)) { - throw new Error(`src-node path does not exist: ${srcNodePath}`); - } - return srcNodePath; - }); } module.exports = { diff --git a/src-electron/main-fs-ipc.js b/src-electron/main-fs-ipc.js index d2eeb6f2..ebaf0da8 100644 --- a/src-electron/main-fs-ipc.js +++ b/src-electron/main-fs-ipc.js @@ -1,3 +1,8 @@ +/** + * IPC handlers for electronFSAPI + * Preload location: contextBridge.exposeInMainWorld('electronFSAPI', { ... }) + */ + const { ipcMain, dialog, BrowserWindow } = require('electron'); const path = require('path'); const fsp = require('fs/promises'); diff --git a/src-electron/main.js b/src-electron/main.js index 161f5737..e6217996 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -1,9 +1,14 @@ -const { app, BrowserWindow, protocol } = require('electron'); +const { app, BrowserWindow, protocol, Menu, ipcMain } = require('electron'); const path = require('path'); +const fs = require('fs'); const { registerAppIpcHandlers, terminateAllProcesses } = require('./main-app-ipc'); const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); +// In-memory key-value store shared across all windows (mirrors Tauri's put_item/get_all_items) +// Used for multi-window storage synchronization +const sharedStorageMap = new Map(); + let mainWindow; async function createWindow() { @@ -21,9 +26,6 @@ async function createWindow() { // Load the test page from the http-server mainWindow.loadURL('http://localhost:8000/src/'); - // Open DevTools for debugging - mainWindow.webContents.openDevTools(); - mainWindow.on('closed', () => { mainWindow = null; }); @@ -39,12 +41,57 @@ async function gracefulShutdown(exitCode = 0) { registerAppIpcHandlers(); registerFsIpcHandlers(); +/** + * IPC handlers for electronAPI + * Preload location: contextBridge.exposeInMainWorld('electronAPI', { ... }) + */ + +// Set zoom factor on the webview (mirrors Tauri's zoom_window) +ipcMain.handle('zoom-window', (event, scaleFactor) => { + event.sender.setZoomFactor(scaleFactor); +}); + +// In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) +ipcMain.handle('put-item', (event, key, value) => { + sharedStorageMap.set(key, value); +}); + +ipcMain.handle('get-all-items', () => { + return Object.fromEntries(sharedStorageMap); +}); + +// Toggle DevTools +ipcMain.handle('toggle-dev-tools', (event) => { + event.sender.toggleDevTools(); +}); + +// Get path to phnode binary +ipcMain.handle('get-phnode-path', () => { + const phNodePath = path.resolve(__dirname, 'bin', 'phnode'); + if (!fs.existsSync(phNodePath)) { + throw new Error(`phnode binary does not exist: ${phNodePath}`); + } + return phNodePath; +}); + +// Get path to src-node (for development) +ipcMain.handle('get-src-node-path', () => { + const srcNodePath = path.resolve(__dirname, '..', '..', 'phoenix', 'src-node'); + if (!fs.existsSync(srcNodePath)) { + throw new Error(`src-node path does not exist: ${srcNodePath}`); + } + return srcNodePath; +}); + // Handle quit request from renderer app.on('quit-requested', (exitCode) => { gracefulShutdown(exitCode); }); app.whenReady().then(async () => { + // Remove default menu bar + Menu.setApplicationMenu(null); + // Register asset:// protocol for serving local files from appLocalData/assets/ const appDataDir = getAppDataDir(); const assetsDir = path.join(appDataDir, 'assets'); diff --git a/src-electron/preload.js b/src-electron/preload.js index b64f2564..2e63f7f2 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -71,6 +71,9 @@ contextBridge.exposeInMainWorld('electronAPI', { putItem: (key, value) => ipcRenderer.invoke('put-item', key, value), getAllItems: () => ipcRenderer.invoke('get-all-items'), + // Toggle DevTools + toggleDevTools: () => ipcRenderer.invoke('toggle-dev-tools'), + // Path to phnode binary (src-electron/bin/phnode) getPhNodePath: () => ipcRenderer.invoke('get-phnode-path'), From 79ffedee6d27358f5e7391a7b35801361e6e266d Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 15:40:09 +0530 Subject: [PATCH 733/864] chore: spawn error handling --- src-electron/main-app-ipc.js | 4 ++++ src-electron/preload.js | 1 + 2 files changed, 5 insertions(+) diff --git a/src-electron/main-app-ipc.js b/src-electron/main-app-ipc.js index 9e2664c3..0ba5e2fc 100644 --- a/src-electron/main-app-ipc.js +++ b/src-electron/main-app-ipc.js @@ -83,7 +83,11 @@ function registerAppIpcHandlers() { }); childProcess.on('error', (err) => { + instance.terminated = true; console.error(`Failed to start process (instance ${instanceId}):`, err); + if (!sender.isDestroyed()) { + sender.send('process-error', instanceId, { message: err.message, code: err.code }); + } }); return instanceId; diff --git a/src-electron/preload.js b/src-electron/preload.js index 2e63f7f2..3bb8e8d5 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -11,6 +11,7 @@ contextBridge.exposeInMainWorld('electronAppAPI', { onProcessStdout: (callback) => ipcRenderer.on('process-stdout', (_event, instanceId, line) => callback(instanceId, line)), onProcessStderr: (callback) => ipcRenderer.on('process-stderr', (_event, instanceId, line) => callback(instanceId, line)), onProcessClose: (callback) => ipcRenderer.on('process-close', (_event, instanceId, data) => callback(instanceId, data)), + onProcessError: (callback) => ipcRenderer.on('process-error', (_event, instanceId, err) => callback(instanceId, err)), // Quit the app with an exit code (for CI) quitApp: (exitCode) => ipcRenderer.invoke('quit-app', exitCode), From 990ec0a5135524ef33170e2957c8453cd178d659 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 16:12:42 +0530 Subject: [PATCH 734/864] feat: trust rin apis in electron edge --- src-electron/main-cred-ipc.js | 112 ++++++++++++++++++++++++++++++++++ src-electron/main.js | 6 ++ src-electron/package.json | 3 + src-electron/preload.js | 9 ++- 4 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 src-electron/main-cred-ipc.js diff --git a/src-electron/main-cred-ipc.js b/src-electron/main-cred-ipc.js new file mode 100644 index 00000000..9f823544 --- /dev/null +++ b/src-electron/main-cred-ipc.js @@ -0,0 +1,112 @@ +const { ipcMain } = require('electron'); +const crypto = require('crypto'); + +// Per-window AES trust map (mirrors Tauri's WindowAesTrust) +// Uses webContents.id which persists across page reloads but changes when window is destroyed +const windowTrustMap = new Map(); // webContentsId -> { key, iv } + +// Keytar for system keychain (libsecret on Linux, Keychain on macOS, Credential Vault on Windows) +let keytar = null; +try { + keytar = require('keytar'); +} catch (e) { + console.warn('keytar not available, credential storage will not work'); +} + +const PHOENIX_CRED_PREFIX = 'phcode_electron_'; + +function registerCredIpcHandlers() { + // Trust window AES key - can only be called once per window + ipcMain.handle('trust-window-aes-key', (event, key, iv) => { + const webContentsId = event.sender.id; + + if (windowTrustMap.has(webContentsId)) { + throw new Error('Trust has already been established for this window.'); + } + + // Validate key (64 hex chars = 32 bytes for AES-256) + if (!/^[0-9a-fA-F]{64}$/.test(key)) { + throw new Error('Invalid AES key. Must be 64 hex characters.'); + } + // Validate IV (24 hex chars = 12 bytes for AES-GCM) + if (!/^[0-9a-fA-F]{24}$/.test(iv)) { + throw new Error('Invalid IV. Must be 24 hex characters.'); + } + + windowTrustMap.set(webContentsId, { key, iv }); + console.log(`AES trust established for webContents: ${webContentsId}`); + }); + + // Remove trust - requires matching key/iv + ipcMain.handle('remove-trust-window-aes-key', (event, key, iv) => { + const webContentsId = event.sender.id; + const stored = windowTrustMap.get(webContentsId); + + if (!stored) { + throw new Error('No trust established for this window.'); + } + if (stored.key !== key || stored.iv !== iv) { + throw new Error('Provided key and IV do not match.'); + } + + windowTrustMap.delete(webContentsId); + console.log(`AES trust removed for webContents: ${webContentsId}`); + }); + + // Store credential in system keychain + ipcMain.handle('store-credential', async (event, scopeName, secretVal) => { + if (!keytar) { + throw new Error('keytar module not available.'); + } + const service = PHOENIX_CRED_PREFIX + scopeName; + await keytar.setPassword(service, process.env.USER || 'user', secretVal); + }); + + // Get credential (encrypted with window's AES key) + ipcMain.handle('get-credential', async (event, scopeName) => { + if (!keytar) { + throw new Error('keytar module not available.'); + } + + const webContentsId = event.sender.id; + const trustData = windowTrustMap.get(webContentsId); + if (!trustData) { + throw new Error('Trust needs to be established first.'); + } + + const service = PHOENIX_CRED_PREFIX + scopeName; + const credential = await keytar.getPassword(service, process.env.USER || 'user'); + if (!credential) { + return null; + } + + // Encrypt with AES-256-GCM (same as Tauri) + const keyBytes = Buffer.from(trustData.key, 'hex'); + const ivBytes = Buffer.from(trustData.iv, 'hex'); + const cipher = crypto.createCipheriv('aes-256-gcm', keyBytes, ivBytes); + let encrypted = cipher.update(credential, 'utf8', 'hex'); + encrypted += cipher.final('hex'); + const authTag = cipher.getAuthTag().toString('hex'); + + return encrypted + authTag; // Return ciphertext + authTag as hex string + }); + + // Delete credential from system keychain + ipcMain.handle('delete-credential', async (event, scopeName) => { + if (!keytar) { + throw new Error('keytar module not available.'); + } + const service = PHOENIX_CRED_PREFIX + scopeName; + await keytar.deletePassword(service, process.env.USER || 'user'); + }); +} + +// Clean up trust when window closes +function cleanupWindowTrust(webContentsId) { + if (windowTrustMap.has(webContentsId)) { + windowTrustMap.delete(webContentsId); + console.log(`AES trust auto-removed for closed webContents: ${webContentsId}`); + } +} + +module.exports = { registerCredIpcHandlers, cleanupWindowTrust }; diff --git a/src-electron/main.js b/src-electron/main.js index e6217996..8123cfc0 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -4,6 +4,7 @@ const fs = require('fs'); const { registerAppIpcHandlers, terminateAllProcesses } = require('./main-app-ipc'); const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); +const { registerCredIpcHandlers, cleanupWindowTrust } = require('./main-cred-ipc'); // In-memory key-value store shared across all windows (mirrors Tauri's put_item/get_all_items) // Used for multi-window storage synchronization @@ -26,6 +27,10 @@ async function createWindow() { // Load the test page from the http-server mainWindow.loadURL('http://localhost:8000/src/'); + mainWindow.webContents.on('destroyed', () => { + cleanupWindowTrust(mainWindow.webContents.id); + }); + mainWindow.on('closed', () => { mainWindow = null; }); @@ -40,6 +45,7 @@ async function gracefulShutdown(exitCode = 0) { // Register all IPC handlers registerAppIpcHandlers(); registerFsIpcHandlers(); +registerCredIpcHandlers(); /** * IPC handlers for electronAPI diff --git a/src-electron/package.json b/src-electron/package.json index 4ecda03d..53583ac9 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -5,6 +5,9 @@ "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", "main": "main.js", + "dependencies": { + "keytar": "^7.9.0" + }, "devDependencies": { "electron": "^40.0.0" } diff --git a/src-electron/preload.js b/src-electron/preload.js index 3bb8e8d5..cf08516d 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -80,5 +80,12 @@ contextBridge.exposeInMainWorld('electronAPI', { // Path to src-node for development (../phoenix/src-node) // Throws if path does not exist - getSrcNodePath: () => ipcRenderer.invoke('get-src-node-path') + getSrcNodePath: () => ipcRenderer.invoke('get-src-node-path'), + + // Trust ring / credential APIs + trustWindowAesKey: (key, iv) => ipcRenderer.invoke('trust-window-aes-key', key, iv), + removeTrustWindowAesKey: (key, iv) => ipcRenderer.invoke('remove-trust-window-aes-key', key, iv), + storeCredential: (scopeName, secretVal) => ipcRenderer.invoke('store-credential', scopeName, secretVal), + getCredential: (scopeName) => ipcRenderer.invoke('get-credential', scopeName), + deleteCredential: (scopeName) => ipcRenderer.invoke('delete-credential', scopeName) }); From a370086ea36a7d3861e07ae0e667aa37226979b7 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 16:16:17 +0530 Subject: [PATCH 735/864] chore: pull in missing deps --- package-lock.json | 4 +- src-electron/package-lock.json | 397 ++++++++++++++++++++++++++++++++- 2 files changed, 388 insertions(+), 13 deletions(-) diff --git a/package-lock.json b/package-lock.json index 485f7547..99aa4e7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "5.0.5", + "version": "5.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "5.0.5", + "version": "5.1.0", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.3", diff --git a/src-electron/package-lock.json b/src-electron/package-lock.json index e8f4879d..ef18303d 100644 --- a/src-electron/package-lock.json +++ b/src-electron/package-lock.json @@ -1,12 +1,15 @@ { - "name": "phoenix-fs-electron-shell", - "version": "1.0.0", + "name": "phoenix-code-electron-shell", + "version": "5.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "phoenix-fs-electron-shell", - "version": "1.0.0", + "name": "phoenix-code-electron-shell", + "version": "5.0.5", + "dependencies": { + "keytar": "^7.9.0" + }, "devDependencies": { "electron": "^40.0.0" } @@ -111,6 +114,37 @@ "@types/node": "*" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/boolean": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", @@ -119,6 +153,30 @@ "dev": true, "optional": true }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "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": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -155,6 +213,12 @@ "node": ">=8" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, "node_modules/clone-response": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", @@ -188,7 +252,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, "dependencies": { "mimic-response": "^3.1.0" }, @@ -203,7 +266,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -211,6 +273,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/defer-to-connect": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", @@ -256,6 +327,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-node": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", @@ -285,7 +365,6 @@ "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, "dependencies": { "once": "^1.4.0" } @@ -339,6 +418,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, "node_modules/extract-zip": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", @@ -368,6 +456,12 @@ "pend": "~1.2.0" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -397,6 +491,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, "node_modules/global-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", @@ -521,6 +621,38 @@ "node": ">=10.19.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -543,6 +675,17 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -583,12 +726,63 @@ "node": ">=4" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.87.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.87.0.tgz", + "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "license": "MIT" + }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -615,7 +809,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -635,6 +828,32 @@ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -648,7 +867,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", - "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -666,6 +884,35 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", @@ -702,6 +949,26 @@ "node": ">=8.0" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -734,6 +1001,51 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "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": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -741,6 +1053,24 @@ "dev": true, "optional": true }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sumchecker": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", @@ -753,6 +1083,46 @@ "node": ">= 8.0" } }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/type-fest": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", @@ -781,11 +1151,16 @@ "node": ">= 4.0.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/yauzl": { "version": "2.10.0", From b0b1f0fcbbee7922de640e8fd4e8befbf90c4e76 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 16:40:54 +0530 Subject: [PATCH 736/864] feat: window management/label apis for electron --- src-electron/main-window-ipc.js | 97 +++++++++++++++++++++++++++++++++ src-electron/main.js | 5 ++ src-electron/preload.js | 10 +++- 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src-electron/main-window-ipc.js diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js new file mode 100644 index 00000000..1485a1c8 --- /dev/null +++ b/src-electron/main-window-ipc.js @@ -0,0 +1,97 @@ +const { ipcMain, BrowserWindow } = require('electron'); +const path = require('path'); + +const PHOENIX_WINDOW_PREFIX = 'phcode-'; +const PHOENIX_EXTENSION_WINDOW_PREFIX = 'extn-'; +const MAX_WINDOWS = 30; + +// Window registry: windowLabel -> BrowserWindow +const windowRegistry = new Map(); +// Reverse lookup: webContentsId -> windowLabel +const webContentsToLabel = new Map(); + +function getNextLabel(prefix) { + for (let i = 1; i <= MAX_WINDOWS; i++) { + const label = `${prefix}${i}`; + if (!windowRegistry.has(label)) { + return label; + } + } + throw new Error(`No free window label available for prefix: ${prefix}`); +} + +function registerWindow(win, label) { + windowRegistry.set(label, win); + webContentsToLabel.set(win.webContents.id, label); + + win.on('closed', () => { + windowRegistry.delete(label); + webContentsToLabel.delete(win.webContents.id); + }); +} + +function registerWindowIpcHandlers() { + // Get all window labels (mirrors Tauri's _get_window_labels) + ipcMain.handle('get-window-labels', () => { + return Array.from(windowRegistry.keys()); + }); + + // Get current window's label + ipcMain.handle('get-current-window-label', (event) => { + return webContentsToLabel.get(event.sender.id) || null; + }); + + // Create new window (mirrors openURLInPhoenixWindow for Electron) + ipcMain.handle('create-phoenix-window', async (event, url, options) => { + const { windowTitle, fullscreen, resizable, height, minHeight, width, minWidth, isExtension } = options || {}; + + const prefix = isExtension ? PHOENIX_EXTENSION_WINDOW_PREFIX : PHOENIX_WINDOW_PREFIX; + const label = getNextLabel(prefix); + + const win = new BrowserWindow({ + width: width || 1366, + height: height || 900, + minWidth: minWidth || 800, + minHeight: minHeight || 600, + fullscreen: fullscreen || false, + resizable: resizable !== false, + title: windowTitle || label, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + contextIsolation: true, + nodeIntegration: false + } + }); + + registerWindow(win, label); + await win.loadURL(url); + + return label; + }); + + // Close current window + ipcMain.handle('close-window', async (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + win.close(); + } + }); + + // Quit app (for last window scenario) + ipcMain.handle('quit-app', (event, exitCode) => { + const { app } = require('electron'); + app.exit(exitCode || 0); + }); + + // Focus current window + ipcMain.handle('focus-window', (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + win.setAlwaysOnTop(true); + win.focus(); + win.setAlwaysOnTop(false); + } + }); +} + +module.exports = { registerWindowIpcHandlers, registerWindow, windowRegistry }; diff --git a/src-electron/main.js b/src-electron/main.js index 8123cfc0..517c825b 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -5,6 +5,7 @@ const fs = require('fs'); const { registerAppIpcHandlers, terminateAllProcesses } = require('./main-app-ipc'); const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); const { registerCredIpcHandlers, cleanupWindowTrust } = require('./main-cred-ipc'); +const { registerWindowIpcHandlers, registerWindow } = require('./main-window-ipc'); // In-memory key-value store shared across all windows (mirrors Tauri's put_item/get_all_items) // Used for multi-window storage synchronization @@ -24,6 +25,9 @@ async function createWindow() { icon: path.join(__dirname, '..', 'src-tauri', 'icons', 'icon.png') }); + // Register main window with label 'main' (mirrors Tauri's window labeling) + registerWindow(mainWindow, 'main'); + // Load the test page from the http-server mainWindow.loadURL('http://localhost:8000/src/'); @@ -46,6 +50,7 @@ async function gracefulShutdown(exitCode = 0) { registerAppIpcHandlers(); registerFsIpcHandlers(); registerCredIpcHandlers(); +registerWindowIpcHandlers(); /** * IPC handlers for electronAPI diff --git a/src-electron/preload.js b/src-electron/preload.js index cf08516d..d09e6a0b 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -87,5 +87,13 @@ contextBridge.exposeInMainWorld('electronAPI', { removeTrustWindowAesKey: (key, iv) => ipcRenderer.invoke('remove-trust-window-aes-key', key, iv), storeCredential: (scopeName, secretVal) => ipcRenderer.invoke('store-credential', scopeName, secretVal), getCredential: (scopeName) => ipcRenderer.invoke('get-credential', scopeName), - deleteCredential: (scopeName) => ipcRenderer.invoke('delete-credential', scopeName) + deleteCredential: (scopeName) => ipcRenderer.invoke('delete-credential', scopeName), + + // Window management APIs (mirrors Tauri's window labeling scheme) + getWindowLabels: () => ipcRenderer.invoke('get-window-labels'), + getCurrentWindowLabel: () => ipcRenderer.invoke('get-current-window-label'), + createPhoenixWindow: (url, options) => ipcRenderer.invoke('create-phoenix-window', url, options), + closeWindow: () => ipcRenderer.invoke('close-window'), + quitApp: (exitCode) => ipcRenderer.invoke('quit-app', exitCode), + focusWindow: () => ipcRenderer.invoke('focus-window') }); From f66543ea9d32136a40bb738710109b8468a4d972 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 16:46:21 +0530 Subject: [PATCH 737/864] chore: focus window the electron way --- src-electron/main-window-ipc.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 1485a1c8..4a53d01f 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -83,13 +83,16 @@ function registerWindowIpcHandlers() { app.exit(exitCode || 0); }); - // Focus current window + // Focus current window and bring to front ipcMain.handle('focus-window', (event) => { const win = BrowserWindow.fromWebContents(event.sender); if (win) { - win.setAlwaysOnTop(true); + if (win.isMinimized()) { + win.restore(); + } + win.moveTop(); + win.show(); win.focus(); - win.setAlwaysOnTop(false); } }); } From 31186d0436d05db9d8386ee2ee87c562f22acaaa Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 17:13:14 +0530 Subject: [PATCH 738/864] shell api migration to electron --- src-electron/main-window-ipc.js | 151 +++++++++++++++++++++++++++++++- src-electron/preload.js | 31 ++++++- 2 files changed, 179 insertions(+), 3 deletions(-) diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 4a53d01f..79fcec4f 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -1,5 +1,6 @@ -const { ipcMain, BrowserWindow } = require('electron'); +const { ipcMain, BrowserWindow, shell, clipboard } = require('electron'); const path = require('path'); +const { spawn } = require('child_process'); const PHOENIX_WINDOW_PREFIX = 'phcode-'; const PHOENIX_EXTENSION_WINDOW_PREFIX = 'extn-'; @@ -20,6 +21,9 @@ function getNextLabel(prefix) { throw new Error(`No free window label available for prefix: ${prefix}`); } +// Track close handlers per window +const windowCloseHandlers = new Map(); + function registerWindow(win, label) { windowRegistry.set(label, win); webContentsToLabel.set(win.webContents.id, label); @@ -27,6 +31,17 @@ function registerWindow(win, label) { win.on('closed', () => { windowRegistry.delete(label); webContentsToLabel.delete(win.webContents.id); + windowCloseHandlers.delete(win.webContents.id); + }); +} + +function setupCloseHandler(win) { + win.on('close', (event) => { + const hasHandler = windowCloseHandlers.get(win.webContents.id); + if (hasHandler && !win.forceClose) { + event.preventDefault(); + win.webContents.send('close-requested'); + } }); } @@ -95,6 +110,138 @@ function registerWindowIpcHandlers() { win.focus(); } }); + + // Get process ID + ipcMain.handle('get-process-id', () => { + return process.pid; + }); + + // Get platform architecture + ipcMain.handle('get-platform-arch', () => { + return process.arch; + }); + + // Get current working directory + ipcMain.handle('get-cwd', () => { + return process.cwd(); + }); + + // Fullscreen APIs + ipcMain.handle('is-fullscreen', (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + return win ? win.isFullScreen() : false; + }); + + ipcMain.handle('set-fullscreen', (event, enable) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + win.setFullScreen(enable); + } + }); + + // Window title APIs + ipcMain.handle('set-window-title', (event, title) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + win.setTitle(title); + } + }); + + ipcMain.handle('get-window-title', (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + return win ? win.getTitle() : ''; + }); + + // Clipboard APIs + ipcMain.handle('clipboard-read-text', () => { + return clipboard.readText(); + }); + + ipcMain.handle('clipboard-write-text', (event, text) => { + clipboard.writeText(text); + }); + + // Read file paths from clipboard (platform-specific) + ipcMain.handle('clipboard-read-files', () => { + const formats = clipboard.availableFormats(); + + // Windows: FileNameW format contains file paths + if (process.platform === 'win32' && formats.includes('FileNameW')) { + const buffer = clipboard.readBuffer('FileNameW'); + // FileNameW is null-terminated UTF-16LE string + const paths = buffer.toString('utf16le').split('\0').filter(p => p.length > 0); + return paths; + } + + // macOS: public.file-url format + if (process.platform === 'darwin') { + // Try reading as file URLs + const text = clipboard.read('public.file-url'); + if (text) { + // Convert file:// URLs to paths + const paths = text.split('\n') + .filter(url => url.startsWith('file://')) + .map(url => decodeURIComponent(url.replace('file://', ''))); + if (paths.length > 0) { + return paths; + } + } + } + + // Linux: text/uri-list format + if (process.platform === 'linux' && formats.includes('text/uri-list')) { + const text = clipboard.read('text/uri-list'); + if (text) { + const paths = text.split('\n') + .filter(url => url.startsWith('file://')) + .map(url => decodeURIComponent(url.replace('file://', ''))); + if (paths.length > 0) { + return paths; + } + } + } + + return null; + }); + + // Shell APIs + ipcMain.handle('move-to-trash', async (event, platformPath) => { + await shell.trashItem(platformPath); + }); + + ipcMain.handle('show-in-folder', (event, platformPath) => { + shell.showItemInFolder(platformPath); + }); + + ipcMain.handle('open-external', async (event, url) => { + await shell.openExternal(url); + }); + + // Windows-only: open URL in specific browser (fire and forget) + ipcMain.handle('open-url-in-browser-win', (event, url, browser) => { + if (process.platform !== 'win32') { + throw new Error('open-url-in-browser-win is only supported on Windows'); + } + spawn('cmd', ['/c', 'start', browser, url], { shell: true, detached: true, stdio: 'ignore' }); + }); + + // Register close handler for current window + ipcMain.handle('register-close-handler', (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + windowCloseHandlers.set(win.webContents.id, true); + setupCloseHandler(win); + } + }); + + // Allow close after handler approves + ipcMain.handle('allow-close', (event) => { + const win = BrowserWindow.fromWebContents(event.sender); + if (win) { + win.forceClose = true; + win.close(); + } + }); } -module.exports = { registerWindowIpcHandlers, registerWindow, windowRegistry }; +module.exports = { registerWindowIpcHandlers, registerWindow, setupCloseHandler, windowRegistry }; diff --git a/src-electron/preload.js b/src-electron/preload.js index d09e6a0b..2cc4aeac 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -95,5 +95,34 @@ contextBridge.exposeInMainWorld('electronAPI', { createPhoenixWindow: (url, options) => ipcRenderer.invoke('create-phoenix-window', url, options), closeWindow: () => ipcRenderer.invoke('close-window'), quitApp: (exitCode) => ipcRenderer.invoke('quit-app', exitCode), - focusWindow: () => ipcRenderer.invoke('focus-window') + focusWindow: () => ipcRenderer.invoke('focus-window'), + + // Process and platform info + getProcessId: () => ipcRenderer.invoke('get-process-id'), + getPlatformArch: () => ipcRenderer.invoke('get-platform-arch'), + getCwd: () => ipcRenderer.invoke('get-cwd'), + + // Fullscreen APIs + isFullscreen: () => ipcRenderer.invoke('is-fullscreen'), + setFullscreen: (enable) => ipcRenderer.invoke('set-fullscreen', enable), + + // Window title APIs + setWindowTitle: (title) => ipcRenderer.invoke('set-window-title', title), + getWindowTitle: () => ipcRenderer.invoke('get-window-title'), + + // Clipboard APIs + clipboardReadText: () => ipcRenderer.invoke('clipboard-read-text'), + clipboardWriteText: (text) => ipcRenderer.invoke('clipboard-write-text', text), + clipboardReadFiles: () => ipcRenderer.invoke('clipboard-read-files'), + + // Shell APIs + moveToTrash: (platformPath) => ipcRenderer.invoke('move-to-trash', platformPath), + showInFolder: (platformPath) => ipcRenderer.invoke('show-in-folder', platformPath), + openExternal: (url) => ipcRenderer.invoke('open-external', url), + openUrlInBrowserWin: (url, browser) => ipcRenderer.invoke('open-url-in-browser-win', url, browser), + + // Close requested handler + onCloseRequested: (callback) => ipcRenderer.on('close-requested', () => callback()), + registerCloseHandler: () => ipcRenderer.invoke('register-close-handler'), + allowClose: () => ipcRenderer.invoke('allow-close') }); From cdd1ed38d26883ba26813f82256b18d8cf597f5a Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 17:23:22 +0530 Subject: [PATCH 739/864] docs: for keeping sync with phoenix-fs repo --- src-electron/main-app-ipc.js | 3 +++ src-electron/main-fs-ipc.js | 3 +++ src-electron/preload.js | 11 ++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src-electron/main-app-ipc.js b/src-electron/main-app-ipc.js index 0ba5e2fc..d4b7151c 100644 --- a/src-electron/main-app-ipc.js +++ b/src-electron/main-app-ipc.js @@ -1,6 +1,9 @@ /** * IPC handlers for electronAppAPI * Preload location: contextBridge.exposeInMainWorld('electronAppAPI', { ... }) + * + * NOTE: This file is copied from phoenix-fs library. Do not modify without + * updating the source library. Only add new Phoenix-specific handlers to main-window-ipc.js. */ const { app, ipcMain } = require('electron'); diff --git a/src-electron/main-fs-ipc.js b/src-electron/main-fs-ipc.js index ebaf0da8..0c32c1a7 100644 --- a/src-electron/main-fs-ipc.js +++ b/src-electron/main-fs-ipc.js @@ -1,6 +1,9 @@ /** * IPC handlers for electronFSAPI * Preload location: contextBridge.exposeInMainWorld('electronFSAPI', { ... }) + * + * NOTE: This file is copied from phoenix-fs library. Do not modify without + * updating the source library. Only add new Phoenix-specific handlers to main-window-ipc.js. */ const { ipcMain, dialog, BrowserWindow } = require('electron'); diff --git a/src-electron/preload.js b/src-electron/preload.js index 2cc4aeac..a3163856 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -1,5 +1,10 @@ const { contextBridge, ipcRenderer } = require('electron'); +/** + * electronAppAPI - Process lifecycle and app info APIs + * NOTE: This API block is copied from phoenix-fs library. Do not modify without + * updating the source library. Only add new Phoenix-specific APIs to electronAPI below. + */ contextBridge.exposeInMainWorld('electronAppAPI', { // App info getAppName: () => ipcRenderer.invoke('get-app-name'), @@ -26,7 +31,11 @@ contextBridge.exposeInMainWorld('electronAppAPI', { getCliArgs: () => ipcRenderer.invoke('get-cli-args') }); -// the electronFSAPI is the fn that you need to copy to your election app impl for the fs to work. +/** + * electronFSAPI - File system APIs + * NOTE: This API block is copied from phoenix-fs library. Do not modify without + * updating the source library. Only add new Phoenix-specific APIs to electronAPI below. + */ contextBridge.exposeInMainWorld('electronFSAPI', { // Path utilities path: { From 2bbe17ccfb6deecfad49a975b0e72ecfa3ae8d6c Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 17:44:07 +0530 Subject: [PATCH 740/864] chore: single window handling in electron --- src-electron/main.js | 26 ++++++++++++++++++++++++++ src-electron/preload.js | 5 ++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src-electron/main.js b/src-electron/main.js index 517c825b..60ba172d 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -7,6 +7,14 @@ const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); const { registerCredIpcHandlers, cleanupWindowTrust } = require('./main-cred-ipc'); const { registerWindowIpcHandlers, registerWindow } = require('./main-window-ipc'); +// Request single instance lock - only one instance of the app should run at a time +const gotTheLock = app.requestSingleInstanceLock(); + +if (!gotTheLock) { + // Another instance is running, quit this one immediately + app.quit(); +} + // In-memory key-value store shared across all windows (mirrors Tauri's put_item/get_all_items) // Used for multi-window storage synchronization const sharedStorageMap = new Map(); @@ -99,6 +107,20 @@ app.on('quit-requested', (exitCode) => { gracefulShutdown(exitCode); }); +// Handle second instance attempts - forward args to existing windows +app.on('second-instance', (event, commandLine, workingDirectory) => { + // Forward to all windows via IPC + // Window focusing is handled by the renderer's singleInstanceHandler + BrowserWindow.getAllWindows().forEach(win => { + if (!win.isDestroyed()) { + win.webContents.send('single-instance', { + args: commandLine, + cwd: workingDirectory + }); + } + }); +}); + app.whenReady().then(async () => { // Remove default menu bar Menu.setApplicationMenu(null); @@ -136,6 +158,10 @@ app.on('window-all-closed', () => { gracefulShutdown(0); }); +// macOS: When dock icon is clicked and no windows are open, create a new window. +// Currently this won't fire because window-all-closed quits the app. If macOS support +// is added and we want apps to stay running with no windows, change window-all-closed +// to not quit on macOS (process.platform !== 'darwin'). app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); diff --git a/src-electron/preload.js b/src-electron/preload.js index a3163856..7f9ed57c 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -133,5 +133,8 @@ contextBridge.exposeInMainWorld('electronAPI', { // Close requested handler onCloseRequested: (callback) => ipcRenderer.on('close-requested', () => callback()), registerCloseHandler: () => ipcRenderer.invoke('register-close-handler'), - allowClose: () => ipcRenderer.invoke('allow-close') + allowClose: () => ipcRenderer.invoke('allow-close'), + + // Single instance event listener (mirrors Tauri's single-instance event) + onSingleInstance: (callback) => ipcRenderer.on('single-instance', (_event, payload) => callback(payload)) }); From 04c8f659f70417bbb0253d0fa9c2310018a3d37e Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 17:49:36 +0530 Subject: [PATCH 741/864] chore: release aes trust on window close --- src-electron/main-window-ipc.js | 10 +++++++--- src-electron/main.js | 19 +++++-------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 79fcec4f..2ab7dfa6 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -1,6 +1,7 @@ const { ipcMain, BrowserWindow, shell, clipboard } = require('electron'); const path = require('path'); const { spawn } = require('child_process'); +const { cleanupWindowTrust } = require('./main-cred-ipc'); const PHOENIX_WINDOW_PREFIX = 'phcode-'; const PHOENIX_EXTENSION_WINDOW_PREFIX = 'extn-'; @@ -25,13 +26,16 @@ function getNextLabel(prefix) { const windowCloseHandlers = new Map(); function registerWindow(win, label) { + const webContentsId = win.webContents.id; windowRegistry.set(label, win); - webContentsToLabel.set(win.webContents.id, label); + webContentsToLabel.set(webContentsId, label); win.on('closed', () => { windowRegistry.delete(label); - webContentsToLabel.delete(win.webContents.id); - windowCloseHandlers.delete(win.webContents.id); + webContentsToLabel.delete(webContentsId); + windowCloseHandlers.delete(webContentsId); + // Clean up AES trust for closing window (mirrors Tauri's on_window_event CloseRequested handler) + cleanupWindowTrust(webContentsId); }); } diff --git a/src-electron/main.js b/src-electron/main.js index 60ba172d..3abba022 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -4,7 +4,7 @@ const fs = require('fs'); const { registerAppIpcHandlers, terminateAllProcesses } = require('./main-app-ipc'); const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); -const { registerCredIpcHandlers, cleanupWindowTrust } = require('./main-cred-ipc'); +const { registerCredIpcHandlers } = require('./main-cred-ipc'); const { registerWindowIpcHandlers, registerWindow } = require('./main-window-ipc'); // Request single instance lock - only one instance of the app should run at a time @@ -19,10 +19,8 @@ if (!gotTheLock) { // Used for multi-window storage synchronization const sharedStorageMap = new Map(); -let mainWindow; - async function createWindow() { - mainWindow = new BrowserWindow({ + const win = new BrowserWindow({ width: 1200, height: 800, webPreferences: { @@ -34,18 +32,11 @@ async function createWindow() { }); // Register main window with label 'main' (mirrors Tauri's window labeling) - registerWindow(mainWindow, 'main'); + // Trust cleanup is handled by registerWindow's closed handler + registerWindow(win, 'main'); // Load the test page from the http-server - mainWindow.loadURL('http://localhost:8000/src/'); - - mainWindow.webContents.on('destroyed', () => { - cleanupWindowTrust(mainWindow.webContents.id); - }); - - mainWindow.on('closed', () => { - mainWindow = null; - }); + win.loadURL('http://localhost:8000/src/'); } async function gracefulShutdown(exitCode = 0) { From 12eeb0cbeae1b974606b259985c7aaab54174aa7 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 18:16:33 +0530 Subject: [PATCH 742/864] fix: electron app launching but not working --- src-electron/main-window-ipc.js | 6 ------ src-electron/main.js | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 2ab7dfa6..daf4bcba 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -96,12 +96,6 @@ function registerWindowIpcHandlers() { } }); - // Quit app (for last window scenario) - ipcMain.handle('quit-app', (event, exitCode) => { - const { app } = require('electron'); - app.exit(exitCode || 0); - }); - // Focus current window and bring to front ipcMain.handle('focus-window', (event) => { const win = BrowserWindow.fromWebContents(event.sender); diff --git a/src-electron/main.js b/src-electron/main.js index 3abba022..4ece3f11 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -35,6 +35,9 @@ async function createWindow() { // Trust cleanup is handled by registerWindow's closed handler registerWindow(win, 'main'); + // uncomment line below if you want to open dev tools at app start + // win.webContents.openDevTools(); + // Load the test page from the http-server win.loadURL('http://localhost:8000/src/'); } From 15814042ae57ee1b96bf6d169c882b5ef720f89c Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 18:52:02 +0530 Subject: [PATCH 743/864] chore: add file/folder drop support apis --- src-electron/preload.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src-electron/preload.js b/src-electron/preload.js index 7f9ed57c..c32409c1 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -1,4 +1,4 @@ -const { contextBridge, ipcRenderer } = require('electron'); +const { contextBridge, ipcRenderer, webUtils } = require('electron'); /** * electronAppAPI - Process lifecycle and app info APIs @@ -136,5 +136,8 @@ contextBridge.exposeInMainWorld('electronAPI', { allowClose: () => ipcRenderer.invoke('allow-close'), // Single instance event listener (mirrors Tauri's single-instance event) - onSingleInstance: (callback) => ipcRenderer.on('single-instance', (_event, payload) => callback(payload)) + onSingleInstance: (callback) => ipcRenderer.on('single-instance', (_event, payload) => callback(payload)), + + // Drag and drop: get native file path from a dropped File object + getPathForFile: (file) => webUtils.getPathForFile(file) }); From 57280d5d73a6fa344d6e1c8888788181543f0e9a Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 21:53:13 +0530 Subject: [PATCH 744/864] ci: update cargo deps --- src-tauri/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0960b6f6..d0cd12aa 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3407,7 +3407,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "5.0.5" +version = "5.1.0" dependencies = [ "aes-gcm", "backtrace", From 90bfe7d133e30864eea0bb0e6b2f3b2f912008a0 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 22:36:04 +0530 Subject: [PATCH 745/864] fix: electron main files always open when starting app in editor due to cli args parsing --- src-electron/main-app-ipc.js | 30 ++++++++++++++++++++++++++++-- src-electron/main.js | 6 ++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src-electron/main-app-ipc.js b/src-electron/main-app-ipc.js index d4b7151c..cdc74c04 100644 --- a/src-electron/main-app-ipc.js +++ b/src-electron/main-app-ipc.js @@ -9,9 +9,33 @@ const { app, ipcMain } = require('electron'); const { spawn } = require('child_process'); const readline = require('readline'); +const path = require('path'); const { productName } = require('./package.json'); let processInstanceId = 0; + +// Path to main.js - used to filter it out from CLI args in dev mode +const mainScriptPath = path.resolve(__dirname, 'main.js'); + +/** + * Filter CLI args to remove internal Electron arguments. + * In dev mode, process.argv includes: [electron, main.js, ...userArgs] + * In production, it includes: [app, ...userArgs] + * This function filters out the main.js entry point in dev mode. + */ +function filterCliArgs(args) { + if (!args || args.length === 0) { + return args; + } + + const normalizedMainScript = mainScriptPath.toLowerCase(); + + return args.filter(arg => { + // Resolve to handle both absolute and relative paths + const resolvedArg = path.resolve(arg).toLowerCase(); + return resolvedArg !== normalizedMainScript; + }); +} // Map of instanceId -> { process, terminated } const spawnedProcesses = new Map(); @@ -115,8 +139,9 @@ function registerAppIpcHandlers() { }); // CLI args (mirrors Tauri's cli.getMatches for --quit-when-done / -q) + // Filter out internal Electron args (main.js in dev mode) ipcMain.handle('get-cli-args', () => { - return process.argv; + return filterCliArgs(process.argv); }); // App path (repo root when running from source) @@ -132,5 +157,6 @@ function registerAppIpcHandlers() { module.exports = { registerAppIpcHandlers, - terminateAllProcesses + terminateAllProcesses, + filterCliArgs }; diff --git a/src-electron/main.js b/src-electron/main.js index 4ece3f11..6b7105d0 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -2,7 +2,7 @@ const { app, BrowserWindow, protocol, Menu, ipcMain } = require('electron'); const path = require('path'); const fs = require('fs'); -const { registerAppIpcHandlers, terminateAllProcesses } = require('./main-app-ipc'); +const { registerAppIpcHandlers, terminateAllProcesses, filterCliArgs } = require('./main-app-ipc'); const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); const { registerCredIpcHandlers } = require('./main-cred-ipc'); const { registerWindowIpcHandlers, registerWindow } = require('./main-window-ipc'); @@ -105,10 +105,12 @@ app.on('quit-requested', (exitCode) => { app.on('second-instance', (event, commandLine, workingDirectory) => { // Forward to all windows via IPC // Window focusing is handled by the renderer's singleInstanceHandler + // Filter out internal electron args (executable and main.js script) + const filteredArgs = filterCliArgs(commandLine); BrowserWindow.getAllWindows().forEach(win => { if (!win.isDestroyed()) { win.webContents.send('single-instance', { - args: commandLine, + args: filteredArgs, cwd: workingDirectory }); } From 31090627d22088c16046bcf6ad9fdd545b06fbef Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 28 Jan 2026 22:44:44 +0530 Subject: [PATCH 746/864] chore: move to the actual dev location --- src-electron/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-electron/package.json b/src-electron/package.json index 53583ac9..7f2ace90 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -1,6 +1,6 @@ { "name": "phoenix-code-electron-shell", - "identifier": "io.phcode.dev-electon-migration", + "identifier": "io.phcode.dev", "version": "5.0.5", "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", From 620c7275ab8beeaf1b22e70af720bb94cfb7d268 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 08:34:34 +0530 Subject: [PATCH 747/864] chore: during dev npm install is preferred to pull in node deps in src-node --- src-build/serveForPlatform.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js index bc4d92da..dc8db303 100644 --- a/src-build/serveForPlatform.js +++ b/src-build/serveForPlatform.js @@ -54,8 +54,8 @@ if (target === "tauri") { await execa("npx", ["tauri", "dev"], {stdio: "inherit"}); } else { const srcNodePath = resolve("../phoenix/src-node"); - console.log(`Running "npm ci" in ${srcNodePath}`); - await execa("npm", ["ci"], {cwd: srcNodePath, stdio: "inherit"}); + console.log(`Running "npm install" in ${srcNodePath}`); + await execa("npm", ["install"], {cwd: srcNodePath, stdio: "inherit"}); console.log('Starting Electron...'); await execa("./src-electron/node_modules/.bin/electron", ["src-electron/main.js"], {stdio: "inherit"}); From 2c7195feaad878d61457a916884f39842b4aca67 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 09:12:20 +0530 Subject: [PATCH 748/864] chore: harden electron security --- src-electron/config.js | 51 +++++++++++++++++++ src-electron/ipc-security.js | 90 +++++++++++++++++++++++++++++++++ src-electron/main-app-ipc.js | 16 ++++-- src-electron/main-cred-ipc.js | 6 +++ src-electron/main-fs-ipc.js | 54 +++++++++++++++----- src-electron/main-window-ipc.js | 67 +++++++++++++++++++----- src-electron/main.js | 13 +++-- src-electron/package.json | 2 + 8 files changed, 268 insertions(+), 31 deletions(-) create mode 100644 src-electron/config.js create mode 100644 src-electron/ipc-security.js diff --git a/src-electron/config.js b/src-electron/config.js new file mode 100644 index 00000000..4d3047fb --- /dev/null +++ b/src-electron/config.js @@ -0,0 +1,51 @@ +/** + * Centralized Configuration Module + * + * This module provides a single source of truth for all configuration values. + * It reads from package.json and can apply stage-wise transforms as needed. + * + * Usage: + * const { stage, trustedElectronDomains, productName } = require('./config'); + */ + +const packageJson = require('./package.json'); + +// Core package.json values +const name = packageJson.name; +const identifier = packageJson.identifier; +const stage = packageJson.stage; +const version = packageJson.version; +const productName = packageJson.productName; +const description = packageJson.description; + +// Security configuration +const trustedElectronDomains = packageJson.trustedElectronDomains || []; + +/** + * Initialize configuration (call once at app startup if needed). + * Currently a no-op but can be extended for async config loading, + * environment variable overrides, or stage-wise transforms. + */ +function initConfig() { + // Future: Add stage-wise transforms, env overrides, etc. + // Example: + // if (stage === 'prod') { + // // Apply production-specific config + // } +} + +module.exports = { + // Package info + name, + identifier, + stage, + version, + productName, + description, + + // Security + trustedElectronDomains, + + // Initialization + initConfig +}; diff --git a/src-electron/ipc-security.js b/src-electron/ipc-security.js new file mode 100644 index 00000000..d92365e2 --- /dev/null +++ b/src-electron/ipc-security.js @@ -0,0 +1,90 @@ +/** + * IPC Security - Trusted Domain Validation + * + * This module implements security measures to ensure Electron APIs are only + * accessible from trusted origins. Trust is evaluated at window load/navigation + * time (not on every IPC call) for optimal performance. + * + * Trust rules: + * - Dev stage: trustedElectronDomains + all localhost URLs + * - Other stages (staging/prod): only trustedElectronDomains + */ + +const { stage, trustedElectronDomains } = require('./config'); + +// Track trusted webContents IDs (Set for O(1) lookup) +const _trustedWebContents = new Set(); + +/** + * Check if a URL is trusted based on stage configuration. + * - Dev stage: trustedElectronDomains + all localhost URLs + * - Other stages: only trustedElectronDomains + */ +function _isTrustedOrigin(url) { + if (!url) return false; + + // Check against trustedElectronDomains + for (const domain of trustedElectronDomains) { + if (url.startsWith(domain)) { + return true; + } + } + + // In dev stage, also allow localhost URLs + if (stage === 'dev') { + try { + const parsed = new URL(url); + if (parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1') { + return true; + } + } catch { + return false; + } + } + + return false; +} + +/** + * Mark a webContents as trusted/untrusted based on its current URL. + * Call this when window loads or navigates. + */ +function updateTrustStatus(webContents) { + const url = webContents.getURL(); + if (_isTrustedOrigin(url)) { + _trustedWebContents.add(webContents.id); + } else { + _trustedWebContents.delete(webContents.id); + } +} + +/** + * Remove trust tracking when webContents is destroyed. + */ +function cleanupTrust(webContentsId) { + _trustedWebContents.delete(webContentsId); +} + +/** + * Fast check if webContents is trusted (O(1) lookup). + */ +function _isWebContentsTrusted(webContentsId) { + return _trustedWebContents.has(webContentsId); +} + +/** + * Assert that IPC event comes from trusted webContents. + * Throws error if not trusted. + */ +function assertTrusted(event) { + if (!_isWebContentsTrusted(event.sender.id)) { + const url = event.senderFrame?.url || event.sender.getURL() || 'unknown'; + throw new Error(`Blocked IPC from untrusted origin: ${url}`); + } +} + +module.exports = { + updateTrustStatus, + cleanupTrust, + assertTrusted +}; diff --git a/src-electron/main-app-ipc.js b/src-electron/main-app-ipc.js index cdc74c04..e890e2a2 100644 --- a/src-electron/main-app-ipc.js +++ b/src-electron/main-app-ipc.js @@ -10,7 +10,8 @@ const { app, ipcMain } = require('electron'); const { spawn } = require('child_process'); const readline = require('readline'); const path = require('path'); -const { productName } = require('./package.json'); +const { productName } = require('./config'); +const { assertTrusted } = require('./ipc-security'); let processInstanceId = 0; @@ -73,6 +74,7 @@ function registerAppIpcHandlers() { // Spawn a child process and forward stdio to the calling renderer. // Returns an instanceId so the renderer can target the correct process. ipcMain.handle('spawn-process', async (event, command, args) => { + assertTrusted(event); const instanceId = ++processInstanceId; const sender = event.sender; console.log(`Spawning: ${command} ${args.join(' ')} (instance ${instanceId})`); @@ -122,6 +124,7 @@ function registerAppIpcHandlers() { // Write data to a specific spawned process stdin ipcMain.handle('write-to-process', (event, instanceId, data) => { + assertTrusted(event); const instance = spawnedProcesses.get(instanceId); if (instance && !instance.terminated) { instance.process.stdin.write(data); @@ -129,28 +132,33 @@ function registerAppIpcHandlers() { }); ipcMain.handle('quit-app', (event, exitCode) => { + assertTrusted(event); console.log('Quit requested with exit code:', exitCode); // This will be handled by the main module's gracefulShutdown app.emit('quit-requested', exitCode); }); ipcMain.on('console-log', (event, message) => { + assertTrusted(event); console.log('Renderer:', message); }); // CLI args (mirrors Tauri's cli.getMatches for --quit-when-done / -q) // Filter out internal Electron args (main.js in dev mode) - ipcMain.handle('get-cli-args', () => { + ipcMain.handle('get-cli-args', (event) => { + assertTrusted(event); return filterCliArgs(process.argv); }); // App path (repo root when running from source) - ipcMain.handle('get-app-path', () => { + ipcMain.handle('get-app-path', (event) => { + assertTrusted(event); return app.getAppPath(); }); // App name from package.json - ipcMain.handle('get-app-name', () => { + ipcMain.handle('get-app-name', (event) => { + assertTrusted(event); return productName; }); } diff --git a/src-electron/main-cred-ipc.js b/src-electron/main-cred-ipc.js index 9f823544..6b2a1c88 100644 --- a/src-electron/main-cred-ipc.js +++ b/src-electron/main-cred-ipc.js @@ -1,5 +1,6 @@ const { ipcMain } = require('electron'); const crypto = require('crypto'); +const { assertTrusted } = require('./ipc-security'); // Per-window AES trust map (mirrors Tauri's WindowAesTrust) // Uses webContents.id which persists across page reloads but changes when window is destroyed @@ -18,6 +19,7 @@ const PHOENIX_CRED_PREFIX = 'phcode_electron_'; function registerCredIpcHandlers() { // Trust window AES key - can only be called once per window ipcMain.handle('trust-window-aes-key', (event, key, iv) => { + assertTrusted(event); const webContentsId = event.sender.id; if (windowTrustMap.has(webContentsId)) { @@ -39,6 +41,7 @@ function registerCredIpcHandlers() { // Remove trust - requires matching key/iv ipcMain.handle('remove-trust-window-aes-key', (event, key, iv) => { + assertTrusted(event); const webContentsId = event.sender.id; const stored = windowTrustMap.get(webContentsId); @@ -55,6 +58,7 @@ function registerCredIpcHandlers() { // Store credential in system keychain ipcMain.handle('store-credential', async (event, scopeName, secretVal) => { + assertTrusted(event); if (!keytar) { throw new Error('keytar module not available.'); } @@ -64,6 +68,7 @@ function registerCredIpcHandlers() { // Get credential (encrypted with window's AES key) ipcMain.handle('get-credential', async (event, scopeName) => { + assertTrusted(event); if (!keytar) { throw new Error('keytar module not available.'); } @@ -93,6 +98,7 @@ function registerCredIpcHandlers() { // Delete credential from system keychain ipcMain.handle('delete-credential', async (event, scopeName) => { + assertTrusted(event); if (!keytar) { throw new Error('keytar module not available.'); } diff --git a/src-electron/main-fs-ipc.js b/src-electron/main-fs-ipc.js index 0c32c1a7..39e08614 100644 --- a/src-electron/main-fs-ipc.js +++ b/src-electron/main-fs-ipc.js @@ -10,7 +10,8 @@ const { ipcMain, dialog, BrowserWindow } = require('electron'); const path = require('path'); const fsp = require('fs/promises'); const os = require('os'); -const { identifier: APP_IDENTIFIER } = require('./package.json'); +const { identifier: APP_IDENTIFIER } = require('./config'); +const { assertTrusted } = require('./ipc-security'); // Electron IPC only preserves Error.message when errors cross the IPC boundary (see // https://github.com/electron/electron/issues/24427). To preserve error.code for FS @@ -47,25 +48,32 @@ function getAppDataDir() { function registerFsIpcHandlers() { // Directory APIs - ipcMain.handle('get-documents-dir', () => { + ipcMain.handle('get-documents-dir', (event) => { + assertTrusted(event); // Match Tauri's documentDir which ends with a trailing slash return path.join(os.homedir(), 'Documents') + path.sep; }); - ipcMain.handle('get-home-dir', () => { + ipcMain.handle('get-home-dir', (event) => { + assertTrusted(event); // Match Tauri's homeDir which ends with a trailing slash const home = os.homedir(); return home.endsWith(path.sep) ? home : home + path.sep; }); - ipcMain.handle('get-temp-dir', () => { + ipcMain.handle('get-temp-dir', (event) => { + assertTrusted(event); return os.tmpdir(); }); - ipcMain.handle('get-app-data-dir', () => getAppDataDir()); + ipcMain.handle('get-app-data-dir', (event) => { + assertTrusted(event); + return getAppDataDir(); + }); // Get Windows drive letters (returns null on non-Windows platforms) - ipcMain.handle('get-windows-drives', async () => { + ipcMain.handle('get-windows-drives', async (event) => { + assertTrusted(event); if (process.platform !== 'win32') { return null; } @@ -86,12 +94,14 @@ function registerFsIpcHandlers() { // Dialogs ipcMain.handle('show-open-dialog', async (event, options) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); const result = await dialog.showOpenDialog(win, options); return result.filePaths; }); ipcMain.handle('show-save-dialog', async (event, options) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); const result = await dialog.showSaveDialog(win, options); return result.filePath; @@ -99,6 +109,7 @@ function registerFsIpcHandlers() { // FS operations ipcMain.handle('fs-readdir', async (event, dirPath) => { + assertTrusted(event); return fsResult( fsp.readdir(dirPath, { withFileTypes: true }) .then(entries => entries.map(e => ({ name: e.name, isDirectory: e.isDirectory() }))) @@ -106,6 +117,7 @@ function registerFsIpcHandlers() { }); ipcMain.handle('fs-stat', async (event, filePath) => { + assertTrusted(event); return fsResult( fsp.stat(filePath).then(stats => ({ isFile: stats.isFile(), @@ -122,12 +134,30 @@ function registerFsIpcHandlers() { ); }); - ipcMain.handle('fs-mkdir', (event, dirPath, options) => fsResult(fsp.mkdir(dirPath, options))); - ipcMain.handle('fs-unlink', (event, filePath) => fsResult(fsp.unlink(filePath))); - ipcMain.handle('fs-rmdir', (event, dirPath, options) => fsResult(fsp.rm(dirPath, options))); - ipcMain.handle('fs-rename', (event, oldPath, newPath) => fsResult(fsp.rename(oldPath, newPath))); - ipcMain.handle('fs-read-file', (event, filePath) => fsResult(fsp.readFile(filePath))); - ipcMain.handle('fs-write-file', (event, filePath, data) => fsResult(fsp.writeFile(filePath, Buffer.from(data)))); + ipcMain.handle('fs-mkdir', (event, dirPath, options) => { + assertTrusted(event); + return fsResult(fsp.mkdir(dirPath, options)); + }); + ipcMain.handle('fs-unlink', (event, filePath) => { + assertTrusted(event); + return fsResult(fsp.unlink(filePath)); + }); + ipcMain.handle('fs-rmdir', (event, dirPath, options) => { + assertTrusted(event); + return fsResult(fsp.rm(dirPath, options)); + }); + ipcMain.handle('fs-rename', (event, oldPath, newPath) => { + assertTrusted(event); + return fsResult(fsp.rename(oldPath, newPath)); + }); + ipcMain.handle('fs-read-file', (event, filePath) => { + assertTrusted(event); + return fsResult(fsp.readFile(filePath)); + }); + ipcMain.handle('fs-write-file', (event, filePath, data) => { + assertTrusted(event); + return fsResult(fsp.writeFile(filePath, Buffer.from(data))); + }); } module.exports = { diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index daf4bcba..ab584227 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -2,6 +2,7 @@ const { ipcMain, BrowserWindow, shell, clipboard } = require('electron'); const path = require('path'); const { spawn } = require('child_process'); const { cleanupWindowTrust } = require('./main-cred-ipc'); +const { updateTrustStatus, cleanupTrust, assertTrusted } = require('./ipc-security'); const PHOENIX_WINDOW_PREFIX = 'phcode-'; const PHOENIX_EXTENSION_WINDOW_PREFIX = 'extn-'; @@ -26,16 +27,30 @@ function getNextLabel(prefix) { const windowCloseHandlers = new Map(); function registerWindow(win, label) { - const webContentsId = win.webContents.id; + const webContents = win.webContents; + const webContentsId = webContents.id; windowRegistry.set(label, win); webContentsToLabel.set(webContentsId, label); + // Initial trust evaluation + updateTrustStatus(webContents); + + // Re-evaluate trust on navigation + webContents.on('did-navigate', () => { + updateTrustStatus(webContents); + }); + webContents.on('did-navigate-in-page', () => { + updateTrustStatus(webContents); + }); + win.on('closed', () => { windowRegistry.delete(label); webContentsToLabel.delete(webContentsId); windowCloseHandlers.delete(webContentsId); // Clean up AES trust for closing window (mirrors Tauri's on_window_event CloseRequested handler) cleanupWindowTrust(webContentsId); + // Clean up security trust + cleanupTrust(webContentsId); }); } @@ -51,22 +66,36 @@ function setupCloseHandler(win) { function registerWindowIpcHandlers() { // Get all window labels (mirrors Tauri's _get_window_labels) - ipcMain.handle('get-window-labels', () => { + ipcMain.handle('get-window-labels', (event) => { + assertTrusted(event); return Array.from(windowRegistry.keys()); }); // Get current window's label ipcMain.handle('get-current-window-label', (event) => { + assertTrusted(event); return webContentsToLabel.get(event.sender.id) || null; }); // Create new window (mirrors openURLInPhoenixWindow for Electron) ipcMain.handle('create-phoenix-window', async (event, url, options) => { + assertTrusted(event); const { windowTitle, fullscreen, resizable, height, minHeight, width, minWidth, isExtension } = options || {}; const prefix = isExtension ? PHOENIX_EXTENSION_WINDOW_PREFIX : PHOENIX_WINDOW_PREFIX; const label = getNextLabel(prefix); + const webPreferences = { + contextIsolation: true, + nodeIntegration: false, + sandbox: true + }; + + // Only inject preload for Phoenix windows, not extensions + if (!isExtension) { + webPreferences.preload = path.join(__dirname, 'preload.js'); + } + const win = new BrowserWindow({ width: width || 1366, height: height || 900, @@ -75,11 +104,7 @@ function registerWindowIpcHandlers() { fullscreen: fullscreen || false, resizable: resizable !== false, title: windowTitle || label, - webPreferences: { - preload: path.join(__dirname, 'preload.js'), - contextIsolation: true, - nodeIntegration: false - } + webPreferences }); registerWindow(win, label); @@ -90,6 +115,7 @@ function registerWindowIpcHandlers() { // Close current window ipcMain.handle('close-window', async (event) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); if (win) { win.close(); @@ -98,6 +124,7 @@ function registerWindowIpcHandlers() { // Focus current window and bring to front ipcMain.handle('focus-window', (event) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); if (win) { if (win.isMinimized()) { @@ -110,27 +137,32 @@ function registerWindowIpcHandlers() { }); // Get process ID - ipcMain.handle('get-process-id', () => { + ipcMain.handle('get-process-id', (event) => { + assertTrusted(event); return process.pid; }); // Get platform architecture - ipcMain.handle('get-platform-arch', () => { + ipcMain.handle('get-platform-arch', (event) => { + assertTrusted(event); return process.arch; }); // Get current working directory - ipcMain.handle('get-cwd', () => { + ipcMain.handle('get-cwd', (event) => { + assertTrusted(event); return process.cwd(); }); // Fullscreen APIs ipcMain.handle('is-fullscreen', (event) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); return win ? win.isFullScreen() : false; }); ipcMain.handle('set-fullscreen', (event, enable) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); if (win) { win.setFullScreen(enable); @@ -139,6 +171,7 @@ function registerWindowIpcHandlers() { // Window title APIs ipcMain.handle('set-window-title', (event, title) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); if (win) { win.setTitle(title); @@ -146,21 +179,25 @@ function registerWindowIpcHandlers() { }); ipcMain.handle('get-window-title', (event) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); return win ? win.getTitle() : ''; }); // Clipboard APIs - ipcMain.handle('clipboard-read-text', () => { + ipcMain.handle('clipboard-read-text', (event) => { + assertTrusted(event); return clipboard.readText(); }); ipcMain.handle('clipboard-write-text', (event, text) => { + assertTrusted(event); clipboard.writeText(text); }); // Read file paths from clipboard (platform-specific) - ipcMain.handle('clipboard-read-files', () => { + ipcMain.handle('clipboard-read-files', (event) => { + assertTrusted(event); const formats = clipboard.availableFormats(); // Windows: FileNameW format contains file paths @@ -204,19 +241,23 @@ function registerWindowIpcHandlers() { // Shell APIs ipcMain.handle('move-to-trash', async (event, platformPath) => { + assertTrusted(event); await shell.trashItem(platformPath); }); ipcMain.handle('show-in-folder', (event, platformPath) => { + assertTrusted(event); shell.showItemInFolder(platformPath); }); ipcMain.handle('open-external', async (event, url) => { + assertTrusted(event); await shell.openExternal(url); }); // Windows-only: open URL in specific browser (fire and forget) ipcMain.handle('open-url-in-browser-win', (event, url, browser) => { + assertTrusted(event); if (process.platform !== 'win32') { throw new Error('open-url-in-browser-win is only supported on Windows'); } @@ -225,6 +266,7 @@ function registerWindowIpcHandlers() { // Register close handler for current window ipcMain.handle('register-close-handler', (event) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); if (win) { windowCloseHandlers.set(win.webContents.id, true); @@ -234,6 +276,7 @@ function registerWindowIpcHandlers() { // Allow close after handler approves ipcMain.handle('allow-close', (event) => { + assertTrusted(event); const win = BrowserWindow.fromWebContents(event.sender); if (win) { win.forceClose = true; diff --git a/src-electron/main.js b/src-electron/main.js index 6b7105d0..10272115 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -6,6 +6,7 @@ const { registerAppIpcHandlers, terminateAllProcesses, filterCliArgs } = require const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); const { registerCredIpcHandlers } = require('./main-cred-ipc'); const { registerWindowIpcHandlers, registerWindow } = require('./main-window-ipc'); +const { assertTrusted } = require('./ipc-security'); // Request single instance lock - only one instance of the app should run at a time const gotTheLock = app.requestSingleInstanceLock(); @@ -61,25 +62,30 @@ registerWindowIpcHandlers(); // Set zoom factor on the webview (mirrors Tauri's zoom_window) ipcMain.handle('zoom-window', (event, scaleFactor) => { + assertTrusted(event); event.sender.setZoomFactor(scaleFactor); }); // In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) ipcMain.handle('put-item', (event, key, value) => { + assertTrusted(event); sharedStorageMap.set(key, value); }); -ipcMain.handle('get-all-items', () => { +ipcMain.handle('get-all-items', (event) => { + assertTrusted(event); return Object.fromEntries(sharedStorageMap); }); // Toggle DevTools ipcMain.handle('toggle-dev-tools', (event) => { + assertTrusted(event); event.sender.toggleDevTools(); }); // Get path to phnode binary -ipcMain.handle('get-phnode-path', () => { +ipcMain.handle('get-phnode-path', (event) => { + assertTrusted(event); const phNodePath = path.resolve(__dirname, 'bin', 'phnode'); if (!fs.existsSync(phNodePath)) { throw new Error(`phnode binary does not exist: ${phNodePath}`); @@ -88,7 +94,8 @@ ipcMain.handle('get-phnode-path', () => { }); // Get path to src-node (for development) -ipcMain.handle('get-src-node-path', () => { +ipcMain.handle('get-src-node-path', (event) => { + assertTrusted(event); const srcNodePath = path.resolve(__dirname, '..', '..', 'phoenix', 'src-node'); if (!fs.existsSync(srcNodePath)) { throw new Error(`src-node path does not exist: ${srcNodePath}`); diff --git a/src-electron/package.json b/src-electron/package.json index 7f2ace90..2f0f3640 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -1,6 +1,8 @@ { "name": "phoenix-code-electron-shell", "identifier": "io.phcode.dev", + "stage": "dev", + "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/"], "version": "5.0.5", "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", From b68bfac5e9a8a8c12792d893f87b432f418e08cc Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 09:30:30 +0530 Subject: [PATCH 749/864] fix: newly spawned untrusted windows shouldnt have electon api injection at all --- src-electron/ipc-security.js | 5 +++-- src-electron/main-window-ipc.js | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src-electron/ipc-security.js b/src-electron/ipc-security.js index d92365e2..6d75afd1 100644 --- a/src-electron/ipc-security.js +++ b/src-electron/ipc-security.js @@ -20,7 +20,7 @@ const _trustedWebContents = new Set(); * - Dev stage: trustedElectronDomains + all localhost URLs * - Other stages: only trustedElectronDomains */ -function _isTrustedOrigin(url) { +function isTrustedOrigin(url) { if (!url) return false; // Check against trustedElectronDomains @@ -51,7 +51,7 @@ function _isTrustedOrigin(url) { */ function updateTrustStatus(webContents) { const url = webContents.getURL(); - if (_isTrustedOrigin(url)) { + if (isTrustedOrigin(url)) { _trustedWebContents.add(webContents.id); } else { _trustedWebContents.delete(webContents.id); @@ -84,6 +84,7 @@ function assertTrusted(event) { } module.exports = { + isTrustedOrigin, updateTrustStatus, cleanupTrust, assertTrusted diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index ab584227..87cc5294 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -2,7 +2,7 @@ const { ipcMain, BrowserWindow, shell, clipboard } = require('electron'); const path = require('path'); const { spawn } = require('child_process'); const { cleanupWindowTrust } = require('./main-cred-ipc'); -const { updateTrustStatus, cleanupTrust, assertTrusted } = require('./ipc-security'); +const { isTrustedOrigin, updateTrustStatus, cleanupTrust, assertTrusted } = require('./ipc-security'); const PHOENIX_WINDOW_PREFIX = 'phcode-'; const PHOENIX_EXTENSION_WINDOW_PREFIX = 'extn-'; @@ -91,8 +91,8 @@ function registerWindowIpcHandlers() { sandbox: true }; - // Only inject preload for Phoenix windows, not extensions - if (!isExtension) { + // Only inject preload for Phoenix windows with trusted URLs, not extensions + if (!isExtension && isTrustedOrigin(url)) { webPreferences.preload = path.join(__dirname, 'preload.js'); } From 472a553696669e281174bec65c76fa496281ba0c Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 11:24:56 +0530 Subject: [PATCH 750/864] chore: better logging --- src-electron/main-cred-ipc.js | 11 +++++++---- src-electron/main-window-ipc.js | 8 ++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src-electron/main-cred-ipc.js b/src-electron/main-cred-ipc.js index 6b2a1c88..cbe613cd 100644 --- a/src-electron/main-cred-ipc.js +++ b/src-electron/main-cred-ipc.js @@ -36,7 +36,9 @@ function registerCredIpcHandlers() { } windowTrustMap.set(webContentsId, { key, iv }); - console.log(`AES trust established for webContents: ${webContentsId}`); + // Lazy require to avoid circular dependency + const { getWindowLabel } = require('./main-window-ipc'); + console.log(`AES trust established for window: ${getWindowLabel(webContentsId)} (webContentsId: ${webContentsId})`); }); // Remove trust - requires matching key/iv @@ -53,7 +55,8 @@ function registerCredIpcHandlers() { } windowTrustMap.delete(webContentsId); - console.log(`AES trust removed for webContents: ${webContentsId}`); + const { getWindowLabel } = require('./main-window-ipc'); + console.log(`AES trust removed for window: ${getWindowLabel(webContentsId)} (webContentsId: ${webContentsId})`); }); // Store credential in system keychain @@ -108,10 +111,10 @@ function registerCredIpcHandlers() { } // Clean up trust when window closes -function cleanupWindowTrust(webContentsId) { +function cleanupWindowTrust(webContentsId, windowLabel) { if (windowTrustMap.has(webContentsId)) { windowTrustMap.delete(webContentsId); - console.log(`AES trust auto-removed for closed webContents: ${webContentsId}`); + console.log(`AES trust auto-removed for closed window: ${windowLabel} (webContentsId: ${webContentsId})`); } } diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 87cc5294..821302f9 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -48,7 +48,7 @@ function registerWindow(win, label) { webContentsToLabel.delete(webContentsId); windowCloseHandlers.delete(webContentsId); // Clean up AES trust for closing window (mirrors Tauri's on_window_event CloseRequested handler) - cleanupWindowTrust(webContentsId); + cleanupWindowTrust(webContentsId, label); // Clean up security trust cleanupTrust(webContentsId); }); @@ -285,4 +285,8 @@ function registerWindowIpcHandlers() { }); } -module.exports = { registerWindowIpcHandlers, registerWindow, setupCloseHandler, windowRegistry }; +function getWindowLabel(webContentsId) { + return webContentsToLabel.get(webContentsId) || 'unknown'; +} + +module.exports = { registerWindowIpcHandlers, registerWindow, setupCloseHandler, windowRegistry, getWindowLabel }; From 9296dd35000fec87dbf07525a868d610183d0448 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 12:16:35 +0530 Subject: [PATCH 751/864] feat: restore window sizes --- src-electron/main-window-ipc.js | 27 ++++- src-electron/main.js | 19 +++- src-electron/window-state.js | 189 ++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+), 6 deletions(-) create mode 100644 src-electron/window-state.js diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 821302f9..c1491b79 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -3,6 +3,7 @@ const path = require('path'); const { spawn } = require('child_process'); const { cleanupWindowTrust } = require('./main-cred-ipc'); const { isTrustedOrigin, updateTrustStatus, cleanupTrust, assertTrusted } = require('./ipc-security'); +const { DEFAULTS } = require('./window-state'); const PHOENIX_WINDOW_PREFIX = 'phcode-'; const PHOENIX_EXTENSION_WINDOW_PREFIX = 'extn-'; @@ -96,11 +97,29 @@ function registerWindowIpcHandlers() { webPreferences.preload = path.join(__dirname, 'preload.js'); } + let windowConfig; + if (isExtension) { + // Extensions manage their own sizing + windowConfig = { + width: width || 800, + height: height || 600, + minWidth: minWidth, + minHeight: minHeight + }; + } else { + // Phoenix windows: use defaults and ensure dimensions are at least the minimums + const actualMinWidth = Math.max(minWidth || DEFAULTS.minWidth, DEFAULTS.minWidth); + const actualMinHeight = Math.max(minHeight || DEFAULTS.minHeight, DEFAULTS.minHeight); + windowConfig = { + width: Math.max(width || DEFAULTS.width, actualMinWidth), + height: Math.max(height || DEFAULTS.height, actualMinHeight), + minWidth: actualMinWidth, + minHeight: actualMinHeight + }; + } + const win = new BrowserWindow({ - width: width || 1366, - height: height || 900, - minWidth: minWidth || 800, - minHeight: minHeight || 600, + ...windowConfig, fullscreen: fullscreen || false, resizable: resizable !== false, title: windowTitle || label, diff --git a/src-electron/main.js b/src-electron/main.js index 10272115..873a4a5d 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -7,6 +7,7 @@ const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); const { registerCredIpcHandlers } = require('./main-cred-ipc'); const { registerWindowIpcHandlers, registerWindow } = require('./main-window-ipc'); const { assertTrusted } = require('./ipc-security'); +const { getWindowOptions, trackWindowState, DEFAULTS } = require('./window-state'); // Request single instance lock - only one instance of the app should run at a time const gotTheLock = app.requestSingleInstanceLock(); @@ -21,9 +22,15 @@ if (!gotTheLock) { const sharedStorageMap = new Map(); async function createWindow() { + // Get window options with restored state or defaults + const windowOptions = getWindowOptions(); + const wasMaximized = windowOptions._wasMaximized; + delete windowOptions._wasMaximized; + const win = new BrowserWindow({ - width: 1200, - height: 800, + ...windowOptions, + minWidth: DEFAULTS.minWidth, + minHeight: DEFAULTS.minHeight, webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, @@ -32,6 +39,14 @@ async function createWindow() { icon: path.join(__dirname, '..', 'src-tauri', 'icons', 'icon.png') }); + // Track window state for persistence + trackWindowState(win); + + // Restore maximized state after window is ready + if (wasMaximized) { + win.maximize(); + } + // Register main window with label 'main' (mirrors Tauri's window labeling) // Trust cleanup is handled by registerWindow's closed handler registerWindow(win, 'main'); diff --git a/src-electron/window-state.js b/src-electron/window-state.js new file mode 100644 index 00000000..b0ee560e --- /dev/null +++ b/src-electron/window-state.js @@ -0,0 +1,189 @@ +/** + * Window State Manager + * + * Persists and restores window position, size, and maximized state. + * Handles multi-monitor setups and gracefully handles disconnected monitors. + */ + +const { screen } = require('electron'); +const path = require('path'); +const fs = require('fs'); +const { getAppDataDir } = require('./main-fs-ipc'); + +const STATE_FILE = 'window-state.json'; + +// Default window dimensions +const DEFAULTS = { + width: 1366, + height: 900, + minWidth: 800, + minHeight: 600 +}; + +/** + * Get the path to the window state file. + */ +function getStateFilePath() { + return path.join(getAppDataDir(), STATE_FILE); +} + +/** + * Load saved window state from disk. + * Returns null if no saved state or file is corrupted. + */ +function loadWindowState() { + try { + const filePath = getStateFilePath(); + if (!fs.existsSync(filePath)) { + return null; + } + const data = fs.readFileSync(filePath, 'utf8'); + return JSON.parse(data); + } catch (err) { + console.warn('Failed to load window state:', err.message); + return null; + } +} + +/** + * Save window state to disk. + */ +function saveWindowState(state) { + try { + const filePath = getStateFilePath(); + // Ensure directory exists + const dir = path.dirname(filePath); + if (!fs.existsSync(dir)) { + fs.mkdirSync(dir, { recursive: true }); + } + fs.writeFileSync(filePath, JSON.stringify(state, null, 2)); + } catch (err) { + console.warn('Failed to save window state:', err.message); + } +} + +/** + * Check if a rectangle is visible on any display. + * Returns true if at least a portion of the window would be visible. + */ +function isVisibleOnAnyDisplay(bounds) { + const displays = screen.getAllDisplays(); + const minVisibleArea = 100; // At least 100px visible + + for (const display of displays) { + const { x, y, width, height } = display.workArea; + + // Calculate overlap between window bounds and display work area + const overlapX = Math.max(0, Math.min(bounds.x + bounds.width, x + width) - Math.max(bounds.x, x)); + const overlapY = Math.max(0, Math.min(bounds.y + bounds.height, y + height) - Math.max(bounds.y, y)); + const overlapArea = overlapX * overlapY; + + if (overlapArea >= minVisibleArea) { + return true; + } + } + return false; +} + +/** + * Get the display nearest to a point. + */ +function getNearestDisplay(x, y) { + return screen.getDisplayNearestPoint({ x, y }); +} + +/** + * Get window options with restored state or defaults. + * Validates saved position is on a visible display. + */ +function getWindowOptions() { + const savedState = loadWindowState(); + + const options = { + width: DEFAULTS.width, + height: DEFAULTS.height, + minWidth: DEFAULTS.minWidth, + minHeight: DEFAULTS.minHeight + }; + + if (savedState) { + // Restore size (clamped to minimums) + options.width = Math.max(savedState.width || DEFAULTS.width, DEFAULTS.minWidth); + options.height = Math.max(savedState.height || DEFAULTS.height, DEFAULTS.minHeight); + + // Check if saved position is visible on any current display + if (savedState.x !== undefined && savedState.y !== undefined) { + const bounds = { + x: savedState.x, + y: savedState.y, + width: options.width, + height: options.height + }; + + if (isVisibleOnAnyDisplay(bounds)) { + // Position is valid, use it + options.x = savedState.x; + options.y = savedState.y; + } else { + // Position is off-screen (monitor disconnected?), center on nearest display + const nearestDisplay = getNearestDisplay(savedState.x, savedState.y); + const { x, y, width, height } = nearestDisplay.workArea; + options.x = x + Math.round((width - options.width) / 2); + options.y = y + Math.round((height - options.height) / 2); + console.log('Window position was off-screen, repositioned to nearest display'); + } + } + + // Track if we need to maximize after window is created + options._wasMaximized = savedState.isMaximized || false; + } + + return options; +} + +/** + * Track window state changes and save on close. + * Call this after creating the BrowserWindow. + */ +function trackWindowState(win) { + let windowState = { + width: DEFAULTS.width, + height: DEFAULTS.height, + x: undefined, + y: undefined, + isMaximized: false + }; + + // Update state from current window bounds + function updateState() { + if (!win.isMaximized() && !win.isMinimized() && !win.isFullScreen()) { + const bounds = win.getBounds(); + windowState.width = bounds.width; + windowState.height = bounds.height; + windowState.x = bounds.x; + windowState.y = bounds.y; + } + windowState.isMaximized = win.isMaximized(); + } + + // Listen for state changes + win.on('resize', updateState); + win.on('move', updateState); + win.on('maximize', updateState); + win.on('unmaximize', updateState); + + // Save state before window closes + win.on('close', () => { + updateState(); + saveWindowState(windowState); + }); + + // Initialize state + updateState(); +} + +module.exports = { + DEFAULTS, + getWindowOptions, + trackWindowState +}; From 3fc6adf03f773d268142ead1abde36af35cfdb29 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 12:27:25 +0530 Subject: [PATCH 752/864] chore: window size and position persistance --- src-electron/main-window-ipc.js | 7 +++++- src-electron/window-state.js | 42 ++++++++------------------------- 2 files changed, 16 insertions(+), 33 deletions(-) diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index c1491b79..4acd3fc3 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -3,7 +3,7 @@ const path = require('path'); const { spawn } = require('child_process'); const { cleanupWindowTrust } = require('./main-cred-ipc'); const { isTrustedOrigin, updateTrustStatus, cleanupTrust, assertTrusted } = require('./ipc-security'); -const { DEFAULTS } = require('./window-state'); +const { DEFAULTS, trackWindowState } = require('./window-state'); const PHOENIX_WINDOW_PREFIX = 'phcode-'; const PHOENIX_EXTENSION_WINDOW_PREFIX = 'extn-'; @@ -126,6 +126,11 @@ function registerWindowIpcHandlers() { webPreferences }); + // Track window state for Phoenix windows (not extensions) + if (!isExtension) { + trackWindowState(win); + } + registerWindow(win, label); await win.loadURL(url); diff --git a/src-electron/window-state.js b/src-electron/window-state.js index b0ee560e..5fdc8ec3 100644 --- a/src-electron/window-state.js +++ b/src-electron/window-state.js @@ -142,44 +142,22 @@ function getWindowOptions() { } /** - * Track window state changes and save on close. + * Track window state and save on close. * Call this after creating the BrowserWindow. */ function trackWindowState(win) { - let windowState = { - width: DEFAULTS.width, - height: DEFAULTS.height, - x: undefined, - y: undefined, - isMaximized: false - }; - - // Update state from current window bounds - function updateState() { - if (!win.isMaximized() && !win.isMinimized() && !win.isFullScreen()) { - const bounds = win.getBounds(); - windowState.width = bounds.width; - windowState.height = bounds.height; - windowState.x = bounds.x; - windowState.y = bounds.y; - } - windowState.isMaximized = win.isMaximized(); - } - - // Listen for state changes - win.on('resize', updateState); - win.on('move', updateState); - win.on('maximize', updateState); - win.on('unmaximize', updateState); - - // Save state before window closes win.on('close', () => { - updateState(); + // getNormalBounds() returns the non-maximized bounds even when maximized + const bounds = win.getNormalBounds(); + const windowState = { + width: bounds.width, + height: bounds.height, + x: bounds.x, + y: bounds.y, + isMaximized: win.isMaximized() + }; saveWindowState(windowState); }); - - // Initialize state - updateState(); } module.exports = { From b44ed392bf9833bd0dac0d1bc980a4513a78779c Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 17:16:48 +0530 Subject: [PATCH 753/864] build: dynamic electron config loading --- .gitignore | 1 + src-build/serveForPlatform.js | 8 ++++++++ src-build/setupElectron.js | 8 ++++++++ src-electron/config-prod.json | 5 +++++ src-electron/config-staging.json | 5 +++++ src-electron/config.js | 24 +++++++++++------------- src-electron/config.json | 8 ++++++++ src-electron/main.js | 5 +++-- 8 files changed, 49 insertions(+), 15 deletions(-) create mode 100644 src-electron/config-prod.json create mode 100644 src-electron/config-staging.json create mode 100644 src-electron/config.json diff --git a/.gitignore b/.gitignore index 17e19c73..169400a3 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ phoenix # Electron things src-electron/bin src-electron/src-node +src-electron/config-effective.json node_modules dist diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js index dc8db303..41ed86b2 100644 --- a/src-build/serveForPlatform.js +++ b/src-build/serveForPlatform.js @@ -2,6 +2,7 @@ import {getPlatformDetails} from "./utils.js"; import {execa} from "execa"; import chalk from "chalk"; import {resolve} from "path"; +import {copyFileSync} from "fs"; const {platform} = getPlatformDetails(); @@ -57,6 +58,13 @@ if (target === "tauri") { console.log(`Running "npm install" in ${srcNodePath}`); await execa("npm", ["install"], {cwd: srcNodePath, stdio: "inherit"}); + // Copy config.json to config-effective.json (dev config for serve) + const electronDir = resolve("src-electron"); + const configSrc = resolve(electronDir, "config.json"); + const configDest = resolve(electronDir, "config-effective.json"); + console.log('Copying config.json to config-effective.json...'); + copyFileSync(configSrc, configDest); + console.log('Starting Electron...'); await execa("./src-electron/node_modules/.bin/electron", ["src-electron/main.js"], {stdio: "inherit"}); } diff --git a/src-build/setupElectron.js b/src-build/setupElectron.js index a435e87d..77cb39a3 100644 --- a/src-build/setupElectron.js +++ b/src-build/setupElectron.js @@ -1,6 +1,7 @@ import { execSync } from 'child_process'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; +import { copyFileSync } from 'fs'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -10,3 +11,10 @@ const electronDir = join(__dirname, '..', 'src-electron'); console.log('Installing src-electron dependencies...'); execSync('npm ci', { cwd: electronDir, stdio: 'inherit' }); console.log('src-electron dependencies installed successfully!'); + +// Copy config.json to config-effective.json (dev config by default) +const configSrc = join(electronDir, 'config.json'); +const configDest = join(electronDir, 'config-effective.json'); +console.log('Copying config.json to config-effective.json...'); +copyFileSync(configSrc, configDest); +console.log('Config file copied successfully!'); diff --git a/src-electron/config-prod.json b/src-electron/config-prod.json new file mode 100644 index 00000000..38eb8914 --- /dev/null +++ b/src-electron/config-prod.json @@ -0,0 +1,5 @@ +{ + "identifier": "io.phcode", + "stage": "production", + "productName": "Phoenix Code" +} diff --git a/src-electron/config-staging.json b/src-electron/config-staging.json new file mode 100644 index 00000000..060b5f29 --- /dev/null +++ b/src-electron/config-staging.json @@ -0,0 +1,5 @@ +{ + "identifier": "io.phcode.staging", + "stage": "stage", + "productName": "Phoenix Code Pre-release" +} diff --git a/src-electron/config.js b/src-electron/config.js index 4d3047fb..c6c34a69 100644 --- a/src-electron/config.js +++ b/src-electron/config.js @@ -2,24 +2,23 @@ * Centralized Configuration Module * * This module provides a single source of truth for all configuration values. - * It reads from package.json and can apply stage-wise transforms as needed. + * It reads from config.json and can apply stage-wise transforms as needed. * * Usage: * const { stage, trustedElectronDomains, productName } = require('./config'); */ -const packageJson = require('./package.json'); +const configJson = require('./config-effective.json'); -// Core package.json values -const name = packageJson.name; -const identifier = packageJson.identifier; -const stage = packageJson.stage; -const version = packageJson.version; -const productName = packageJson.productName; -const description = packageJson.description; +// Core config values +const identifier = configJson.identifier; +const phoenixLoadURL = configJson.phoenixLoadURL; +const stage = configJson.stage; +const version = configJson.version; +const productName = configJson.productName; // Security configuration -const trustedElectronDomains = packageJson.trustedElectronDomains || []; +const trustedElectronDomains = configJson.trustedElectronDomains || []; /** * Initialize configuration (call once at app startup if needed). @@ -35,13 +34,12 @@ function initConfig() { } module.exports = { - // Package info - name, + // App info identifier, + phoenixLoadURL, stage, version, productName, - description, // Security trustedElectronDomains, diff --git a/src-electron/config.json b/src-electron/config.json new file mode 100644 index 00000000..39a63458 --- /dev/null +++ b/src-electron/config.json @@ -0,0 +1,8 @@ +{ + "identifier": "io.phcode.dev", + "phoenixLoadURL": "http://localhost:8000/src/", + "stage": "dev", + "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/"], + "version": "5.0.5", + "productName": "Phoenix Code Experimental Build" +} diff --git a/src-electron/main.js b/src-electron/main.js index 873a4a5d..64d985c3 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -8,6 +8,7 @@ const { registerCredIpcHandlers } = require('./main-cred-ipc'); const { registerWindowIpcHandlers, registerWindow } = require('./main-window-ipc'); const { assertTrusted } = require('./ipc-security'); const { getWindowOptions, trackWindowState, DEFAULTS } = require('./window-state'); +const { phoenixLoadURL } = require('./config'); // Request single instance lock - only one instance of the app should run at a time const gotTheLock = app.requestSingleInstanceLock(); @@ -54,8 +55,8 @@ async function createWindow() { // uncomment line below if you want to open dev tools at app start // win.webContents.openDevTools(); - // Load the test page from the http-server - win.loadURL('http://localhost:8000/src/'); + // Load Phoenix from configured URL + win.loadURL(phoenixLoadURL); } async function gracefulShutdown(exitCode = 0) { From 66b655a10c7c1fb5dde7cf725858085c44e57bf2 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 17:21:27 +0530 Subject: [PATCH 754/864] chore: add gaMetricsURL for electron --- src-electron/config-prod.json | 3 ++- src-electron/config-staging.json | 3 ++- src-electron/config.json | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src-electron/config-prod.json b/src-electron/config-prod.json index 38eb8914..183b1042 100644 --- a/src-electron/config-prod.json +++ b/src-electron/config-prod.json @@ -1,5 +1,6 @@ { "identifier": "io.phcode", "stage": "production", - "productName": "Phoenix Code" + "productName": "Phoenix Code", + "gaMetricsURL": "https://phcode.dev/desktop-metrics.html" } diff --git a/src-electron/config-staging.json b/src-electron/config-staging.json index 060b5f29..b97ccbb5 100644 --- a/src-electron/config-staging.json +++ b/src-electron/config-staging.json @@ -1,5 +1,6 @@ { "identifier": "io.phcode.staging", "stage": "stage", - "productName": "Phoenix Code Pre-release" + "productName": "Phoenix Code Pre-release", + "gaMetricsURL": "https://staging.phcode.dev/desktop-metrics.html" } diff --git a/src-electron/config.json b/src-electron/config.json index 39a63458..5ca03e5a 100644 --- a/src-electron/config.json +++ b/src-electron/config.json @@ -1,8 +1,9 @@ { "identifier": "io.phcode.dev", - "phoenixLoadURL": "http://localhost:8000/src/", "stage": "dev", - "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/"], "version": "5.0.5", - "productName": "Phoenix Code Experimental Build" + "productName": "Phoenix Code Experimental Build", + "phoenixLoadURL": "http://localhost:8000/src/", + "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/"], + "gaMetricsURL": "http://localhost:8000/src/desktop-metrics.html" } From bced3d52106d68822e83709b95c86769fa458d12 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 18:36:06 +0530 Subject: [PATCH 755/864] chore: elecctron health metrics migration --- src-electron/config-staging.json | 1 + src-electron/config.js | 2 ++ src-electron/main-window-ipc.js | 13 +++++++++++- src-electron/main.js | 36 ++++++++++++++++++++++++++++++-- src-electron/preload.js | 6 +++++- 5 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src-electron/config-staging.json b/src-electron/config-staging.json index b97ccbb5..9d6e4202 100644 --- a/src-electron/config-staging.json +++ b/src-electron/config-staging.json @@ -2,5 +2,6 @@ "identifier": "io.phcode.staging", "stage": "stage", "productName": "Phoenix Code Pre-release", + "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/", "https://staging.phcode.dev/"], "gaMetricsURL": "https://staging.phcode.dev/desktop-metrics.html" } diff --git a/src-electron/config.js b/src-electron/config.js index c6c34a69..dc610613 100644 --- a/src-electron/config.js +++ b/src-electron/config.js @@ -13,6 +13,7 @@ const configJson = require('./config-effective.json'); // Core config values const identifier = configJson.identifier; const phoenixLoadURL = configJson.phoenixLoadURL; +const gaMetricsURL = configJson.gaMetricsURL; const stage = configJson.stage; const version = configJson.version; const productName = configJson.productName; @@ -37,6 +38,7 @@ module.exports = { // App info identifier, phoenixLoadURL, + gaMetricsURL, stage, version, productName, diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 4acd3fc3..a7996412 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -27,6 +27,9 @@ function getNextLabel(prefix) { // Track close handlers per window const windowCloseHandlers = new Map(); +// Callback when all registered windows are closed +let onAllWindowsClosedCallback = null; + function registerWindow(win, label) { const webContents = win.webContents; const webContentsId = webContents.id; @@ -52,6 +55,10 @@ function registerWindow(win, label) { cleanupWindowTrust(webContentsId, label); // Clean up security trust cleanupTrust(webContentsId); + // Notify if all registered windows are closed + if (windowRegistry.size === 0 && onAllWindowsClosedCallback) { + onAllWindowsClosedCallback(); + } }); } @@ -313,4 +320,8 @@ function getWindowLabel(webContentsId) { return webContentsToLabel.get(webContentsId) || 'unknown'; } -module.exports = { registerWindowIpcHandlers, registerWindow, setupCloseHandler, windowRegistry, getWindowLabel }; +function setOnAllWindowsClosed(callback) { + onAllWindowsClosedCallback = callback; +} + +module.exports = { registerWindowIpcHandlers, registerWindow, getWindowLabel, setOnAllWindowsClosed }; diff --git a/src-electron/main.js b/src-electron/main.js index 64d985c3..5fd6c4f7 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -5,10 +5,10 @@ const fs = require('fs'); const { registerAppIpcHandlers, terminateAllProcesses, filterCliArgs } = require('./main-app-ipc'); const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); const { registerCredIpcHandlers } = require('./main-cred-ipc'); -const { registerWindowIpcHandlers, registerWindow } = require('./main-window-ipc'); +const { registerWindowIpcHandlers, registerWindow, setOnAllWindowsClosed } = require('./main-window-ipc'); const { assertTrusted } = require('./ipc-security'); const { getWindowOptions, trackWindowState, DEFAULTS } = require('./window-state'); -const { phoenixLoadURL } = require('./config'); +const { phoenixLoadURL, gaMetricsURL } = require('./config'); // Request single instance lock - only one instance of the app should run at a time const gotTheLock = app.requestSingleInstanceLock(); @@ -22,6 +22,25 @@ if (!gotTheLock) { // Used for multi-window storage synchronization const sharedStorageMap = new Map(); +// Hidden metrics window for Google Analytics +let metricsWindow = null; + +async function createMetricsWindow() { + metricsWindow = new BrowserWindow({ + show: false, + width: 400, + height: 300, + webPreferences: { + preload: path.join(__dirname, 'preload.js'), + contextIsolation: true, + nodeIntegration: false + } + }); + metricsWindow.loadURL(gaMetricsURL); + // uncomment line below if you want to open dev tools at app start + metricsWindow.webContents.openDevTools(); +} + async function createWindow() { // Get window options with restored state or defaults const windowOptions = getWindowOptions(); @@ -71,6 +90,11 @@ registerFsIpcHandlers(); registerCredIpcHandlers(); registerWindowIpcHandlers(); +// Quit when all registered Phoenix windows are closed (metrics window doesn't count) +setOnAllWindowsClosed(() => { + gracefulShutdown(0); +}); + /** * IPC handlers for electronAPI * Preload location: contextBridge.exposeInMainWorld('electronAPI', { ... }) @@ -119,6 +143,13 @@ ipcMain.handle('get-src-node-path', (event) => { return srcNodePath; }); +// Health metrics forwarding to hidden metrics window (no assertTrusted needed - metrics come from Phoenix windows) +ipcMain.on('send-health-metric', (event, payload) => { + if (metricsWindow && !metricsWindow.isDestroyed()) { + metricsWindow.webContents.send('health-metric', payload); + } +}); + // Handle quit request from renderer app.on('quit-requested', (exitCode) => { gracefulShutdown(exitCode); @@ -170,6 +201,7 @@ app.whenReady().then(async () => { } }); + await createMetricsWindow(); await createWindow(); }); diff --git a/src-electron/preload.js b/src-electron/preload.js index c32409c1..ce30dd2b 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -139,5 +139,9 @@ contextBridge.exposeInMainWorld('electronAPI', { onSingleInstance: (callback) => ipcRenderer.on('single-instance', (_event, payload) => callback(payload)), // Drag and drop: get native file path from a dropped File object - getPathForFile: (file) => webUtils.getPathForFile(file) + getPathForFile: (file) => webUtils.getPathForFile(file), + + // Health metrics for Google Analytics (sends to hidden metrics window) + sendHealthMetric: (payload) => ipcRenderer.send('send-health-metric', payload), + onHealthMetric: (callback) => ipcRenderer.on('health-metric', (_event, payload) => callback(payload)) }); From 964210bceb8888289de52221a12aac9eff096bd0 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 21:46:24 +0530 Subject: [PATCH 756/864] build: linux electron app image dev builds generation --- .gitignore | 1 + package.json | 1 + src-build/setupElectron.js | 6 +- src-electron/electron-builder.yml | 29 + src-electron/main.js | 25 +- src-electron/package-lock.json | 3507 +++++++++++++++++++++++++++-- src-electron/package.json | 6 +- 7 files changed, 3328 insertions(+), 247 deletions(-) create mode 100644 src-electron/electron-builder.yml diff --git a/.gitignore b/.gitignore index 169400a3..9f02bff5 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ phoenix src-electron/bin src-electron/src-node src-electron/config-effective.json +src-electron/dist node_modules dist diff --git a/package.json b/package.json index 05680f56..f7ff496a 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "_make_src-node": "node ./src-build/makeSrcNode.js ../phoenix/src-node", + "build:electron": "npm run _make_src-node && cd src-electron && npm run build:appimage", "_ci_make_src-node": "node ./src-build/makeSrcNode.js phoenix/src-node", "_ci-clonePhoenixForTests": "npm run _ci-env-warn && node ./src-build/clonePhoenixForTests.js", "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm ci && npm run build && cd ..", diff --git a/src-build/setupElectron.js b/src-build/setupElectron.js index 77cb39a3..f98cd767 100644 --- a/src-build/setupElectron.js +++ b/src-build/setupElectron.js @@ -8,8 +8,10 @@ const __dirname = dirname(__filename); const electronDir = join(__dirname, '..', 'src-electron'); -console.log('Installing src-electron dependencies...'); -execSync('npm ci', { cwd: electronDir, stdio: 'inherit' }); +// Use the same npm command that was used at root level (npm install vs npm ci) +const npmCommand = process.env.npm_command === 'install' ? 'npm install' : 'npm ci'; +console.log(`Installing src-electron dependencies with ${npmCommand}...`); +execSync(npmCommand, { cwd: electronDir, stdio: 'inherit' }); console.log('src-electron dependencies installed successfully!'); // Copy config.json to config-effective.json (dev config by default) diff --git a/src-electron/electron-builder.yml b/src-electron/electron-builder.yml new file mode 100644 index 00000000..5475de9e --- /dev/null +++ b/src-electron/electron-builder.yml @@ -0,0 +1,29 @@ +appId: io.phcode.dev +productName: Phoenix Code +copyright: Copyright © 2024 phcode.dev + +asar: true + +linux: + target: + - AppImage + category: Development + icon: ../src-tauri/icons + +files: + - "**/*" + - "!dist/**" + - "!src-node/**" + - "!bin/**" + +asarUnpack: + - "node_modules/keytar/**" + +extraResources: + - from: "src-node" + to: "src-node" + - from: "bin" + to: "bin" + +extraMetadata: + main: main.js diff --git a/src-electron/main.js b/src-electron/main.js index 5fd6c4f7..00a7a38e 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -16,6 +16,25 @@ const gotTheLock = app.requestSingleInstanceLock(); if (!gotTheLock) { // Another instance is running, quit this one immediately app.quit(); + // Return value is ignored but this stops further module execution + return; +} + +function getPhNodePath() { + if (!app.isPackaged) { + return path.resolve(__dirname, 'bin', 'phnode'); + } + // extraResources places files directly in resources/ + return path.join(process.resourcesPath, 'bin', 'phnode'); +} + +function getSrcNodePath() { + if (!app.isPackaged) { + // Dev: use phoenix repo's src-node + return path.resolve(__dirname, '..', '..', 'phoenix', 'src-node'); + } + // extraResources places files directly in resources/ + return path.join(process.resourcesPath, 'src-node'); } // In-memory key-value store shared across all windows (mirrors Tauri's put_item/get_all_items) @@ -126,17 +145,17 @@ ipcMain.handle('toggle-dev-tools', (event) => { // Get path to phnode binary ipcMain.handle('get-phnode-path', (event) => { assertTrusted(event); - const phNodePath = path.resolve(__dirname, 'bin', 'phnode'); + const phNodePath = getPhNodePath(); if (!fs.existsSync(phNodePath)) { throw new Error(`phnode binary does not exist: ${phNodePath}`); } return phNodePath; }); -// Get path to src-node (for development) +// Get path to src-node ipcMain.handle('get-src-node-path', (event) => { assertTrusted(event); - const srcNodePath = path.resolve(__dirname, '..', '..', 'phoenix', 'src-node'); + const srcNodePath = getSrcNodePath(); if (!fs.existsSync(srcNodePath)) { throw new Error(`src-node path does not exist: ${srcNodePath}`); } diff --git a/src-electron/package-lock.json b/src-electron/package-lock.json index ef18303d..d722b9ba 100644 --- a/src-electron/package-lock.json +++ b/src-electron/package-lock.json @@ -11,7 +11,68 @@ "keytar": "^7.9.0" }, "devDependencies": { - "electron": "^40.0.0" + "electron": "^40.0.0", + "electron-builder": "^24.13.3" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@electron/asar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.4.1.tgz", + "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@electron/asar/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/asar/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, "node_modules/@electron/get": { @@ -35,332 +96,1885 @@ "global-agent": "^3.0.0" } }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "node_modules/@electron/notarize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.2.1.tgz", + "integrity": "sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==", "dev": true, - "engines": { - "node": ">=10" + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "engines": { + "node": ">= 10.0.0" } }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { - "defer-to-connect": "^2.0.0" + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { "node": ">=10" } }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "node_modules/@electron/notarize/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, + "license": "MIT", "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true + "node_modules/@electron/notarize/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "node_modules/@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@types/node": "*" + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" } }, - "node_modules/@types/node": { - "version": "24.10.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz", - "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==", + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, + "license": "MIT", "dependencies": { - "undici-types": "~7.16.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", "dev": true, - "dependencies": { - "@types/node": "*" + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" } }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "node_modules/@electron/osx-sign/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "@types/node": "*" + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/base64-js": { + "node_modules/@electron/osx-sign/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/universal": { "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "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" + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.5.1.tgz", + "integrity": "sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@electron/asar": "^3.2.1", + "@malept/cross-spawn-promise": "^1.1.0", + "debug": "^4.3.1", + "dir-compare": "^3.0.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/@electron/universal/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, "license": "MIT", "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, - "optional": true + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "node_modules/@electron/universal/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { "node": "*" } }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, "engines": { - "node": ">=10.6.0" + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.9.tgz", + "integrity": "sha512-ne4A0IpG3+2ETuREInjPNhUGis1SFjv1d5asp8MzEAGtOZeTeHVDOYqOgqfhvseqg/iXty2hjBf1zAOb7RNiNw==", + "dev": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true, + "license": "MIT" + }, + "node_modules/app-builder-lib": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.13.3.tgz", + "integrity": "sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/notarize": "2.2.1", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.5.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.8", + "electron-publish": "24.13.1", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "dmg-builder": "24.13.3", + "electron-builder-squirrel-windows": "24.13.3" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "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": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builder-util": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.13.1.tgz", + "integrity": "sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.4.tgz", + "integrity": "sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/builder-util/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/config-file-ts": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.6.tgz", + "integrity": "sha512-6boGVaglwblBgJqGyxm4+xCmEGcWgnWHSWHY5jad58awQhB6gftq0G8HbzU39YqCIYHMLAiL1yjwiZ36m/CL8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.3.10", + "typescript": "^5.3.3" + } + }, + "node_modules/config-file-ts/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "optional": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "optional": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "optional": true + }, + "node_modules/dir-compare": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" + } + }, + "node_modules/dir-compare/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.13.3.tgz", + "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/dmg-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" } }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "license": "ISC" + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "mimic-response": "^1.0.0" + "jake": "^10.8.5" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/electron": { + "version": "40.0.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-40.0.0.tgz", + "integrity": "sha512-UyBy5yJ0/wm4gNugCtNPjvddjAknMTuXR2aCHioXicH7aKRKGDBPp4xqTEi/doVcB3R+MN3wfU9o8d/9pwgK2A==", "dev": true, + "hasInstallScript": true, "dependencies": { - "ms": "^2.1.3" + "@electron/get": "^2.0.0", + "@types/node": "^24.9.0", + "extract-zip": "^2.0.1" }, - "engines": { - "node": ">=6.0" + "bin": { + "electron": "cli.js" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "engines": { + "node": ">= 12.20.55" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "node_modules/electron-builder": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.13.3.tgz", + "integrity": "sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==", + "dev": true, + "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "app-builder-lib": "24.13.3", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "dmg-builder": "24.13.3", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" }, - "engines": { - "node": ">=10" + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=14.0.0" } }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node_modules/electron-builder-squirrel-windows": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-24.13.3.tgz", + "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "24.13.3", + "archiver": "^5.3.1", + "builder-util": "24.13.1", + "fs-extra": "^10.1.0" } }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, "engines": { - "node": ">=4.0.0" + "node": ">=12" } }, - "node_modules/defer-to-connect": { + "node_modules/electron-builder-squirrel-windows/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder-squirrel-windows/node_modules/universalify": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 10.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "node_modules/electron-builder/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, - "optional": true, + "license": "MIT", "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "universalify": "^2.0.0" }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", + "node_modules/electron-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 10.0.0" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "node_modules/electron-publish": { + "version": "24.13.1", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.13.1.tgz", + "integrity": "sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==", "dev": true, - "optional": true + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "24.13.1", + "builder-util-runtime": "9.2.4", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } }, - "node_modules/electron": { - "version": "40.0.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-40.0.0.tgz", - "integrity": "sha512-UyBy5yJ0/wm4gNugCtNPjvddjAknMTuXR2aCHioXicH7aKRKGDBPp4xqTEi/doVcB3R+MN3wfU9o8d/9pwgK2A==", + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "dependencies": { - "@electron/get": "^2.0.0", - "@types/node": "^24.9.0", - "extract-zip": "^2.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, - "bin": { - "electron": "cli.js" + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-publish/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 12.20.55" + "node": ">= 10.0.0" } }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", @@ -378,12 +1992,18 @@ "node": ">=6" } }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "optional": true, "engines": { "node": ">= 0.4" } @@ -393,7 +2013,35 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "optional": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, "engines": { "node": ">= 0.4" } @@ -405,6 +2053,16 @@ "dev": true, "optional": true }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -427,33 +2085,102 @@ "node": ">=6" } }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "optional": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" + "minimatch": "^5.0.1" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 10.17.0" + "node": ">=14" }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, + "license": "MIT", "dependencies": { - "pend": "~1.2.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" } }, "node_modules/fs-constants": { @@ -476,6 +2203,98 @@ "node": ">=6 <7 || >=8" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "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-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -497,6 +2316,52 @@ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "license": "MIT" }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/global-agent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", @@ -550,7 +2415,6 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, - "optional": true, "engines": { "node": ">= 0.4" }, @@ -589,6 +2453,16 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", @@ -602,12 +2476,82 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/http-cache-semantics": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", "dev": true }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/http2-wrapper": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", @@ -621,6 +2565,59 @@ "node": ">=10.19.0" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-corefoundation/node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -641,6 +2638,18 @@ ], "license": "BSD-3-Clause" }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -653,12 +2662,116 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.7.tgz", + "integrity": "sha512-gnWD14Jh3FzS3CPhF0AxNOJ8CxqeblPTADzI38r0wt8ZyQl5edpy75myt08EG2oKvpyiqSqsx+Wkz9vtkbTqYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "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/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -666,6 +2779,19 @@ "dev": true, "optional": true }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -695,6 +2821,101 @@ "json-buffer": "3.0.1" } }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true, + "license": "MIT" + }, "node_modules/lowercase-keys": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", @@ -704,6 +2925,19 @@ "node": ">=8" } }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/matcher": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", @@ -717,6 +2951,52 @@ "node": ">=10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-response": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", @@ -726,6 +3006,19 @@ "node": ">=4" } }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -735,6 +3028,56 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -783,6 +3126,16 @@ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", "license": "MIT" }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", @@ -822,12 +3175,85 @@ "node": ">=8" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, "node_modules/prebuild-install": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", @@ -854,6 +3280,13 @@ "node": ">=10" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -863,6 +3296,20 @@ "node": ">=0.4.0" } }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/pump": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", @@ -872,6 +3319,16 @@ "once": "^1.3.1" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", @@ -899,6 +3356,24 @@ "rc": "cli.js" } }, + "node_modules/read-config-file": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "config-file-ts": "^0.2.4", + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -913,6 +3388,26 @@ "node": ">= 6" } }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-alpn": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", @@ -931,6 +3426,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, "node_modules/roarr": { "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", @@ -969,6 +3474,33 @@ ], "license": "MIT" }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", + "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -995,10 +3527,46 @@ "type-fest": "^0.13.1" }, "engines": { - "node": ">=10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/simple-concat": { @@ -1046,6 +3614,81 @@ "simple-concat": "^1.0.0" } }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -1053,6 +3696,16 @@ "dev": true, "optional": true }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -1062,6 +3715,64 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -1083,6 +3794,38 @@ "node": ">= 8.0" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", @@ -1111,6 +3854,95 @@ "node": ">=6" } }, + "node_modules/tar/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/temp-file/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -1136,6 +3968,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/undici-types": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", @@ -1151,17 +3997,159 @@ "node": ">= 4.0.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true, + "license": "(WTFPL OR MIT)" + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -1171,6 +4159,43 @@ "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } } } } diff --git a/src-electron/package.json b/src-electron/package.json index 2f0f3640..a2dd9c32 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -7,10 +7,14 @@ "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", "main": "main.js", + "scripts": { + "build:appimage": "electron-builder --linux AppImage" + }, "dependencies": { "keytar": "^7.9.0" }, "devDependencies": { - "electron": "^40.0.0" + "electron": "^40.0.0", + "electron-builder": "^24.13.3" } } From f7673a943b2b83defc13152ce0ef280085160b2f Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 22:12:05 +0530 Subject: [PATCH 757/864] fix: file copy paste not workin gin file tree --- src-electron/main-window-ipc.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index a7996412..da8332b8 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -244,8 +244,8 @@ function registerWindowIpcHandlers() { // Try reading as file URLs const text = clipboard.read('public.file-url'); if (text) { - // Convert file:// URLs to paths - const paths = text.split('\n') + // Convert file:// URLs to paths (handle both \n and \r\n line endings) + const paths = text.split(/\r?\n/) .filter(url => url.startsWith('file://')) .map(url => decodeURIComponent(url.replace('file://', ''))); if (paths.length > 0) { @@ -254,11 +254,11 @@ function registerWindowIpcHandlers() { } } - // Linux: text/uri-list format + // Linux: text/uri-list format (uses \r\n line endings per RFC 2483) if (process.platform === 'linux' && formats.includes('text/uri-list')) { const text = clipboard.read('text/uri-list'); if (text) { - const paths = text.split('\n') + const paths = text.split(/\r?\n/) .filter(url => url.startsWith('file://')) .map(url => decodeURIComponent(url.replace('file://', ''))); if (paths.length > 0) { From af39dc612a98a7e762be8990224a0434cfb140b8 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 29 Jan 2026 22:25:43 +0530 Subject: [PATCH 758/864] chore: in dev builds directly serve from the fs with custom protocol --- src-electron/config.json | 4 +-- src-electron/main.js | 60 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src-electron/config.json b/src-electron/config.json index 5ca03e5a..e12704ce 100644 --- a/src-electron/config.json +++ b/src-electron/config.json @@ -3,7 +3,7 @@ "stage": "dev", "version": "5.0.5", "productName": "Phoenix Code Experimental Build", - "phoenixLoadURL": "http://localhost:8000/src/", + "phoenixLoadURL": "phtauri://localhost/src/", "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/"], - "gaMetricsURL": "http://localhost:8000/src/desktop-metrics.html" + "gaMetricsURL": "phtauri://localhost/src/desktop-metrics.html" } diff --git a/src-electron/main.js b/src-electron/main.js index 00a7a38e..8a92e639 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow, protocol, Menu, ipcMain } = require('electron'); +const { app, BrowserWindow, protocol, Menu, ipcMain, net } = require('electron'); const path = require('path'); const fs = require('fs'); @@ -10,6 +10,21 @@ const { assertTrusted } = require('./ipc-security'); const { getWindowOptions, trackWindowState, DEFAULTS } = require('./window-state'); const { phoenixLoadURL, gaMetricsURL } = require('./config'); +// Register phtauri:// as a privileged scheme (must be done before app ready) +// This enables standard web features: fetch, localStorage, cookies, etc. +protocol.registerSchemesAsPrivileged([ + { + scheme: 'phtauri', + privileges: { + standard: true, + secure: true, + supportFetchAPI: true, + corsEnabled: true, + stream: true + } + } +]); + // Request single instance lock - only one instance of the app should run at a time const gotTheLock = app.requestSingleInstanceLock(); @@ -194,11 +209,45 @@ app.whenReady().then(async () => { // Remove default menu bar Menu.setApplicationMenu(null); + // Register phtauri:// protocol for serving Phoenix files + // In dev: serves from ../phoenix/ repo + // In packaged: would need different handling (but typically uses https:// in production) + if (!app.isPackaged) { + const phoenixRepoPath = path.resolve(__dirname, '..', '..', 'phoenix'); + + protocol.handle('phtauri', (request) => { + try { + const url = new URL(request.url); + // phtauri://localhost/src/index.html -> ../phoenix/src/index.html + let requestedPath = decodeURIComponent(url.pathname); + + // Serve index.html for directory requests + if (requestedPath.endsWith('/')) { + requestedPath += 'index.html'; + } + + const filePath = path.join(phoenixRepoPath, requestedPath); + const normalizedFilePath = path.normalize(filePath); + + // Security: Ensure path is under phoenix repo (prevent directory traversal) + if (!normalizedFilePath.startsWith(phoenixRepoPath)) { + console.error('phtauri access denied - path not under phoenix repo:', requestedPath); + return new Response('Access denied', { status: 403 }); + } + + return net.fetch(`file://${normalizedFilePath}`); + } catch (err) { + console.error('phtauri protocol error:', err); + return new Response('Not found', { status: 404 }); + } + }); + } + // Register asset:// protocol for serving local files from appLocalData/assets/ const appDataDir = getAppDataDir(); const assetsDir = path.join(appDataDir, 'assets'); - protocol.registerFileProtocol('asset', (request, callback) => { + protocol.handle('asset', (request) => { try { const url = new URL(request.url); // Decode the path from URL encoding @@ -209,14 +258,13 @@ app.whenReady().then(async () => { // Security: Ensure path is under assets directory (prevent directory traversal) if (!normalizedRequested.startsWith(normalizedAssetsDir)) { console.error('Asset access denied - path not under assets dir:', requestedPath); - callback({ error: -10 }); // net::ERR_ACCESS_DENIED - return; + return new Response('Access denied', { status: 403 }); } - callback({ path: normalizedRequested }); + return net.fetch(`file://${normalizedRequested}`); } catch (err) { console.error('Asset protocol error:', err); - callback({ error: -2 }); // net::ERR_FAILED + return new Response('Not found', { status: 404 }); } }); From 73b2ff802e19da30c2c33699a3fc7fad1b3c8208 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 09:39:19 +0530 Subject: [PATCH 759/864] build: build electron appimage npm run command --- .gitignore | 1 + package.json | 3 +- src-electron/electron-builder.yml | 3 ++ src-electron/main.js | 69 +++++++++++++++++-------------- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 9f02bff5..5bb72fe3 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ src-electron/bin src-electron/src-node src-electron/config-effective.json src-electron/dist +src-electron/phoenix-dist node_modules dist diff --git a/package.json b/package.json index f7ff496a..10d7e216 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,8 @@ "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "_make_src-node": "node ./src-build/makeSrcNode.js ../phoenix/src-node", - "build:electron": "npm run _make_src-node && cd src-electron && npm run build:appimage", + "_copy_phoenix-dist": "cd ../phoenix && npm run release:prod && cd ../phoenix-desktop && shx rm -rf src-electron/phoenix-dist && shx cp -r ../phoenix/dist src-electron/phoenix-dist", + "build:electron": "npm run _make_src-node && npm run _copy_phoenix-dist && cd src-electron && npm run build:appimage", "_ci_make_src-node": "node ./src-build/makeSrcNode.js phoenix/src-node", "_ci-clonePhoenixForTests": "npm run _ci-env-warn && node ./src-build/clonePhoenixForTests.js", "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm ci && npm run build && cd ..", diff --git a/src-electron/electron-builder.yml b/src-electron/electron-builder.yml index 5475de9e..6da2ed24 100644 --- a/src-electron/electron-builder.yml +++ b/src-electron/electron-builder.yml @@ -15,6 +15,7 @@ files: - "!dist/**" - "!src-node/**" - "!bin/**" + - "!phoenix-dist/**" asarUnpack: - "node_modules/keytar/**" @@ -24,6 +25,8 @@ extraResources: to: "src-node" - from: "bin" to: "bin" + - from: "phoenix-dist" + to: "phoenix-dist" extraMetadata: main: main.js diff --git a/src-electron/main.js b/src-electron/main.js index 8a92e639..82adb08d 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -210,38 +210,45 @@ app.whenReady().then(async () => { Menu.setApplicationMenu(null); // Register phtauri:// protocol for serving Phoenix files - // In dev: serves from ../phoenix/ repo - // In packaged: would need different handling (but typically uses https:// in production) - if (!app.isPackaged) { - const phoenixRepoPath = path.resolve(__dirname, '..', '..', 'phoenix'); - - protocol.handle('phtauri', (request) => { - try { - const url = new URL(request.url); - // phtauri://localhost/src/index.html -> ../phoenix/src/index.html - let requestedPath = decodeURIComponent(url.pathname); - - // Serve index.html for directory requests - if (requestedPath.endsWith('/')) { - requestedPath += 'index.html'; - } - - const filePath = path.join(phoenixRepoPath, requestedPath); - const normalizedFilePath = path.normalize(filePath); - - // Security: Ensure path is under phoenix repo (prevent directory traversal) - if (!normalizedFilePath.startsWith(phoenixRepoPath)) { - console.error('phtauri access denied - path not under phoenix repo:', requestedPath); - return new Response('Access denied', { status: 403 }); - } - - return net.fetch(`file://${normalizedFilePath}`); - } catch (err) { - console.error('phtauri protocol error:', err); - return new Response('Not found', { status: 404 }); + // In dev: serves from ../phoenix/ repo (phtauri://localhost/src/ -> ../phoenix/src/) + // In packaged: serves from resources/phoenix-dist/ (phtauri://localhost/src/ -> phoenix-dist/) + const phoenixBasePath = app.isPackaged + ? path.join(process.resourcesPath, 'phoenix-dist') + : path.resolve(__dirname, '..', '..', 'phoenix', 'src'); + + protocol.handle('phtauri', (request) => { + try { + const url = new URL(request.url); + // phtauri://localhost/src/index.html -> strip /src prefix + let requestedPath = decodeURIComponent(url.pathname); + + // Strip /src/ prefix since phoenix-dist already contains src contents + if (requestedPath.startsWith('/src/')) { + requestedPath = requestedPath.substring(4); // Remove '/src' + } else if (requestedPath === '/src') { + requestedPath = '/'; } - }); - } + + // Serve index.html for directory requests + if (requestedPath.endsWith('/')) { + requestedPath += 'index.html'; + } + + const filePath = path.join(phoenixBasePath, requestedPath); + const normalizedFilePath = path.normalize(filePath); + + // Security: Ensure path is under phoenix base (prevent directory traversal) + if (!normalizedFilePath.startsWith(phoenixBasePath)) { + console.error('phtauri access denied - path not under phoenix base:', requestedPath); + return new Response('Access denied', { status: 403 }); + } + + return net.fetch(`file://${normalizedFilePath}`); + } catch (err) { + console.error('phtauri protocol error:', err); + return new Response('Not found', { status: 404 }); + } + }); // Register asset:// protocol for serving local files from appLocalData/assets/ const appDataDir = getAppDataDir(); From d1513399e85a54410446c4176531ae7dcab5fb5f Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sun, 1 Feb 2026 04:54:35 +0000 Subject: [PATCH 760/864] ci: update phcode version to 5.1.1 --- package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 10d7e216..29c484a9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.0", + "version": "5.1.1", "type": "module", "scripts": { "tauri": "tauri", @@ -52,6 +52,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "ea4c212496edbb651bed31b2a3768d2223ead900" + "commit": "a6a2bcaaeadb8ad2a8320492640672dcdc1981f3" } } \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c9234140..9779cb5a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.0" +version = "5.1.1" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index bd8130b1..f5040f78 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.0" + "version": "5.1.1" }, "tauri": { "allowlist": { From 2cc9824a0985e951c41e820c0133e6c3eb88ed1c Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 12:38:02 +0530 Subject: [PATCH 761/864] build: releaseSrc and releaseSrcDebug npm builds electron appimage in linux --- package.json | 7 +- src-build/createSrcRelease.js | 171 ++++++++++++++++++++++++++++ src-build/createSrcReleaseConfig.js | 46 -------- src-electron/config-dev.json | 4 + src-electron/config-prod.json | 1 + src-electron/config-staging.json | 1 + src-electron/main.js | 14 +-- 7 files changed, 182 insertions(+), 62 deletions(-) create mode 100644 src-build/createSrcRelease.js delete mode 100644 src-build/createSrcReleaseConfig.js create mode 100644 src-electron/config-dev.json diff --git a/package.json b/package.json index 29c484a9..7522b3fe 100644 --- a/package.json +++ b/package.json @@ -6,22 +6,19 @@ "scripts": { "tauri": "tauri", "tauriBuildDemoApp": "node src-build/createDemoReleaseConfig.js && tauri build --config ./src-tauri/tauri-local.conf.json", - "_createSrcReleaseConfig": "node src-build/createSrcReleaseConfig.js", "_createDistReleaseConfig": "node src-build/createDistReleaseConfig.js", "_createDistBundleReleaseConfig": "node src-build/createDistBundleReleaseConfig.js", "_createDistTestReleaseConfig": "node src-build/createDistTestReleaseConfig.js", "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", - "releaseSrc": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseSrcDebug": "npm run _make_src-node && npm run _createSrcReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug --verbose", + "releaseSrc": "node src-build/createSrcRelease.js", + "releaseSrcDebug": "node src-build/createSrcRelease.js --debug", "releaseDist": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistBundle": "npm run _make_src-node && npm run _createDistBundleReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --verbose", "releaseDistDebug": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug --verbose", "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "_make_src-node": "node ./src-build/makeSrcNode.js ../phoenix/src-node", - "_copy_phoenix-dist": "cd ../phoenix && npm run release:prod && cd ../phoenix-desktop && shx rm -rf src-electron/phoenix-dist && shx cp -r ../phoenix/dist src-electron/phoenix-dist", - "build:electron": "npm run _make_src-node && npm run _copy_phoenix-dist && cd src-electron && npm run build:appimage", "_ci_make_src-node": "node ./src-build/makeSrcNode.js phoenix/src-node", "_ci-clonePhoenixForTests": "npm run _ci-env-warn && node ./src-build/clonePhoenixForTests.js", "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm ci && npm run build && cd ..", diff --git a/src-build/createSrcRelease.js b/src-build/createSrcRelease.js new file mode 100644 index 00000000..112f5123 --- /dev/null +++ b/src-build/createSrcRelease.js @@ -0,0 +1,171 @@ +import { execSync } from 'child_process'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; +import fs from 'fs'; +import * as os from 'os'; +import chalk from 'chalk'; +import { getPlatformDetails } from './utils.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const projectRoot = join(__dirname, '..'); + +// Parse command line args +const args = process.argv.slice(2); +const isDebug = args.includes('--debug'); +const { platform } = getPlatformDetails(); + +// Determine target from CLI or auto-detect +let target; +if (args.includes('electron')) { + target = 'electron'; +} else if (args.includes('tauri')) { + target = 'tauri'; +} else { + // Auto-detect: Linux uses Electron, Windows/Mac use Tauri + target = (platform === 'linux') ? 'electron' : 'tauri'; +} + +// Print override instructions +console.log(chalk.cyan('\n=== Phoenix Code Release Build ===\n')); +console.log(`Platform: ${platform}, Target: ${target}${isDebug ? ' (debug)' : ''}\n`); +console.log(chalk.gray('To force a different target:')); +console.log(chalk.gray(` npm run releaseSrc -- tauri # Force Tauri build`)); +console.log(chalk.gray(` npm run releaseSrc -- electron # Force Electron build`)); +console.log(chalk.gray(` npm run releaseSrcDebug -- tauri # Force Tauri debug build\n`)); + +// Warn about non-standard platform/target combinations +const recommendedTarget = (platform === 'linux') ? 'electron' : 'tauri'; +if (target !== recommendedTarget) { + const y = chalk.yellow; + const b = chalk.bold.yellow; + const line1 = ` Building ${target} on ${platform} is not officially supported.`; + const line2 = ` Recommended: npm run releaseSrc (auto-detects ${recommendedTarget} for ${platform})`; + const width = Math.max(50, line1.length, line2.length) + 2; + const border = '═'.repeat(width); + const pad = (str) => str + ' '.repeat(width - str.length); + + console.warn(y(`╔${border}╗`)); + console.warn(y('║') + b(pad(' ⚠️ NON-STANDARD PLATFORM CONFIGURATION')) + y('║')); + console.warn(y(`╠${border}╣`)); + console.warn(y('║') + y(pad(line1)) + y('║')); + console.warn(y('║') + y(pad(line2)) + y('║')); + console.warn(y(`╚${border}╝\n`)); +} + +function run(cmd, options = {}) { + console.log(chalk.blue(`> ${cmd}`)); + execSync(cmd, { stdio: 'inherit', ...options }); +} + +function setupSrcNode(targetDir) { + console.log(chalk.cyan('\n=== Setting up src-node ===\n')); + const srcNodeSource = join(projectRoot, '..', 'phoenix', 'src-node'); + const destPath = join(projectRoot, targetDir, 'src-node'); + + console.log(`Setting up ${destPath}...`); + run(`shx rm -rf "${destPath}"`); + run(`shx cp -r "${srcNodeSource}" "${destPath}"`); + console.log('Installing production dependencies...'); + execSync('npm ci --production', { cwd: destPath, stdio: 'inherit' }); + // Remove unsupported musl binaries + execSync(`shx rm -f "${destPath}/node_modules/@msgpackr-extract/msgpackr-extract-linux-*/*.musl.node"`, { stdio: 'pipe' }); + execSync(`shx rm -f "${destPath}/node_modules/@lmdb/lmdb-linux-*/*.musl.node"`, { stdio: 'pipe' }); +} + +function createTauriConfig() { + console.log(chalk.cyan('\n=== Creating Tauri Config ===\n')); + const tauriConfigPath = join(projectRoot, 'src-tauri', 'tauri.conf.json'); + const tauriLocalConfigPath = join(projectRoot, 'src-tauri', 'tauri-local.conf.json'); + + console.log('Reading config file:', tauriConfigPath); + let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + + console.log(chalk.cyan('!Only creating executables. Installers are disabled.\n')); + configJson.tauri.bundle.active = false; + configJson.build.distDir = '../../phoenix/src/'; + + const phoenixVersion = configJson.package.version; + if (os.platform() === 'win32') { + configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; + } else { + configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; + } + + if (os.platform() === 'darwin') { + configJson.tauri.bundle.icon = [ + "icons-mac/32x32.png", "icons-mac/128x128.png", + "icons-mac/128x128@2x.png", "icons-mac/icon.icns", "icons-mac/icon.ico" + ]; + } + + console.log('Window Boot url:', configJson.tauri.windows[0].url); + fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); +} + +function buildTauri() { + console.log(chalk.cyan('\n=== Building Tauri ===\n')); + setupSrcNode('src-tauri'); + createTauriConfig(); + const debugFlags = isDebug ? '--debug --verbose' : ''; + run(`tauri build --config ./src-tauri/tauri-local.conf.json ${debugFlags}`.trim()); +} + +function createElectronConfig() { + console.log(chalk.cyan('\n=== Creating Electron Config ===\n')); + const electronDir = join(projectRoot, 'src-electron'); + const configPath = join(electronDir, 'config.json'); + const configDevPath = join(electronDir, 'config-dev.json'); + const configEffectivePath = join(electronDir, 'config-effective.json'); + + console.log('Merging config.json + config-dev.json -> config-effective.json'); + const baseConfig = JSON.parse(fs.readFileSync(configPath)); + const devConfig = JSON.parse(fs.readFileSync(configDevPath)); + + // Merge: config-dev.json overrides config.json + const effectiveConfig = { ...baseConfig, ...devConfig }; + + console.log('phoenixLoadURL:', effectiveConfig.phoenixLoadURL); + console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); + fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); +} + +function buildElectron() { + console.log(chalk.cyan('\n=== Building Electron AppImage ===\n')); + setupSrcNode('src-electron'); + createElectronConfig(); + + const phoenixDir = join(projectRoot, '..', 'phoenix'); + const phoenixDistSrc = join(phoenixDir, 'dist'); + const phoenixDistDest = join(projectRoot, 'src-electron', 'phoenix-dist'); + + // Build phoenix production dist + console.log('Building Phoenix production dist...'); + run('npm run release:prod', { cwd: phoenixDir }); + + // Copy dist to electron + console.log('Copying phoenix dist...'); + run(`shx rm -rf "${phoenixDistDest}"`); + run(`shx cp -r "${phoenixDistSrc}" "${phoenixDistDest}"`); + + // Build AppImage + console.log('Building AppImage...'); + run('npm run build:appimage', { cwd: join(projectRoot, 'src-electron') }); +} + +async function main() { + if (target === 'tauri') { + buildTauri(); + } else { + buildElectron(); + } + + console.log(chalk.green('\n=== Release build complete! ===\n')); +} + +main().catch(err => { + console.error(chalk.red('Build failed:'), err); + process.exit(1); +}); diff --git a/src-build/createSrcReleaseConfig.js b/src-build/createSrcReleaseConfig.js deleted file mode 100644 index 60128bcb..00000000 --- a/src-build/createSrcReleaseConfig.js +++ /dev/null @@ -1,46 +0,0 @@ -import {fileURLToPath} from "url"; -import {dirname} from "path"; -import fs from 'fs'; -import * as os from 'os'; - -import {getPlatformDetails} from "./utils.js"; -import chalk from "chalk"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -async function createSrcReleaseConfig() { - const platform = getPlatformDetails().platform; - const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` - : `${__dirname}/../src-tauri/tauri.conf.json`; - const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` - : `${__dirname}/../src-tauri/tauri-local.conf.json`; - console.log("Reading config file: ", tauriConfigPath); - let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run releaseDistBundle\n")); - configJson.tauri.bundle.active = false; - configJson.build.distDir = '../../phoenix/src/' - const phoenixVersion = configJson.package.version; - if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; - configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; - } else { - configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; - configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; - } - if(os.platform() === 'darwin'){ - // inject macos icons - configJson.tauri.bundle.icon = [ - "icons-mac/32x32.png", - "icons-mac/128x128.png", - "icons-mac/128x128@2x.png", - "icons-mac/icon.icns", - "icons-mac/icon.ico" - ]; - } - console.log("Window Boot url is: ", configJson.tauri.windows[0].url); - console.log("Writing new local config json ", tauriLocalConfigPath); - fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); -} - -await createSrcReleaseConfig(); diff --git a/src-electron/config-dev.json b/src-electron/config-dev.json new file mode 100644 index 00000000..b2d784ea --- /dev/null +++ b/src-electron/config-dev.json @@ -0,0 +1,4 @@ +{ + "phoenixLoadURL": "phtauri://localhost/", + "gaMetricsURL": "phtauri://localhost/desktop-metrics.html" +} diff --git a/src-electron/config-prod.json b/src-electron/config-prod.json index 183b1042..bcb80e94 100644 --- a/src-electron/config-prod.json +++ b/src-electron/config-prod.json @@ -2,5 +2,6 @@ "identifier": "io.phcode", "stage": "production", "productName": "Phoenix Code", + "phoenixLoadURL": "phtauri://localhost/", "gaMetricsURL": "https://phcode.dev/desktop-metrics.html" } diff --git a/src-electron/config-staging.json b/src-electron/config-staging.json index 9d6e4202..23e48f01 100644 --- a/src-electron/config-staging.json +++ b/src-electron/config-staging.json @@ -2,6 +2,7 @@ "identifier": "io.phcode.staging", "stage": "stage", "productName": "Phoenix Code Pre-release", + "phoenixLoadURL": "phtauri://localhost/", "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/", "https://staging.phcode.dev/"], "gaMetricsURL": "https://staging.phcode.dev/desktop-metrics.html" } diff --git a/src-electron/main.js b/src-electron/main.js index 82adb08d..cf684ee2 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -210,25 +210,17 @@ app.whenReady().then(async () => { Menu.setApplicationMenu(null); // Register phtauri:// protocol for serving Phoenix files - // In dev: serves from ../phoenix/ repo (phtauri://localhost/src/ -> ../phoenix/src/) - // In packaged: serves from resources/phoenix-dist/ (phtauri://localhost/src/ -> phoenix-dist/) + // In dev: serves from ../phoenix/ (URL includes /src/ prefix from config.json) + // In packaged: serves from resources/phoenix-dist (URL has no /src/ prefix) const phoenixBasePath = app.isPackaged ? path.join(process.resourcesPath, 'phoenix-dist') - : path.resolve(__dirname, '..', '..', 'phoenix', 'src'); + : path.resolve(__dirname, '..', '..', 'phoenix'); protocol.handle('phtauri', (request) => { try { const url = new URL(request.url); - // phtauri://localhost/src/index.html -> strip /src prefix let requestedPath = decodeURIComponent(url.pathname); - // Strip /src/ prefix since phoenix-dist already contains src contents - if (requestedPath.startsWith('/src/')) { - requestedPath = requestedPath.substring(4); // Remove '/src' - } else if (requestedPath === '/src') { - requestedPath = '/'; - } - // Serve index.html for directory requests if (requestedPath.endsWith('/')) { requestedPath += 'index.html'; From da38b301c3a7c5c6f031875b6af03f2b55f71440 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 16:32:26 +0530 Subject: [PATCH 762/864] build: release src should package src dir not dist --- src-build/createSrcRelease.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-build/createSrcRelease.js b/src-build/createSrcRelease.js index 112f5123..4ff5ffbf 100644 --- a/src-build/createSrcRelease.js +++ b/src-build/createSrcRelease.js @@ -138,12 +138,12 @@ function buildElectron() { createElectronConfig(); const phoenixDir = join(projectRoot, '..', 'phoenix'); - const phoenixDistSrc = join(phoenixDir, 'dist'); + const phoenixDistSrc = join(phoenixDir, 'src'); const phoenixDistDest = join(projectRoot, 'src-electron', 'phoenix-dist'); // Build phoenix production dist - console.log('Building Phoenix production dist...'); - run('npm run release:prod', { cwd: phoenixDir }); + console.log('Building Phoenix'); + run('npm run build', { cwd: phoenixDir }); // Copy dist to electron console.log('Copying phoenix dist...'); From 0b7f2bc466d798f6b9b8f005d1f1ff8b1abb284c Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 16:50:14 +0530 Subject: [PATCH 763/864] build: release dist refactor for tauri --- package.json | 8 +- src-build/createDistBundleReleaseConfig.js | 48 ---------- src-build/createDistRelease.js | 105 +++++++++++++++++++++ src-build/createDistReleaseConfig.js | 47 --------- src-build/createSrcRelease.js | 2 +- src-build/serveForPlatform.js | 6 +- 6 files changed, 111 insertions(+), 105 deletions(-) delete mode 100644 src-build/createDistBundleReleaseConfig.js create mode 100644 src-build/createDistRelease.js delete mode 100644 src-build/createDistReleaseConfig.js diff --git a/package.json b/package.json index 7522b3fe..f9dc7d0e 100644 --- a/package.json +++ b/package.json @@ -6,16 +6,14 @@ "scripts": { "tauri": "tauri", "tauriBuildDemoApp": "node src-build/createDemoReleaseConfig.js && tauri build --config ./src-tauri/tauri-local.conf.json", - "_createDistReleaseConfig": "node src-build/createDistReleaseConfig.js", - "_createDistBundleReleaseConfig": "node src-build/createDistBundleReleaseConfig.js", "_createDistTestReleaseConfig": "node src-build/createDistTestReleaseConfig.js", "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", "releaseSrc": "node src-build/createSrcRelease.js", "releaseSrcDebug": "node src-build/createSrcRelease.js --debug", - "releaseDist": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseDistBundle": "npm run _make_src-node && npm run _createDistBundleReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --verbose", - "releaseDistDebug": "npm run _make_src-node && npm run _createDistReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug --verbose", + "releaseDist": "node src-build/createDistRelease.js", + "releaseDistBundle": "node src-build/createDistRelease.js --bundle", + "releaseDistDebug": "node src-build/createDistRelease.js --debug", "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", "_make_src-node": "node ./src-build/makeSrcNode.js ../phoenix/src-node", diff --git a/src-build/createDistBundleReleaseConfig.js b/src-build/createDistBundleReleaseConfig.js deleted file mode 100644 index 8b84e252..00000000 --- a/src-build/createDistBundleReleaseConfig.js +++ /dev/null @@ -1,48 +0,0 @@ -import {fileURLToPath} from "url"; -import {dirname} from "path"; -import fs from 'fs'; -import chalk from 'chalk'; - -import {getPlatformDetails, patchTauriConfigWithMetricsHTML} from "./utils.js"; -import os from "os"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -async function createDistReleaseConfig() { - const platform = getPlatformDetails().platform; - const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` - : `${__dirname}/../src-tauri/tauri.conf.json`; - const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` - : `${__dirname}/../src-tauri/tauri-local.conf.json`; - console.log("Reading Tauri config file: ", tauriConfigPath); - let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log(chalk.cyan("\n!Updates and signing is disabled while creating msi, appimage and dmg installers. If you want to sign, use tauri build commands directly.\n")); - configJson.tauri.bundle.active = true; - configJson.tauri.updater.active = false; - configJson.build.distDir = '../../phoenix/dist/'; - const phoenixVersion = configJson.package.version; - if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; - configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; - } else { - configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; - configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; - } - if(os.platform() === 'darwin'){ - // inject macos icons - configJson.tauri.bundle.icon = [ - "icons-mac/32x32.png", - "icons-mac/128x128.png", - "icons-mac/128x128@2x.png", - "icons-mac/icon.icns", - "icons-mac/icon.ico" - ]; - } - patchTauriConfigWithMetricsHTML(configJson); - console.log("Window Boot url is: ", configJson.tauri.windows[0].url); - console.log("Writing new local config json ", tauriLocalConfigPath); - fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); -} - -await createDistReleaseConfig(); diff --git a/src-build/createDistRelease.js b/src-build/createDistRelease.js new file mode 100644 index 00000000..201254ed --- /dev/null +++ b/src-build/createDistRelease.js @@ -0,0 +1,105 @@ +import { execSync } from 'child_process'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; +import fs from 'fs'; +import os from 'os'; +import chalk from 'chalk'; +import { getPlatformDetails, patchTauriConfigWithMetricsHTML } from './utils.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const projectRoot = join(__dirname, '..'); + +// Parse command line args +const args = process.argv.slice(2); +const isBundle = args.includes('--bundle'); +const isDebug = args.includes('--debug'); +const { platform } = getPlatformDetails(); + +// Print build info +console.log(chalk.cyan('\n=== Phoenix Code Dist Release Build ===\n')); +console.log(`Platform: ${platform}, Bundle: ${isBundle}, Debug: ${isDebug}\n`); + +function run(cmd, options = {}) { + console.log(chalk.blue(`> ${cmd}`)); + execSync(cmd, { stdio: 'inherit', ...options }); +} + +function setupSrcNode() { + console.log(chalk.cyan('\n=== Setting up src-node ===\n')); + const srcNodeSource = join(projectRoot, '..', 'phoenix', 'src-node'); + const destPath = join(projectRoot, 'src-tauri', 'src-node'); + + console.log(`Setting up ${destPath}...`); + run(`shx rm -rf "${destPath}"`); + run(`shx cp -r "${srcNodeSource}" "${destPath}"`); + console.log('Installing production dependencies...'); + execSync('npm ci --production', { cwd: destPath, stdio: 'inherit' }); + // Remove unsupported musl binaries + execSync(`shx rm -f "${destPath}/node_modules/@msgpackr-extract/msgpackr-extract-linux-*/*.musl.node"`, { stdio: 'pipe' }); + execSync(`shx rm -f "${destPath}/node_modules/@lmdb/lmdb-linux-*/*.musl.node"`, { stdio: 'pipe' }); +} + +function createDistConfig() { + console.log(chalk.cyan('\n=== Creating Tauri Config ===\n')); + const tauriConfigPath = join(projectRoot, 'src-tauri', 'tauri.conf.json'); + const tauriLocalConfigPath = join(projectRoot, 'src-tauri', 'tauri-local.conf.json'); + + console.log('Reading Tauri config file:', tauriConfigPath); + let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + + if (isBundle) { + console.log(chalk.cyan('\n!Updates and signing is disabled while creating msi, appimage and dmg installers. If you want to sign, use tauri build commands directly.\n')); + configJson.tauri.bundle.active = true; + configJson.tauri.updater.active = false; + } else { + console.log(chalk.cyan('\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run releaseDistBundle\n')); + configJson.tauri.bundle.active = false; + } + + configJson.build.distDir = '../../phoenix/dist/'; + + const phoenixVersion = configJson.package.version; + if (os.platform() === 'win32') { + configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; + } else { + configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; + configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; + } + + if (os.platform() === 'darwin') { + // inject macos icons + configJson.tauri.bundle.icon = [ + "icons-mac/32x32.png", + "icons-mac/128x128.png", + "icons-mac/128x128@2x.png", + "icons-mac/icon.icns", + "icons-mac/icon.ico" + ]; + } + + patchTauriConfigWithMetricsHTML(configJson); + console.log('Window Boot url:', configJson.tauri.windows[0].url); + console.log('Writing new local config json:', tauriLocalConfigPath); + fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); +} + +function buildTauri() { + console.log(chalk.cyan('\n=== Building Tauri ===\n')); + const debugFlags = isDebug ? '--debug --verbose' : ''; + const verboseFlag = isBundle && !isDebug ? '--verbose' : ''; + run(`tauri build --config ./src-tauri/tauri-local.conf.json ${debugFlags} ${verboseFlag}`.trim().replace(/\s+/g, ' ')); +} + +async function main() { + setupSrcNode(); + createDistConfig(); + buildTauri(); + console.log(chalk.green('\n=== Dist release build complete! ===\n')); +} + +main().catch(err => { + console.error(chalk.red('Build failed:'), err); + process.exit(1); +}); diff --git a/src-build/createDistReleaseConfig.js b/src-build/createDistReleaseConfig.js deleted file mode 100644 index 2c674386..00000000 --- a/src-build/createDistReleaseConfig.js +++ /dev/null @@ -1,47 +0,0 @@ -import {fileURLToPath} from "url"; -import {dirname} from "path"; -import fs from 'fs'; -import chalk from 'chalk'; - -import {getPlatformDetails, patchTauriConfigWithMetricsHTML} from "./utils.js"; -import os from "os"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -async function createDistReleaseConfig() { - const platform = getPlatformDetails().platform; - const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` - : `${__dirname}/../src-tauri/tauri.conf.json`; - const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` - : `${__dirname}/../src-tauri/tauri-local.conf.json`; - console.log("Reading Tauri config file: ", tauriConfigPath); - let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run releaseDistBundle\n")); - configJson.tauri.bundle.active = false; - configJson.build.distDir = '../../phoenix/dist/'; - const phoenixVersion = configJson.package.version; - if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; - configJson.tauri.windows[2].url = `https://phtauri.localhost/v${phoenixVersion}/drop-files.html`; - } else { - configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; - configJson.tauri.windows[2].url = `phtauri://localhost/v${phoenixVersion}/drop-files.html`; - } - if(os.platform() === 'darwin'){ - // inject macos icons - configJson.tauri.bundle.icon = [ - "icons-mac/32x32.png", - "icons-mac/128x128.png", - "icons-mac/128x128@2x.png", - "icons-mac/icon.icns", - "icons-mac/icon.ico" - ]; - } - patchTauriConfigWithMetricsHTML(configJson); - console.log("Window Boot url is: ", configJson.tauri.windows[0].url); - console.log("Writing new local config json ", tauriLocalConfigPath); - fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); -} - -await createDistReleaseConfig(); diff --git a/src-build/createSrcRelease.js b/src-build/createSrcRelease.js index 4ff5ffbf..7c2070ac 100644 --- a/src-build/createSrcRelease.js +++ b/src-build/createSrcRelease.js @@ -141,7 +141,7 @@ function buildElectron() { const phoenixDistSrc = join(phoenixDir, 'src'); const phoenixDistDest = join(projectRoot, 'src-electron', 'phoenix-dist'); - // Build phoenix production dist + // Build phoenix dev src console.log('Building Phoenix'); run('npm run build', { cwd: phoenixDir }); diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js index 41ed86b2..6a6a6f37 100644 --- a/src-build/serveForPlatform.js +++ b/src-build/serveForPlatform.js @@ -42,12 +42,10 @@ if (target !== recommendedTarget) { console.log(`Platform: ${platform}, target: ${target}`); -// Run common setup -console.log('\nEnsure to start phoenix server at http://localhost:8000 for development.'); -console.log('Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\n'); - // Run platform-specific command if (target === "tauri") { + console.log('\nEnsure to start phoenix server at http://localhost:8000 for development.'); + console.log('Follow https://github.com/phcode-dev/phoenix#running-phoenix for instructions.\n'); console.log('Setting up src-node...'); await execa("npm", ["run", "_make_src-node"], {stdio: "inherit"}); From da9dad4a83cfb1c4a200acc534c95d3e3e9edbca Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 17:23:03 +0530 Subject: [PATCH 764/864] build: releaseDist now supports electron in linux --- src-build/createDistRelease.js | 102 ++++++++++++++++++++++++++++++--- 1 file changed, 95 insertions(+), 7 deletions(-) diff --git a/src-build/createDistRelease.js b/src-build/createDistRelease.js index 201254ed..0c4e54be 100644 --- a/src-build/createDistRelease.js +++ b/src-build/createDistRelease.js @@ -2,7 +2,7 @@ import { execSync } from 'child_process'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import fs from 'fs'; -import os from 'os'; +import * as os from 'os'; import chalk from 'chalk'; import { getPlatformDetails, patchTauriConfigWithMetricsHTML } from './utils.js'; @@ -16,19 +16,52 @@ const isBundle = args.includes('--bundle'); const isDebug = args.includes('--debug'); const { platform } = getPlatformDetails(); +// Determine target from CLI or auto-detect +let target; +if (args.includes('electron')) { + target = 'electron'; +} else if (args.includes('tauri')) { + target = 'tauri'; +} else { + // Auto-detect: Linux uses Electron, Windows/Mac use Tauri + target = (platform === 'linux') ? 'electron' : 'tauri'; +} + // Print build info console.log(chalk.cyan('\n=== Phoenix Code Dist Release Build ===\n')); -console.log(`Platform: ${platform}, Bundle: ${isBundle}, Debug: ${isDebug}\n`); +console.log(`Platform: ${platform}, Target: ${target}, Bundle: ${isBundle}${isDebug ? ' (debug)' : ''}\n`); +console.log(chalk.gray('To force a different target:')); +console.log(chalk.gray(` npm run releaseDist -- tauri # Force Tauri build`)); +console.log(chalk.gray(` npm run releaseDist -- electron # Force Electron build\n`)); + +// Warn about non-standard platform/target combinations +const recommendedTarget = (platform === 'linux') ? 'electron' : 'tauri'; +if (target !== recommendedTarget) { + const y = chalk.yellow; + const b = chalk.bold.yellow; + const line1 = ` Building ${target} on ${platform} is not officially supported.`; + const line2 = ` Recommended: npm run releaseDist (auto-detects ${recommendedTarget} for ${platform})`; + const width = Math.max(50, line1.length, line2.length) + 2; + const border = '═'.repeat(width); + const pad = (str) => str + ' '.repeat(width - str.length); + + console.warn(y(`╔${border}╗`)); + console.warn(y('║') + b(pad(' ⚠️ NON-STANDARD PLATFORM CONFIGURATION')) + y('║')); + console.warn(y(`╠${border}╣`)); + console.warn(y('║') + y(pad(line1)) + y('║')); + console.warn(y('║') + y(pad(line2)) + y('║')); + console.warn(y(`╚${border}╝\n`)); +} function run(cmd, options = {}) { console.log(chalk.blue(`> ${cmd}`)); execSync(cmd, { stdio: 'inherit', ...options }); } -function setupSrcNode() { +function setupSrcNode(targetDir) { console.log(chalk.cyan('\n=== Setting up src-node ===\n')); const srcNodeSource = join(projectRoot, '..', 'phoenix', 'src-node'); - const destPath = join(projectRoot, 'src-tauri', 'src-node'); + const destPath = join(projectRoot, targetDir, 'src-node'); console.log(`Setting up ${destPath}...`); run(`shx rm -rf "${destPath}"`); @@ -87,15 +120,70 @@ function createDistConfig() { function buildTauri() { console.log(chalk.cyan('\n=== Building Tauri ===\n')); + setupSrcNode('src-tauri'); + createDistConfig(); const debugFlags = isDebug ? '--debug --verbose' : ''; const verboseFlag = isBundle && !isDebug ? '--verbose' : ''; run(`tauri build --config ./src-tauri/tauri-local.conf.json ${debugFlags} ${verboseFlag}`.trim().replace(/\s+/g, ' ')); } +function createElectronConfig() { + console.log(chalk.cyan('\n=== Creating Electron Config ===\n')); + const electronDir = join(projectRoot, 'src-electron'); + const configPath = join(electronDir, 'config.json'); + const configEffectivePath = join(electronDir, 'config-effective.json'); + + // Read ../phoenix/dist/config.json to get environment + const phoenixDistConfigPath = join(projectRoot, '..', 'phoenix', 'dist', 'config.json'); + console.log('Reading Phoenix dist config:', phoenixDistConfigPath); + const phoenixDistConfig = JSON.parse(fs.readFileSync(phoenixDistConfigPath)); + const environment = phoenixDistConfig.config.environment; // "dev", "stage", or "production" + + // Map environment to config file + const envConfigMap = { + 'dev': 'config-dev.json', + 'stage': 'config-staging.json', + 'production': 'config-prod.json' + }; + const envConfigFile = envConfigMap[environment] || 'config-dev.json'; + const envConfigPath = join(electronDir, envConfigFile); + + console.log(`Environment: ${environment} -> using ${envConfigFile}`); + + // Merge config.json + env-specific config + const baseConfig = JSON.parse(fs.readFileSync(configPath)); + const envConfig = JSON.parse(fs.readFileSync(envConfigPath)); + const effectiveConfig = { ...baseConfig, ...envConfig }; + + console.log('phoenixLoadURL:', effectiveConfig.phoenixLoadURL); + console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); + fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); +} + +function buildElectron() { + console.log(chalk.cyan('\n=== Building Electron AppImage ===\n')); + setupSrcNode('src-electron'); + createElectronConfig(); + + const phoenixDistSrc = join(projectRoot, '..', 'phoenix', 'dist'); + const phoenixDistDest = join(projectRoot, 'src-electron', 'phoenix-dist'); + + // Copy dist to electron + console.log('Copying phoenix dist...'); + run(`shx rm -rf "${phoenixDistDest}"`); + run(`shx cp -r "${phoenixDistSrc}" "${phoenixDistDest}"`); + + // Build AppImage + console.log('Building AppImage...'); + run('npm run build:appimage', { cwd: join(projectRoot, 'src-electron') }); +} + async function main() { - setupSrcNode(); - createDistConfig(); - buildTauri(); + if (target === 'tauri') { + buildTauri(); + } else { + buildElectron(); + } console.log(chalk.green('\n=== Dist release build complete! ===\n')); } From 5640d87ed5dbd64be7ab14db590e300da4d82a7f Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 17:50:22 +0530 Subject: [PATCH 765/864] build: electron dist test build scripts --- package.json | 5 +- src-build/createDistTestRelease.js | 189 +++++++++++++++++++++++ src-build/createDistTestReleaseConfig.js | 48 ------ 3 files changed, 191 insertions(+), 51 deletions(-) create mode 100644 src-build/createDistTestRelease.js delete mode 100644 src-build/createDistTestReleaseConfig.js diff --git a/package.json b/package.json index f9dc7d0e..ab710999 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "scripts": { "tauri": "tauri", "tauriBuildDemoApp": "node src-build/createDemoReleaseConfig.js && tauri build --config ./src-tauri/tauri-local.conf.json", - "_createDistTestReleaseConfig": "node src-build/createDistTestReleaseConfig.js", "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", "releaseSrc": "node src-build/createSrcRelease.js", @@ -14,8 +13,8 @@ "releaseDist": "node src-build/createDistRelease.js", "releaseDistBundle": "node src-build/createDistRelease.js --bundle", "releaseDistDebug": "node src-build/createDistRelease.js --debug", - "releaseDistTest": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json", - "releaseDistTestDebug": "npm run _make_src-node && npm run _createDistTestReleaseConfig && tauri build --config ./src-tauri/tauri-local.conf.json --debug", + "releaseDistTest": "node src-build/createDistTestRelease.js", + "releaseDistTestDebug": "node src-build/createDistTestRelease.js --debug", "_make_src-node": "node ./src-build/makeSrcNode.js ../phoenix/src-node", "_ci_make_src-node": "node ./src-build/makeSrcNode.js phoenix/src-node", "_ci-clonePhoenixForTests": "npm run _ci-env-warn && node ./src-build/clonePhoenixForTests.js", diff --git a/src-build/createDistTestRelease.js b/src-build/createDistTestRelease.js new file mode 100644 index 00000000..90fce2d0 --- /dev/null +++ b/src-build/createDistTestRelease.js @@ -0,0 +1,189 @@ +import { execSync } from 'child_process'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; +import fs from 'fs'; +import * as os from 'os'; +import chalk from 'chalk'; +import { getPlatformDetails } from './utils.js'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const projectRoot = join(__dirname, '..'); + +// Parse command line args +const args = process.argv.slice(2); +const isDebug = args.includes('--debug'); +const { platform } = getPlatformDetails(); + +// Determine target from CLI or auto-detect +let target; +if (args.includes('electron')) { + target = 'electron'; +} else if (args.includes('tauri')) { + target = 'tauri'; +} else { + // Auto-detect: Linux uses Electron, Windows/Mac use Tauri + target = (platform === 'linux') ? 'electron' : 'tauri'; +} + +// Print build info +console.log(chalk.cyan('\n=== Phoenix Code Dist-Test Release Build ===\n')); +console.log(`Platform: ${platform}, Target: ${target}${isDebug ? ' (debug)' : ''}\n`); +console.log(chalk.gray('To force a different target:')); +console.log(chalk.gray(` npm run releaseDistTest -- tauri # Force Tauri build`)); +console.log(chalk.gray(` npm run releaseDistTest -- electron # Force Electron build\n`)); + +// Warn about non-standard platform/target combinations +const recommendedTarget = (platform === 'linux') ? 'electron' : 'tauri'; +if (target !== recommendedTarget) { + const y = chalk.yellow; + const b = chalk.bold.yellow; + const line1 = ` Building ${target} on ${platform} is not officially supported.`; + const line2 = ` Recommended: npm run releaseDistTest (auto-detects ${recommendedTarget} for ${platform})`; + const width = Math.max(50, line1.length, line2.length) + 2; + const border = '═'.repeat(width); + const pad = (str) => str + ' '.repeat(width - str.length); + + console.warn(y(`╔${border}╗`)); + console.warn(y('║') + b(pad(' ⚠️ NON-STANDARD PLATFORM CONFIGURATION')) + y('║')); + console.warn(y(`╠${border}╣`)); + console.warn(y('║') + y(pad(line1)) + y('║')); + console.warn(y('║') + y(pad(line2)) + y('║')); + console.warn(y(`╚${border}╝\n`)); +} + +function run(cmd, options = {}) { + console.log(chalk.blue(`> ${cmd}`)); + execSync(cmd, { stdio: 'inherit', ...options }); +} + +function setupSrcNode(targetDir) { + console.log(chalk.cyan('\n=== Setting up src-node ===\n')); + const srcNodeSource = join(projectRoot, '..', 'phoenix', 'src-node'); + const destPath = join(projectRoot, targetDir, 'src-node'); + + console.log(`Setting up ${destPath}...`); + run(`shx rm -rf "${destPath}"`); + run(`shx cp -r "${srcNodeSource}" "${destPath}"`); + console.log('Installing production dependencies...'); + execSync('npm ci --production', { cwd: destPath, stdio: 'inherit' }); + // Remove unsupported musl binaries + execSync(`shx rm -f "${destPath}/node_modules/@msgpackr-extract/msgpackr-extract-linux-*/*.musl.node"`, { stdio: 'pipe' }); + execSync(`shx rm -f "${destPath}/node_modules/@lmdb/lmdb-linux-*/*.musl.node"`, { stdio: 'pipe' }); +} + +function createDistTestConfig() { + console.log(chalk.cyan('\n=== Creating Tauri Config (dist-test) ===\n')); + const tauriConfigPath = join(projectRoot, 'src-tauri', 'tauri.conf.json'); + const tauriLocalConfigPath = join(projectRoot, 'src-tauri', 'tauri-local.conf.json'); + + console.log('Reading Tauri config file:', tauriConfigPath); + let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); + + // Test-specific settings + configJson.package.productName = "phoenix-test"; + configJson.tauri.windows[0].title = "phoenix-tester"; + + console.log(chalk.cyan('\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n')); + configJson.tauri.bundle.active = false; + + configJson.build.distDir = '../../phoenix/dist-test/'; + + const phoenixVersion = configJson.package.version; + if (os.platform() === 'win32') { + configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; + } else { + configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; + } + + // For tests we only need the main window. Other windows seem to be breaking tests in github actions. + configJson.tauri.windows = [configJson.tauri.windows[0]]; + + if (os.platform() === 'darwin') { + // inject macos icons + configJson.tauri.bundle.icon = [ + "icons-mac/32x32.png", + "icons-mac/128x128.png", + "icons-mac/128x128@2x.png", + "icons-mac/icon.icns", + "icons-mac/icon.ico" + ]; + } + + console.log('Window Boot url:', configJson.tauri.windows[0].url); + console.log('Writing new local config json:', tauriLocalConfigPath); + fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); +} + +function buildTauri() { + console.log(chalk.cyan('\n=== Building Tauri (dist-test) ===\n')); + setupSrcNode('src-tauri'); + createDistTestConfig(); + const debugFlags = isDebug ? '--debug --verbose' : ''; + run(`tauri build --config ./src-tauri/tauri-local.conf.json ${debugFlags}`.trim().replace(/\s+/g, ' ')); +} + +function createElectronConfig() { + console.log(chalk.cyan('\n=== Creating Electron Config (dist-test) ===\n')); + const electronDir = join(projectRoot, 'src-electron'); + const configPath = join(electronDir, 'config.json'); + const configEffectivePath = join(electronDir, 'config-effective.json'); + + // Read ../phoenix/dist-test/src/config.json to get environment (note: src subfolder for dist-test) + const phoenixDistTestConfigPath = join(projectRoot, '..', 'phoenix', 'dist-test', 'src', 'config.json'); + console.log('Reading Phoenix dist-test config:', phoenixDistTestConfigPath); + const phoenixDistTestConfig = JSON.parse(fs.readFileSync(phoenixDistTestConfigPath)); + const environment = phoenixDistTestConfig.config.environment; // "dev", "stage", or "production" + + // Map environment to config file + const envConfigMap = { + 'dev': 'config-dev.json', + 'stage': 'config-staging.json', + 'production': 'config-prod.json' + }; + const envConfigFile = envConfigMap[environment] || 'config-dev.json'; + const envConfigPath = join(electronDir, envConfigFile); + + console.log(`Environment: ${environment} -> using ${envConfigFile}`); + + // Merge config.json + env-specific config + const baseConfig = JSON.parse(fs.readFileSync(configPath)); + const envConfig = JSON.parse(fs.readFileSync(envConfigPath)); + const effectiveConfig = { ...baseConfig, ...envConfig }; + + console.log('phoenixLoadURL:', effectiveConfig.phoenixLoadURL); + console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); + fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); +} + +function buildElectron() { + console.log(chalk.cyan('\n=== Building Electron AppImage (dist-test) ===\n')); + setupSrcNode('src-electron'); + createElectronConfig(); + + const phoenixDistTestSrc = join(projectRoot, '..', 'phoenix', 'dist-test'); + const phoenixDistDest = join(projectRoot, 'src-electron', 'phoenix-dist'); + + // Copy dist-test to electron + console.log('Copying phoenix dist-test...'); + run(`shx rm -rf "${phoenixDistDest}"`); + run(`shx cp -r "${phoenixDistTestSrc}" "${phoenixDistDest}"`); + + // Build AppImage + console.log('Building AppImage...'); + run('npm run build:appimage', { cwd: join(projectRoot, 'src-electron') }); +} + +async function main() { + if (target === 'tauri') { + buildTauri(); + } else { + buildElectron(); + } + console.log(chalk.green('\n=== Dist-test release build complete! ===\n')); +} + +main().catch(err => { + console.error(chalk.red('Build failed:'), err); + process.exit(1); +}); diff --git a/src-build/createDistTestReleaseConfig.js b/src-build/createDistTestReleaseConfig.js deleted file mode 100644 index 4b449427..00000000 --- a/src-build/createDistTestReleaseConfig.js +++ /dev/null @@ -1,48 +0,0 @@ -import {fileURLToPath} from "url"; -import {dirname} from "path"; -import fs from 'fs'; - -import {getPlatformDetails} from "./utils.js"; -import chalk from "chalk"; -import os from "os"; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = dirname(__filename); - -async function createDistTestReleaseConfig() { - const platform = getPlatformDetails().platform; - const tauriConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri.conf.json` - : `${__dirname}/../src-tauri/tauri.conf.json`; - const tauriLocalConfigPath = (platform === "win") ? `${__dirname}\\..\\src-tauri\\tauri-local.conf.json` - : `${__dirname}/../src-tauri/tauri-local.conf.json`; - console.log("Reading config file: ", tauriConfigPath); - let configJson = JSON.parse(fs.readFileSync(tauriConfigPath)); - configJson.package.productName = "phoenix-test"; - configJson.tauri.windows[0].title = "phoenix-tester"; - console.log(chalk.cyan("\n!Only creating executables. Creating msi, appimage and dmg installers are disabled in this build. If you want to create an installer, use: npm run tauri build manually after setting distDir in tauri conf!\n")); - configJson.tauri.bundle.active = false; - configJson.build.distDir = '../../phoenix/dist-test/'; - const phoenixVersion = configJson.package.version; - if(os.platform() === 'win32'){ - configJson.tauri.windows[0].url = `https://phtauri.localhost/v${phoenixVersion}/`; - } else { - configJson.tauri.windows[0].url = `phtauri://localhost/v${phoenixVersion}/`; - } - // for tests we only need the main window. other windows seems to be breaking tests in github actions. - configJson.tauri.windows = [configJson.tauri.windows[0]]; - if(os.platform() === 'darwin'){ - // inject macos icons - configJson.tauri.bundle.icon = [ - "icons-mac/32x32.png", - "icons-mac/128x128.png", - "icons-mac/128x128@2x.png", - "icons-mac/icon.icns", - "icons-mac/icon.ico" - ]; - } - console.log("Window Boot url is: ", configJson.tauri.windows[0].url); - console.log("Writing new local config json ", tauriLocalConfigPath); - fs.writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); -} - -await createDistTestReleaseConfig(); From 668c028a5be7c0cf4a3c7deadda5972d5436df97 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 18:28:33 +0530 Subject: [PATCH 766/864] ci: create electron bins in pipeline scripts --- package.json | 11 ++-- ...eleaseConfig.js => ci-setupDistFolders.js} | 50 ++++++++++++++++++- src-tauri/src/main.rs | 4 +- src-tauri/tauri.conf.json | 13 ++--- 4 files changed, 63 insertions(+), 15 deletions(-) rename src-build/{ci-createDistReleaseConfig.js => ci-setupDistFolders.js} (74%) diff --git a/package.json b/package.json index ab710999..250ca0a7 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "scripts": { "tauri": "tauri", "tauriBuildDemoApp": "node src-build/createDemoReleaseConfig.js && tauri build --config ./src-tauri/tauri-local.conf.json", - "_ci-createDistReleaseConfig": "node src-build/ci-createDistReleaseConfig.js", + "_ci-setupDistFolders": "node src-build/ci-setupDistFolders.js", "_ci-env-warn": "echo !!!This script is supposed to executed in github actions only. Ignore if you are seeing this message in a github actions log.", "releaseSrc": "node src-build/createSrcRelease.js", "releaseSrcDebug": "node src-build/createSrcRelease.js --debug", @@ -19,9 +19,10 @@ "_ci_make_src-node": "node ./src-build/makeSrcNode.js phoenix/src-node", "_ci-clonePhoenixForTests": "npm run _ci-env-warn && node ./src-build/clonePhoenixForTests.js", "_ci-cloneAndBuildPhoenix": "npm run _ci-env-warn && node ./src-build/clonePhoenix.js && cd phoenix && npm ci && npm run build && cd ..", - "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", - "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", - "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-createDistReleaseConfig && npm run _ci_make_src-node", + "_ci-release:dev": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:dev && cd .. && npm run _ci-setupDistFolders && npm run _ci_make_src-node", + "_ci-release:staging": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:staging && cd .. && npm run _ci-setupDistFolders && npm run _ci_make_src-node", + "_ci-release:prod": "npm run _ci-env-warn && npm run _ci-cloneAndBuildPhoenix && cd phoenix && npm run release:prod && cd .. && npm run _ci-setupDistFolders && npm run _ci_make_src-node", + "_ci-releaseElectronApp": "cd src-electron && npm run build:appimage && cd ..", "_ci-update-phcode-build": "node src-build/update-phcode-build.js", "serve": "node src-build/serveForPlatform.js", "serve:tauri": "node src-build/serveForPlatform.js tauri", @@ -48,4 +49,4 @@ "branch": "tauri", "commit": "a6a2bcaaeadb8ad2a8320492640672dcdc1981f3" } -} \ No newline at end of file +} diff --git a/src-build/ci-createDistReleaseConfig.js b/src-build/ci-setupDistFolders.js similarity index 74% rename from src-build/ci-createDistReleaseConfig.js rename to src-build/ci-setupDistFolders.js index 746405d2..c0e8311a 100644 --- a/src-build/ci-createDistReleaseConfig.js +++ b/src-build/ci-setupDistFolders.js @@ -49,7 +49,7 @@ function replaceBundleIdentifierString(sourceStr, newIdentifier) { return sourceStr.replace(IDENTIFIER_PLACEHOLDER, newIdentifier); } -async function ciCreateDistReleaseConfig() { +function ciCreateTauriDistReleaseConfig() { const phoenixConfigPath = join(__dirname, '..', 'phoenix', 'dist', 'config.json'); const packageJSONPath = join(__dirname, '..', 'package.json'); const tauriTOMLPath = join(__dirname, '..', 'src-tauri', 'Cargo.toml'); @@ -133,4 +133,50 @@ async function ciCreateDistReleaseConfig() { return phoenixVersion; } -await ciCreateDistReleaseConfig(); +function createElectronReleaseAssets() { + console.log("=== Setting up Electron release assets ==="); + const projectRoot = join(__dirname, '..'); + const electronDir = join(projectRoot, 'src-electron'); + + // 1. Copy phoenix/dist/ to src-electron/phoenix-dist/ + const phoenixDistSrc = join(projectRoot, 'phoenix', 'dist'); + const phoenixDistDest = join(electronDir, 'phoenix-dist'); + console.log('Copying phoenix dist to:', phoenixDistDest); + // Remove existing and copy fresh + if (fs.existsSync(phoenixDistDest)) { + fs.rmSync(phoenixDistDest, { recursive: true }); + } + fs.cpSync(phoenixDistSrc, phoenixDistDest, { recursive: true }); + + // 2. Create config-effective.json based on environment + const configPath = join(electronDir, 'config.json'); + const configEffectivePath = join(electronDir, 'config-effective.json'); + + // Read phoenix/dist/config.json for environment + const phoenixDistConfigPath = join(projectRoot, 'phoenix', 'dist', 'config.json'); + const phoenixDistConfig = JSON.parse(fs.readFileSync(phoenixDistConfigPath)); + const environment = phoenixDistConfig.config.environment; // "dev", "stage", or "production" + + // Map environment to config file + const envConfigMap = { + 'dev': 'config-dev.json', + 'stage': 'config-staging.json', + 'production': 'config-prod.json' + }; + const envConfigFile = envConfigMap[environment] || 'config-dev.json'; + const envConfigPath = join(electronDir, envConfigFile); + + console.log(`Environment: ${environment} -> using ${envConfigFile}`); + + // Merge config.json + env-specific config + const baseConfig = JSON.parse(fs.readFileSync(configPath)); + const envConfig = JSON.parse(fs.readFileSync(envConfigPath)); + const effectiveConfig = { ...baseConfig, ...envConfig }; + + console.log('phoenixLoadURL:', effectiveConfig.phoenixLoadURL); + console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); + fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); +} + +ciCreateTauriDistReleaseConfig(); +createElectronReleaseAssets(); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 7e090fb1..0564025c 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -542,12 +542,12 @@ fn main() { std::process::exit(0); } #[cfg(target_os = "macos")]{ - tauri_plugin_deep_link::prepare("io.phcode"); + tauri_plugin_deep_link::prepare("io.phcode.dev"); } // warning: any string that resembles the following strings will be rewritten in source in prod by build scripts. // This is so that app bundle IDs are correct. IF they are app bundle IDs use the strings. else dont. - // do not use strings: "io.phcode.dev" "io.phcode.staging" "io.phcode" for anything other than bundle identifiers + // do not use strings: "TAURI_BUNDLE_IDENTIFIER_PLACE_HOLDER" "TAURI_BUNDLE_IDENTIFIER_PLACE_HOLDER" "io.phcode" for anything other than bundle identifiers // in this file!!! // GUI apps on macOS and Linux do not inherit the $PATH from your shell dotfiles (.bashrc, .bash_profile, .zshrc, etc). diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f5040f78..c044b0cc 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -3,7 +3,7 @@ "build": { "beforeBuildCommand": "", "devPath": "http://localhost:8000/src/", - "distDir": "../src/", + "distDir": "../phoenix/dist/", "withGlobalTauri": true }, "package": { @@ -434,8 +434,8 @@ ] }, { - "scheme": "http", - "domain": "localhost:8000", + "scheme": "https", + "domain": "dev.phcode.dev", "enableTauriAPI": true, "windows": [ "healthData" @@ -464,19 +464,20 @@ "width": 1366, "minWidth": 800, "acceptFirstMouse": true, - "fileDropEnabled": false + "fileDropEnabled": false, + "url": "phtauri://localhost/v5.1.0/" }, { "label": "healthData", "title": "Health data window", - "url": "http://localhost:8000/src/desktop-metrics.html", + "url": "https://dev.phcode.dev/desktop-metrics.html", "visible": false, "fileDropEnabled": false }, { "label": "fileDrop", "title": "Drop To Open Files", - "url": "http://localhost:8000/src/drop-files.html", + "url": "phtauri://localhost/v5.1.0/drop-files.html", "visible": false, "fileDropEnabled": true, "decorations": false From 233879175856554504b93a7e8cb955440388714b Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 18:33:30 +0530 Subject: [PATCH 767/864] refactor: remove unused tests targets that was never used --- .../workflows/prod-desktop-tests-on-pull.yml | 349 ------------------ .../staging-desktop-tests-on-pull.yml | 325 ---------------- 2 files changed, 674 deletions(-) delete mode 100644 .github/workflows/prod-desktop-tests-on-pull.yml delete mode 100644 .github/workflows/staging-desktop-tests-on-pull.yml diff --git a/.github/workflows/prod-desktop-tests-on-pull.yml b/.github/workflows/prod-desktop-tests-on-pull.yml deleted file mode 100644 index f6b153c4..00000000 --- a/.github/workflows/prod-desktop-tests-on-pull.yml +++ /dev/null @@ -1,349 +0,0 @@ -name: On pull request on prod Win/Mac/Linux run full tests suite - -on: - pull_request: - branches: [ prod ] - -jobs: - - testDesktopLinux: - runs-on: ubuntu-22.04 - timeout-minutes: 90 - steps: - - uses: actions/checkout@v4 - - name: setup node - uses: actions/setup-node@v4 - with: - node-version: 24 - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - - - name: install dependencies (ubuntu only) - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf - sudo apt install build-essential curl wget file libssl-dev libayatana-appindicator3-dev - sudo apt-get install xvfb - - - name: npm install ci deps - env: - GH_TOKEN: ${{ github.token }} - run: npm ci - - - name: Download phoenix and build build phoenix dist-test - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm run _ci-clonePhoenixForTests - cd .. - cd phoenix - npm ci - npm run build - npm run release:prod - - - name: build test runner - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm ci - npm run releaseDistTestDebug - - - name: Run tauri unit tests - uses: nick-fields/retry@v3 - id: linuxRunUnit - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - - - name: Run tauri integration tests - uses: nick-fields/retry@v3 - id: linuxRunIntegration - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - - - name: Run tauri mainview tests - uses: nick-fields/retry@v3 - id: linuxRunMainview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - - - name: Run tauri livepreview tests - uses: nick-fields/retry@v3 - id: linuxRunLivepreview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q - - - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v3 - id: linuxRunLegacyInteg - continue-on-error: true - with: - timeout_minutes: 20 - max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q - - - name: Fail on test runs failed in Linux (prod) - if: steps.linuxRunUnit.outcome == 'failure' || steps.linuxRunIntegration.outcome == 'failure' || steps.linuxRunMainview.outcome == 'failure' || steps.linuxRunLivepreview.outcome == 'failure' || steps.linuxRunLegacyInteg.outcome == 'failure' - run: | - echo "Linux (prod) tests failed, marking step as failed" - echo "Failed tests:" - if [ "${{ steps.linuxRunUnit.outcome }}" == "failure" ]; then - echo "- Run tauri unit tests" - fi - if [ "${{ steps.linuxRunIntegration.outcome }}" == "failure" ]; then - echo "- Run tauri integration tests" - fi - if [ "${{ steps.linuxRunMainview.outcome }}" == "failure" ]; then - echo "- Run tauri mainview tests" - fi - if [ "${{ steps.linuxRunLivepreview.outcome }}" == "failure" ]; then - echo "- Run tauri livepreview tests" - fi - if [ "${{ steps.linuxRunLegacyInteg.outcome }}" == "failure" ]; then - echo "- Run tauri LegacyInteg tests" - fi - exit 1 - - testDesktopMac: - runs-on: macos-15 - timeout-minutes: 90 - steps: - - uses: actions/checkout@v4 - - name: setup node - uses: actions/setup-node@v4 - with: - node-version: 24 - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - - - name: npm install ci deps - env: - GH_TOKEN: ${{ github.token }} - run: npm ci - - - name: Download phoenix and build build phoenix dist-test - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm run _ci-clonePhoenixForTests - cd .. - cd phoenix - npm ci - npm run build - npm run release:prod - - - name: build test runner - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm ci - npm run releaseDistTestDebug - - - name: Run tauri unit tests - uses: nick-fields/retry@v3 - id: macRunUnit - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - - - name: Run tauri integration tests - uses: nick-fields/retry@v3 - id: macRunIntegration - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - - - name: Run tauri mainview tests - uses: nick-fields/retry@v3 - id: macRunMainview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - - - name: Run tauri livepreview tests - uses: nick-fields/retry@v3 - id: macRunLivepreview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q - - - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v3 - id: macRunLegacyInteg - continue-on-error: true - with: - timeout_minutes: 30 - max_attempts: 3 - command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q - - - name: Fail on test runs failed in Mac (prod) - if: steps.macRunUnit.outcome == 'failure' || steps.macRunIntegration.outcome == 'failure' || steps.macRunMainview.outcome == 'failure' || steps.macRunLivepreview.outcome == 'failure' || steps.macRunLegacyInteg.outcome == 'failure' - run: | - echo "Mac (prod) tests failed, marking step as failed" - echo "Failed tests:" - if [ "${{ steps.macRunUnit.outcome }}" == "failure" ]; then - echo "- Run tauri unit tests" - fi - if [ "${{ steps.macRunIntegration.outcome }}" == "failure" ]; then - echo "- Run tauri integration tests" - fi - if [ "${{ steps.macRunMainview.outcome }}" == "failure" ]; then - echo "- Run tauri mainview tests" - fi - if [ "${{ steps.macRunLivepreview.outcome }}" == "failure" ]; then - echo "- Run tauri livepreview tests" - fi - if [ "${{ steps.macRunLegacyInteg.outcome }}" == "failure" ]; then - echo "- Run tauri LegacyInteg tests" - fi - exit 1 - - testDesktopWindows: - runs-on: windows-latest - timeout-minutes: 90 - steps: - - uses: actions/checkout@v4 - - name: setup node - uses: actions/setup-node@v4 - with: - node-version: 24 - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - - - name: npm install ci deps - env: - GH_TOKEN: ${{ github.token }} - run: npm ci - - - name: Download phoenix and build build phoenix dist-test - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm run _ci-clonePhoenixForTests - cd .. - cd phoenix - npm ci - npm run build - npm run release:prod - - - name: build test runner - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm ci - npm run releaseDistTestDebug - - - name: Run tauri unit tests in windows - # GUI apps in windows doesn't log on console. so we capture the output to a text file and print it, then fail on error. - uses: nick-fields/retry@v3 - id: windowsRunUnit - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=unit -q > output-unit.txt 2>&1 - shell: cmd - - - name: Print windows unit test output to console - run: type output-unit.txt - shell: cmd - - - name: Run tauri integration tests in windows - uses: nick-fields/retry@v3 - id: windowsRunIntegration - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=integration -q > output-integration.txt 2>&1 - shell: cmd - - - name: Print windows integration test output to console - run: type output-integration.txt - shell: cmd - - - name: Run tauri mainview tests in windows - uses: nick-fields/retry@v3 - id: windowsRunMainview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=mainview -q > output-mainview.txt 2>&1 - shell: cmd - - - name: Print windows mainview test output to console - run: type output-mainview.txt - shell: cmd - - - name: Run tauri livepreview tests in windows - uses: nick-fields/retry@v3 - id: windowsRunLivepreview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=livepreview -q > output-livepreview.txt 2>&1 - shell: cmd - - - name: Print windows livepreview test output to console - run: type output-livepreview.txt - shell: cmd - - - name: Run tauri LegacyInteg tests in windows - uses: nick-fields/retry@v3 - id: windowsRunLegacyInteg - continue-on-error: true - with: - timeout_minutes: 30 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=LegacyInteg -q > output-LegacyInteg.txt 2>&1 - shell: cmd - - - name: Print windows LegacyInteg test output to console - run: type output-LegacyInteg.txt - shell: cmd - - - name: Fail on test runs failed in windows - if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLivepreview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' - run: | - echo "Windows tests failed, marking step as failed" - exit 1 - shell: cmd diff --git a/.github/workflows/staging-desktop-tests-on-pull.yml b/.github/workflows/staging-desktop-tests-on-pull.yml deleted file mode 100644 index f31d55df..00000000 --- a/.github/workflows/staging-desktop-tests-on-pull.yml +++ /dev/null @@ -1,325 +0,0 @@ -name: On pull request on staging Win/Mac/Linux run full tests suite - -on: - pull_request: - branches: [ staging ] - -jobs: - - testDesktopLinux: - runs-on: ubuntu-22.04 - timeout-minutes: 90 - steps: - - uses: actions/checkout@v4 - - name: setup node - uses: actions/setup-node@v4 - with: - node-version: 24 - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - - - name: install dependencies (ubuntu only) - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf - sudo apt install build-essential curl wget file libssl-dev libayatana-appindicator3-dev - sudo apt-get install xvfb - - - name: npm install ci deps - env: - GH_TOKEN: ${{ github.token }} - run: npm ci - - - name: Download phoenix and build build phoenix dist-test - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm run _ci-clonePhoenixForTests - cd .. - cd phoenix - npm ci - npm run build - npm run release:staging - - - name: build test runner - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm ci - npm run releaseDistTestDebug - - - name: Run tauri unit tests - uses: nick-fields/retry@v3 - id: linuxRunUnit - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - - - name: Run tauri integration tests - uses: nick-fields/retry@v3 - id: linuxRunIntegration - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - - - name: Run tauri mainview tests - uses: nick-fields/retry@v3 - id: linuxRunMainview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - - - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v3 - id: linuxRunLegacyInteg - continue-on-error: true - with: - timeout_minutes: 20 - max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q - - - name: Fail on test runs failed in Linux (staging) - if: steps.linuxRunUnit.outcome == 'failure' || steps.linuxRunIntegration.outcome == 'failure' || steps.linuxRunMainview.outcome == 'failure' || steps.linuxRunLegacyInteg.outcome == 'failure' - run: | - echo "Linux (staging) tests failed, marking step as failed" - echo "Failed tests:" - if [ "${{ steps.linuxRunUnit.outcome }}" == "failure" ]; then - echo "- Run tauri unit tests" - fi - if [ "${{ steps.linuxRunIntegration.outcome }}" == "failure" ]; then - echo "- Run tauri integration tests" - fi - if [ "${{ steps.linuxRunMainview.outcome }}" == "failure" ]; then - echo "- Run tauri mainview tests" - fi - if [ "${{ steps.linuxRunLegacyInteg.outcome }}" == "failure" ]; then - echo "- Run tauri LegacyInteg tests" - fi - exit 1 - - testDesktopMac: - runs-on: macos-15 - timeout-minutes: 90 - steps: - - uses: actions/checkout@v4 - - name: setup node - uses: actions/setup-node@v4 - with: - node-version: 24 - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - - - name: npm install ci deps - env: - GH_TOKEN: ${{ github.token }} - run: npm ci - - - name: Download phoenix and build build phoenix dist-test - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm run _ci-clonePhoenixForTests - cd .. - cd phoenix - npm ci - npm run build - npm run release:staging - - - name: build test runner - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm ci - npm run releaseDistTestDebug - - - name: Run tauri unit tests - uses: nick-fields/retry@v3 - id: macRunUnit - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: ./src-tauri/target/debug/phoenix-test --run-tests=unit -q - - - name: Run tauri integration tests - uses: nick-fields/retry@v3 - id: macRunIntegration - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: ./src-tauri/target/debug/phoenix-test --run-tests=integration -q - - - name: Run tauri mainview tests - uses: nick-fields/retry@v3 - id: macRunMainview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q - - - name: Run tauri LegacyInteg tests - uses: nick-fields/retry@v3 - id: macRunLegacyInteg - continue-on-error: true - with: - timeout_minutes: 30 - max_attempts: 3 - command: ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q - - - name: Fail on test runs failed in Mac (staging) - if: steps.macRunUnit.outcome == 'failure' || steps.macRunIntegration.outcome == 'failure' || steps.macRunMainview.outcome == 'failure' || steps.macRunLegacyInteg.outcome == 'failure' - run: | - echo "Mac (staging) tests failed, marking step as failed" - echo "Failed tests:" - if [ "${{ steps.macRunUnit.outcome }}" == "failure" ]; then - echo "- Run tauri unit tests" - fi - if [ "${{ steps.macRunIntegration.outcome }}" == "failure" ]; then - echo "- Run tauri integration tests" - fi - if [ "${{ steps.macRunMainview.outcome }}" == "failure" ]; then - echo "- Run tauri mainview tests" - fi - if [ "${{ steps.macRunLegacyInteg.outcome }}" == "failure" ]; then - echo "- Run tauri LegacyInteg tests" - fi - exit 1 - - testDesktopWindows: - runs-on: windows-latest - timeout-minutes: 90 - steps: - - uses: actions/checkout@v4 - - name: setup node - uses: actions/setup-node@v4 - with: - node-version: 24 - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - - - name: npm install ci deps - env: - GH_TOKEN: ${{ github.token }} - run: npm ci - - - name: Download phoenix and build build phoenix dist-test - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm run _ci-clonePhoenixForTests - cd .. - cd phoenix - npm ci - npm run build - npm run release:staging - - - name: build test runner - env: - GH_TOKEN: ${{ github.token }} - PRO_REPO_URL: ${{ secrets.PRO_REPO_URL }} - PRO_REPO_ACCESS_TOKEN: ${{ secrets.PRO_REPO_ACCESS_TOKEN }} - run: | - npm ci - npm run releaseDistTestDebug - - - name: Run tauri unit tests in windows - # GUI apps in windows doesn't log on console. so we capture the output to a text file and print it, then fail on error. - uses: nick-fields/retry@v3 - id: windowsRunUnit - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=unit -q > output-unit.txt 2>&1 - shell: cmd - - - name: Print windows unit test output to console - run: type output-unit.txt - shell: cmd - - - name: Run tauri integration tests in windows - uses: nick-fields/retry@v3 - id: windowsRunIntegration - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=integration -q > output-integration.txt 2>&1 - shell: cmd - - - name: Print windows integration test output to console - run: type output-integration.txt - shell: cmd - - - name: Run tauri mainview tests in windows - uses: nick-fields/retry@v3 - id: windowsRunMainview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=mainview -q > output-mainview.txt 2>&1 - shell: cmd - - - name: Print windows mainview test output to console - run: type output-mainview.txt - shell: cmd - - - name: Run tauri livepreview tests in windows - uses: nick-fields/retry@v3 - id: windowsRunLivepreview - continue-on-error: true - with: - timeout_minutes: 12 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=livepreview -q > output-livepreview.txt 2>&1 - shell: cmd - - - name: Print windows livepreview test output to console - run: type output-livepreview.txt - shell: cmd - - - name: Run tauri LegacyInteg tests in windows - uses: nick-fields/retry@v3 - id: windowsRunLegacyInteg - continue-on-error: true - with: - timeout_minutes: 30 - max_attempts: 3 - command: .\src-tauri\target\debug\phoenix-test.exe --run-tests=LegacyInteg -q > output-LegacyInteg.txt 2>&1 - shell: cmd - - - name: Print windows LegacyInteg test output to console - run: type output-LegacyInteg.txt - shell: cmd - - - name: Fail on test runs failed in windows - if: steps.windowsRunUnit.outcome == 'failure' || steps.windowsRunIntegration.outcome == 'failure' || steps.windowsRunMainview.outcome == 'failure' || steps.windowsRunLivepreview.outcome == 'failure' || steps.windowsRunLegacyInteg.outcome == 'failure' - run: | - echo "Windows tests failed, marking step as failed" - exit 1 - shell: cmd From 0ea57762f10c966aef06b98177e3020e9b920221 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 18:40:13 +0530 Subject: [PATCH 768/864] cli arg to print --version or -v match with tauri output --- src-electron/main.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src-electron/main.js b/src-electron/main.js index cf684ee2..c7c2a51d 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -8,7 +8,13 @@ const { registerCredIpcHandlers } = require('./main-cred-ipc'); const { registerWindowIpcHandlers, registerWindow, setOnAllWindowsClosed } = require('./main-window-ipc'); const { assertTrusted } = require('./ipc-security'); const { getWindowOptions, trackWindowState, DEFAULTS } = require('./window-state'); -const { phoenixLoadURL, gaMetricsURL } = require('./config'); +const { phoenixLoadURL, gaMetricsURL, version, productName } = require('./config'); + +// Handle --version / -v flag before any Electron initialization +if (process.argv.includes('-v') || process.argv.includes('--version')) { + console.log(`${version}`); + process.exit(0); +} // Register phtauri:// as a privileged scheme (must be done before app ready) // This enables standard web features: fetch, localStorage, cookies, etc. From 52bc58db9aad2307444cc1202f7b008787f19b18 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 18:53:18 +0530 Subject: [PATCH 769/864] match appimage bin naming with existing convention --- src-electron/electron-builder.yml | 2 +- src-electron/package.json | 2 +- src-electron/renameBin.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 src-electron/renameBin.js diff --git a/src-electron/electron-builder.yml b/src-electron/electron-builder.yml index 6da2ed24..dd80d342 100644 --- a/src-electron/electron-builder.yml +++ b/src-electron/electron-builder.yml @@ -1,5 +1,5 @@ appId: io.phcode.dev -productName: Phoenix Code +productName: phoenix-code copyright: Copyright © 2024 phcode.dev asar: true diff --git a/src-electron/package.json b/src-electron/package.json index a2dd9c32..0486a86e 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -8,7 +8,7 @@ "description": "Phoenix Code Experimental Build", "main": "main.js", "scripts": { - "build:appimage": "electron-builder --linux AppImage" + "build:appimage": "electron-builder --linux AppImage && node renameBin.js" }, "dependencies": { "keytar": "^7.9.0" diff --git a/src-electron/renameBin.js b/src-electron/renameBin.js new file mode 100644 index 00000000..d886f6c0 --- /dev/null +++ b/src-electron/renameBin.js @@ -0,0 +1,30 @@ +const fs = require('fs'); +const path = require('path'); + +// Read config-effective.json for productName and version +const configPath = path.join(__dirname, 'config-effective.json'); +const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); + +const productName = config.productName; +const version = config.version; + +// Transform "Phoenix Code Experimental Build" → "phoenix-code-experimental-build" +const artifactBaseName = productName.toLowerCase().replace(/\s+/g, '-'); + +// Find the built AppImage in dist/ folder +const distDir = path.join(__dirname, 'dist'); +const files = fs.readdirSync(distDir); +const appImageFile = files.find(f => f.endsWith('.AppImage')); + +if (!appImageFile) { + console.error('No AppImage found in dist/'); + process.exit(1); +} + +const oldPath = path.join(distDir, appImageFile); +const newName = `${artifactBaseName}_${version}.AppImage`; +const newPath = path.join(distDir, newName); + +console.log(`Renaming: ${appImageFile} → ${newName}`); +fs.renameSync(oldPath, newPath); +console.log(`Done: ${newPath}`); From 96c84b80098832ef4bbcbc4e68ba9a094f665403 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 20:05:54 +0530 Subject: [PATCH 770/864] fix: relative urls not opening corectly --- src-electron/config-prod.json | 1 + src-electron/main-window-ipc.js | 20 +++++++++++++++++--- src-electron/main.js | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src-electron/config-prod.json b/src-electron/config-prod.json index bcb80e94..56d98e69 100644 --- a/src-electron/config-prod.json +++ b/src-electron/config-prod.json @@ -3,5 +3,6 @@ "stage": "production", "productName": "Phoenix Code", "phoenixLoadURL": "phtauri://localhost/", + "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/"], "gaMetricsURL": "https://phcode.dev/desktop-metrics.html" } diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index da8332b8..78497bdc 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -93,14 +93,25 @@ function registerWindowIpcHandlers() { const prefix = isExtension ? PHOENIX_EXTENSION_WINDOW_PREFIX : PHOENIX_WINDOW_PREFIX; const label = getNextLabel(prefix); + // Resolve relative URLs based on the sender's current URL + let resolvedUrl = url; + if (!url.startsWith('http://') && !url.startsWith('https://') && !url.startsWith('file://')) { + const senderUrl = event.sender.getURL(); + if (senderUrl) { + resolvedUrl = new URL(url, senderUrl).href; + } + } + + console.log(`Creating window ${label} with URL ${resolvedUrl}, isTrustedOrigin=${isTrustedOrigin(resolvedUrl)}`); + const webPreferences = { contextIsolation: true, nodeIntegration: false, sandbox: true }; - // Only inject preload for Phoenix windows with trusted URLs, not extensions - if (!isExtension && isTrustedOrigin(url)) { + // Only inject preload for Phoenix windows with trusted URLs + if (isTrustedOrigin(resolvedUrl)) { webPreferences.preload = path.join(__dirname, 'preload.js'); } @@ -133,13 +144,16 @@ function registerWindowIpcHandlers() { webPreferences }); + // uncomment line below if you want to open dev tools at app start + // win.webContents.openDevTools(); + // Track window state for Phoenix windows (not extensions) if (!isExtension) { trackWindowState(win); } registerWindow(win, label); - await win.loadURL(url); + await win.loadURL(resolvedUrl); return label; }); diff --git a/src-electron/main.js b/src-electron/main.js index c7c2a51d..4cf8bcf0 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -78,7 +78,7 @@ async function createMetricsWindow() { }); metricsWindow.loadURL(gaMetricsURL); // uncomment line below if you want to open dev tools at app start - metricsWindow.webContents.openDevTools(); + // metricsWindow.webContents.openDevTools(); } async function createWindow() { From 07cf7acf733b20f3324ceef5ca34067532f704dc Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 21:37:31 +0530 Subject: [PATCH 771/864] fix: dont log electron 404 in console --- src-electron/main.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src-electron/main.js b/src-electron/main.js index 4cf8bcf0..996af054 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -2,6 +2,16 @@ const { app, BrowserWindow, protocol, Menu, ipcMain, net } = require('electron') const path = require('path'); const fs = require('fs'); +// Suppress Electron's noisy "Failed to load URL" stderr messages for subframe load failures +const originalStderrWrite = process.stderr.write.bind(process.stderr); +process.stderr.write = (chunk, encoding, callback) => { + const str = typeof chunk === 'string' ? chunk : chunk.toString(); + if (str.includes('electron: Failed to load URL:')) { + return true; // Suppress this message + } + return originalStderrWrite(chunk, encoding, callback); +}; + const { registerAppIpcHandlers, terminateAllProcesses, filterCliArgs } = require('./main-app-ipc'); const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc'); const { registerCredIpcHandlers } = require('./main-cred-ipc'); From 436409d00287e07429d2c2043544035197b23422 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 30 Jan 2026 22:53:27 +0530 Subject: [PATCH 772/864] chore: match asset protocol handling in electron to tauris impl --- src-electron/main.js | 6 +++++- src-electron/preload.js | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src-electron/main.js b/src-electron/main.js index 996af054..1885c285 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -266,7 +266,11 @@ app.whenReady().then(async () => { try { const url = new URL(request.url); // Decode the path from URL encoding - const requestedPath = decodeURIComponent(url.pathname.substring(1)); // Remove leading / + let requestedPath = decodeURIComponent(url.pathname); + // On Windows, URL pathname has extra leading / before drive letter (e.g., /C:/...) + if (/^\/[A-Z]:/i.test(requestedPath)) { + requestedPath = requestedPath.substring(1); + } const normalizedRequested = path.normalize(requestedPath); const normalizedAssetsDir = path.normalize(assetsDir); diff --git a/src-electron/preload.js b/src-electron/preload.js index ce30dd2b..388301e7 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -71,7 +71,9 @@ contextBridge.exposeInMainWorld('electronAPI', { if (!platformPath) return null; // Normalize path separators to forward slashes for URL const normalizedPath = platformPath.replace(/\\/g, '/'); - return `asset://localhost/${encodeURIComponent(normalizedPath)}`; + // Encode each path segment individually to preserve URL path structure (like Tauri's convertFileSrc) + const encodedPath = normalizedPath.split('/').map(segment => encodeURIComponent(segment)).join('/'); + return `asset://localhost${encodedPath}`; }, // Set zoom factor on the webview (mirrors Tauri's zoom_window) From 680ea693877f238d2460ff1566f32fd423e60fae Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 31 Jan 2026 12:12:37 +0530 Subject: [PATCH 773/864] test: fix issues raised by test fialures --- src-electron/ipc-security.js | 7 ++++++- src-electron/main-cred-ipc.js | 36 ++++++++++++++++++++++++++------- src-electron/main-window-ipc.js | 11 ++++++++++ src-electron/main.js | 11 +++++++++- src-electron/preload.js | 1 + 5 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src-electron/ipc-security.js b/src-electron/ipc-security.js index 6d75afd1..3fe94ebb 100644 --- a/src-electron/ipc-security.js +++ b/src-electron/ipc-security.js @@ -30,10 +30,15 @@ function isTrustedOrigin(url) { } } - // In dev stage, also allow localhost URLs + // In dev stage, also allow localhost URLs (but NOT asset:// protocol) + // asset:// is for static file serving only and should never have API access if (stage === 'dev') { try { const parsed = new URL(url); + // Exclude asset:// protocol - it's sandboxed like Tauri's asset protocol + if (parsed.protocol === 'asset:') { + return false; + } if (parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1') { return true; } diff --git a/src-electron/main-cred-ipc.js b/src-electron/main-cred-ipc.js index cbe613cd..f05ebca1 100644 --- a/src-electron/main-cred-ipc.js +++ b/src-electron/main-cred-ipc.js @@ -48,7 +48,8 @@ function registerCredIpcHandlers() { const stored = windowTrustMap.get(webContentsId); if (!stored) { - throw new Error('No trust established for this window.'); + // Match Tauri's error message + throw new Error('No trust association found for this window.'); } if (stored.key !== key || stored.iv !== iv) { throw new Error('Provided key and IV do not match.'); @@ -59,6 +60,10 @@ function registerCredIpcHandlers() { console.log(`AES trust removed for window: ${getWindowLabel(webContentsId)} (webContentsId: ${webContentsId})`); }); + // Special marker for empty string credentials (keytar doesn't allow empty passwords) + // Using a unique string that's unlikely to be a real credential value + const EMPTY_CREDENTIAL_MARKER = '___PHCODE_EMPTY_CREDENTIAL_MARKER___'; + // Store credential in system keychain ipcMain.handle('store-credential', async (event, scopeName, secretVal) => { assertTrusted(event); @@ -66,7 +71,11 @@ function registerCredIpcHandlers() { throw new Error('keytar module not available.'); } const service = PHOENIX_CRED_PREFIX + scopeName; - await keytar.setPassword(service, process.env.USER || 'user', secretVal); + // Handle empty strings by storing a special marker (keytar requires non-empty passwords) + // Check for empty string, null, or undefined - all become the marker + const isEmpty = secretVal === '' || secretVal === null || secretVal === undefined; + const valueToStore = isEmpty ? EMPTY_CREDENTIAL_MARKER : secretVal; + await keytar.setPassword(service, process.env.USER || 'user', valueToStore); }); // Get credential (encrypted with window's AES key) @@ -79,15 +88,22 @@ function registerCredIpcHandlers() { const webContentsId = event.sender.id; const trustData = windowTrustMap.get(webContentsId); if (!trustData) { - throw new Error('Trust needs to be established first.'); + // Match Tauri's error message + throw new Error('Trust needs to be first established for this window to get or set credentials.'); } const service = PHOENIX_CRED_PREFIX + scopeName; - const credential = await keytar.getPassword(service, process.env.USER || 'user'); - if (!credential) { + const account = process.env.USER || 'user'; + let credential = await keytar.getPassword(service, account); + if (credential === null || credential === undefined) { return null; } + // Convert empty credential marker back to empty string + if (credential === EMPTY_CREDENTIAL_MARKER) { + credential = ''; + } + // Encrypt with AES-256-GCM (same as Tauri) const keyBytes = Buffer.from(trustData.key, 'hex'); const ivBytes = Buffer.from(trustData.iv, 'hex'); @@ -96,7 +112,9 @@ function registerCredIpcHandlers() { encrypted += cipher.final('hex'); const authTag = cipher.getAuthTag().toString('hex'); - return encrypted + authTag; // Return ciphertext + authTag as hex string + // For empty credentials, encrypted will be empty string, but authTag will still be present + const result = encrypted + authTag; + return result; }); // Delete credential from system keychain @@ -106,7 +124,11 @@ function registerCredIpcHandlers() { throw new Error('keytar module not available.'); } const service = PHOENIX_CRED_PREFIX + scopeName; - await keytar.deletePassword(service, process.env.USER || 'user'); + const deleted = await keytar.deletePassword(service, process.env.USER || 'user'); + // Match Tauri's behavior: throw if credential didn't exist + if (!deleted) { + throw new Error('No matching entry found in secure storage'); + } }); } diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 78497bdc..6e445ad1 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -167,6 +167,17 @@ function registerWindowIpcHandlers() { } }); + // Close a window by its label + ipcMain.handle('close-window-by-label', async (event, label) => { + assertTrusted(event); + const win = windowRegistry.get(label); + if (win && !win.isDestroyed()) { + win.close(); + return true; + } + return false; + }); + // Focus current window and bring to front ipcMain.handle('focus-window', (event) => { assertTrusted(event); diff --git a/src-electron/main.js b/src-electron/main.js index 1885c285..082e73b2 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -26,7 +26,7 @@ if (process.argv.includes('-v') || process.argv.includes('--version')) { process.exit(0); } -// Register phtauri:// as a privileged scheme (must be done before app ready) +// Register custom schemes as privileged (must be done before app ready) // This enables standard web features: fetch, localStorage, cookies, etc. protocol.registerSchemesAsPrivileged([ { @@ -38,6 +38,15 @@ protocol.registerSchemesAsPrivileged([ corsEnabled: true, stream: true } + }, + { + // asset:// is for serving static files only - minimal privileges to match Tauri's security posture + // No standard/secure/corsEnabled - just enough for fetch() to read local assets + scheme: 'asset', + privileges: { + supportFetchAPI: true, + stream: true + } } ]); diff --git a/src-electron/preload.js b/src-electron/preload.js index 388301e7..5a80b252 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -105,6 +105,7 @@ contextBridge.exposeInMainWorld('electronAPI', { getCurrentWindowLabel: () => ipcRenderer.invoke('get-current-window-label'), createPhoenixWindow: (url, options) => ipcRenderer.invoke('create-phoenix-window', url, options), closeWindow: () => ipcRenderer.invoke('close-window'), + closeWindowByLabel: (label) => ipcRenderer.invoke('close-window-by-label', label), quitApp: (exitCode) => ipcRenderer.invoke('quit-app', exitCode), focusWindow: () => ipcRenderer.invoke('focus-window'), From 094622db80614e942b5a55eec26bafb5207ccfd7 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 31 Jan 2026 13:55:37 +0530 Subject: [PATCH 774/864] feat: electron window event passing apis --- src-electron/main-window-ipc.js | 23 +++++++++++++++++++++++ src-electron/preload.js | 14 ++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 6e445ad1..f244ccf7 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -192,6 +192,29 @@ function registerWindowIpcHandlers() { } }); + // Inter-window event system (mirrors Tauri's event system) + // Send event to a specific window by label + ipcMain.handle('emit-to-window', (event, targetLabel, eventName, payload) => { + assertTrusted(event); + const targetWin = windowRegistry.get(targetLabel); + if (targetWin && !targetWin.isDestroyed()) { + targetWin.webContents.send('window-event', { eventName, payload }); + return true; + } + return false; + }); + + // Broadcast event to all windows + ipcMain.handle('emit-to-all-windows', (event, eventName, payload) => { + assertTrusted(event); + const senderLabel = webContentsToLabel.get(event.sender.id); + for (const [label, win] of windowRegistry) { + if (!win.isDestroyed() && label !== senderLabel) { + win.webContents.send('window-event', { eventName, payload }); + } + } + }); + // Get process ID ipcMain.handle('get-process-id', (event) => { assertTrusted(event); diff --git a/src-electron/preload.js b/src-electron/preload.js index 5a80b252..6ef2ef49 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -109,6 +109,20 @@ contextBridge.exposeInMainWorld('electronAPI', { quitApp: (exitCode) => ipcRenderer.invoke('quit-app', exitCode), focusWindow: () => ipcRenderer.invoke('focus-window'), + // Inter-window event system (mirrors Tauri's event system) + emitToWindow: (targetLabel, eventName, payload) => ipcRenderer.invoke('emit-to-window', targetLabel, eventName, payload), + emitToAllWindows: (eventName, payload) => ipcRenderer.invoke('emit-to-all-windows', eventName, payload), + onWindowEvent: (eventName, callback) => { + const handler = (event, data) => { + if (data.eventName === eventName) { + callback(data.payload); + } + }; + ipcRenderer.on('window-event', handler); + // Return unlisten function (like Tauri) + return () => ipcRenderer.removeListener('window-event', handler); + }, + // Process and platform info getProcessId: () => ipcRenderer.invoke('get-process-id'), getPlatformArch: () => ipcRenderer.invoke('get-platform-arch'), From c527ad0925fe5accdb3239277dabb253492b3e1f Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 10:48:32 +0530 Subject: [PATCH 775/864] ci: electron test runners in gihub actions linux --- .github/workflows/desktop-linux-test-pull.yml | 13 ++++++------- src-build/createDistTestRelease.js | 2 +- src-electron/package.json | 4 +++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index f1a77ef0..c174f2e2 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -25,8 +25,7 @@ jobs: - name: install dependencies (ubuntu only) run: | sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf - sudo apt install build-essential curl wget file libssl-dev libayatana-appindicator3-dev + sudo apt install build-essential curl wget file libssl-dev sudo apt-get install xvfb - name: npm install ci deps @@ -63,7 +62,7 @@ jobs: with: timeout_minutes: 12 max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=unit -q + command: xvfb-run src-electron/dist/phoenix-test-runner.appimage --run-tests=unit -q - name: Run tauri integration tests uses: nick-fields/retry@v3 @@ -72,7 +71,7 @@ jobs: with: timeout_minutes: 12 max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=integration -q + command: xvfb-run src-electron/dist/phoenix-test-runner.appimage --run-tests=integration -q - name: Run tauri mainview tests uses: nick-fields/retry@v3 @@ -81,7 +80,7 @@ jobs: with: timeout_minutes: 12 max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=mainview -q + command: xvfb-run src-electron/dist/phoenix-test-runner.appimage --run-tests=mainview -q - name: Run tauri livepreview tests uses: nick-fields/retry@v3 @@ -90,7 +89,7 @@ jobs: with: timeout_minutes: 12 max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=livepreview -q + command: xvfb-run src-electron/dist/phoenix-test-runner.appimage --run-tests=livepreview -q - name: Run tauri LegacyInteg tests uses: nick-fields/retry@v3 @@ -99,7 +98,7 @@ jobs: with: timeout_minutes: 20 max_attempts: 3 - command: xvfb-run ./src-tauri/target/debug/phoenix-test --run-tests=LegacyInteg -q + command: xvfb-run src-electron/dist/phoenix-test-runner.appimage --run-tests=LegacyInteg -q - name: Fail on test runs failed in Linux if: steps.linuxRunUnit.outcome == 'failure' || steps.linuxRunIntegration.outcome == 'failure' || steps.linuxRunMainview.outcome == 'failure' || steps.linuxRunLivepreview.outcome == 'failure' || steps.linuxRunLegacyInteg.outcome == 'failure' diff --git a/src-build/createDistTestRelease.js b/src-build/createDistTestRelease.js index 90fce2d0..9c70123b 100644 --- a/src-build/createDistTestRelease.js +++ b/src-build/createDistTestRelease.js @@ -171,7 +171,7 @@ function buildElectron() { // Build AppImage console.log('Building AppImage...'); - run('npm run build:appimage', { cwd: join(projectRoot, 'src-electron') }); + run('npm run build:appimageForTest', { cwd: join(projectRoot, 'src-electron') }); } async function main() { diff --git a/src-electron/package.json b/src-electron/package.json index 0486a86e..1338d0de 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -8,7 +8,9 @@ "description": "Phoenix Code Experimental Build", "main": "main.js", "scripts": { - "build:appimage": "electron-builder --linux AppImage && node renameBin.js" + "clean:appimage": "shx rm -rf dist/*.AppImage", + "build:appimage": "npm run clean:appimage && electron-builder --linux AppImage && node renameBin.js", + "build:appimageForTest": "npm run clean:appimage && electron-builder --linux AppImage && shx mv dist/*.AppImage dist/phoenix-test-runner.appimage" }, "dependencies": { "keytar": "^7.9.0" From 75040fb05a594b6b4e6deb373ed3d40cf7878b09 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 10:56:37 +0530 Subject: [PATCH 776/864] fix: electron build in actions fails as its trying to resolve app updaters --- src-electron/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-electron/package.json b/src-electron/package.json index 1338d0de..391abf08 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -9,8 +9,8 @@ "main": "main.js", "scripts": { "clean:appimage": "shx rm -rf dist/*.AppImage", - "build:appimage": "npm run clean:appimage && electron-builder --linux AppImage && node renameBin.js", - "build:appimageForTest": "npm run clean:appimage && electron-builder --linux AppImage && shx mv dist/*.AppImage dist/phoenix-test-runner.appimage" + "build:appimage": "npm run clean:appimage && electron-builder --linux AppImage --publish never && node renameBin.js", + "build:appimageForTest": "npm run clean:appimage && electron-builder --linux AppImage --publish never && shx mv dist/*.AppImage dist/phoenix-test-runner.appimage" }, "dependencies": { "keytar": "^7.9.0" From d49b99450f3a10bcb64005a3486eb947a1e6e4ba Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 11:03:33 +0530 Subject: [PATCH 777/864] fix: electron build in actions fails as its trying to resolve app updaters --- src-electron/electron-builder.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src-electron/electron-builder.yml b/src-electron/electron-builder.yml index dd80d342..8ba1d295 100644 --- a/src-electron/electron-builder.yml +++ b/src-electron/electron-builder.yml @@ -30,3 +30,5 @@ extraResources: extraMetadata: main: main.js + +publish: null From 0977fe62429af59b741e4340b04a1074b305de78 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 11:04:38 +0530 Subject: [PATCH 778/864] ci: we no longer need to install rust as we scwitched to electron --- .github/workflows/desktop-linux-test-pull.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index c174f2e2..1bb72be5 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -17,10 +17,6 @@ jobs: uses: actions/setup-node@v4 with: node-version: 24 - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - name: install dependencies (ubuntu only) run: | From 2bbb474c00fc22b69a127a7966c03e586a3b2888 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 11:09:55 +0530 Subject: [PATCH 779/864] ci: libfuse is needed for appimage to run --- .github/workflows/desktop-linux-test-pull.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/desktop-linux-test-pull.yml b/.github/workflows/desktop-linux-test-pull.yml index 1bb72be5..0056f9a0 100644 --- a/.github/workflows/desktop-linux-test-pull.yml +++ b/.github/workflows/desktop-linux-test-pull.yml @@ -23,6 +23,8 @@ jobs: sudo apt-get update sudo apt install build-essential curl wget file libssl-dev sudo apt-get install xvfb + # libfuse2 is required for AppImages to run + sudo apt-get install libfuse2 - name: npm install ci deps env: From d540d0f64fe490ded0f397ee49fe7a8568706e9e Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 11:52:47 +0530 Subject: [PATCH 780/864] fix: elefctron app wont exit with non-0 exit codes --- src-electron/main.js | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src-electron/main.js b/src-electron/main.js index 082e73b2..386314bf 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -137,10 +137,26 @@ async function createWindow() { win.loadURL(phoenixLoadURL); } +let isShuttingDown = false; +let pendingExitCode = 0; + async function gracefulShutdown(exitCode = 0) { + // If non-zero exit code, always update (failure takes precedence) + if (exitCode !== 0) { + pendingExitCode = exitCode; + } + if (isShuttingDown) { + return; // Already shutting down + } + isShuttingDown = true; console.log('Initiating graceful shutdown...'); - await terminateAllProcesses(); - app.exit(exitCode); + try { + await terminateAllProcesses(); + app.exit(pendingExitCode); + } catch (err) { + console.error('Error during shutdown:', err); + app.exit(pendingExitCode || 1); + } } // Register all IPC handlers @@ -314,6 +330,6 @@ app.on('activate', () => { } }); -// Handle process termination signals -process.on('SIGINT', () => gracefulShutdown(0)); -process.on('SIGTERM', () => gracefulShutdown(0)); +// Handle process termination signals (exit 128+signal per Unix convention) +process.on('SIGINT', () => gracefulShutdown(130)); // 128 + 2 +process.on('SIGTERM', () => gracefulShutdown(143)); // 128 + 15 From 99077bfe23ecdb6955709f6bcfce6901fa3ed0a5 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 14:17:32 +0530 Subject: [PATCH 781/864] ci: geenrate linux release bins and on release hooks for updates --- .github/workflows/tauri-build-dev.yml | 69 ++++++++++++------------- .github/workflows/updateNotification.js | 33 ++++++++++++ 2 files changed, 66 insertions(+), 36 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index c978ff1f..420612f7 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -277,12 +277,7 @@ jobs: permissions: contents: write timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - platform: [ ubuntu-22.04] - - runs-on: ${{ matrix.platform }} + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: get Git Tag @@ -293,20 +288,6 @@ jobs: with: node-version: 24 - - name: GLIBC version - run: | - ldd --version - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - - name: install dependencies (ubuntu only) - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - sudo apt-get install -y libwebrtc-audio-processing-dev - sudo apt-get install -y libunwind-dev - sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} @@ -315,25 +296,41 @@ jobs: run: | npm ci npm run _ci-release:dev - npm run tauri build - ls -alh ./src-tauri/target/release - mkdir ./src-tauri/target/release/phoenix-code - cp ./src-tauri/target/release/phoenix-code-experimental-build ./src-tauri/target/release/phoenix-code - cp ./src-build/linux/install-readme.txt ./src-tauri/target/release/phoenix-code/readme.txt - cp ./src-tauri/target/release/phnode ./src-tauri/target/release/phoenix-code - cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/phoenix-code - ls -alh ./src-tauri/target/release/phoenix-code - tar -cvzf phoenix-code.tar.gz -C ./src-tauri/target/release phoenix-code - ls -alh phoenix-code.tar.gz - GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') - OUTPUT_FILENAME="phoenix-code-experimental-build_$(node -p "require('./package.json').version")_amd64_linux_bin-GLIBC-${GLIBC_VER}.tar.gz" - mv phoenix-code.tar.gz "$OUTPUT_FILENAME" - echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV - ls + npm run _ci-releaseElectronApp + ls -alh ./src-electron/dist/ + echo "OUTPUT_FILENAME=$(ls ./src-electron/dist/*.AppImage | head -1 | xargs basename)" >> $GITHUB_ENV + + - name: Sign AppImage with minisign + env: + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + run: | + # Install minisign + sudo apt-get update && sudo apt-get install -y minisign + + # Write private key to temp file + echo "$TAURI_PRIVATE_KEY" > /tmp/tauri_private.key + + # Sign the AppImage + APPIMAGE_PATH="./src-electron/dist/${{ env.OUTPUT_FILENAME }}" + echo "$TAURI_KEY_PASSWORD" | minisign -S -s /tmp/tauri_private.key -m "$APPIMAGE_PATH" -t "$(date +%s) file:${{ env.OUTPUT_FILENAME }}" + + # Clean up private key + rm /tmp/tauri_private.key + + # Show signature file + echo "Signature file contents:" + cat "${APPIMAGE_PATH}.minisig" + + # Rename .minisig to .sig for consistency + mv "${APPIMAGE_PATH}.minisig" "${APPIMAGE_PATH}.sig" + - name: Upload Release Asset uses: softprops/action-gh-release@v2 with: - files: ${{ env.OUTPUT_FILENAME }} + files: | + ./src-electron/dist/${{ env.OUTPUT_FILENAME }} + ./src-electron/dist/${{ env.OUTPUT_FILENAME }}.sig tag_name: ${{ env.GIT_TAG_NAME }} draft: true env: diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js index 2670c54d..a26bc264 100644 --- a/.github/workflows/updateNotification.js +++ b/.github/workflows/updateNotification.js @@ -87,6 +87,10 @@ const WINDOWS_X64_NAME_SUFFIX = "_x64-setup.exe"; const MAC_INTEL_NAME_SUFFIX = "_x64.dmg"; // "Phoenix.Code.Experimental.Build_3.4.2_aarch64.dmg" const MAC_M1_NAME_SUFFIX = "_aarch64.dmg"; +// "phoenix-code-experimental-build_3.4.2.AppImage" +const LINUX_APPIMAGE_NAME_SUFFIX = ".AppImage"; +// "phoenix-code-experimental-build_3.4.2.AppImage.sig" +const LINUX_APPIMAGE_SIG_SUFFIX = ".AppImage.sig"; function _getDownloadURLByNameSuffix(releaseAssets, suffix) { for(let releaseAsset of releaseAssets) { if(releaseAsset.name.endsWith(suffix)){ @@ -163,6 +167,26 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) console.log("Updating tauri update JSON file: ", _identifyUpdateJSONPath(releaseAssets)); const latestJSON = JSON.parse(await _getLatestJson(releaseAssets)); latestJSON.notes = releaseNotes; + + // Add Linux AppImage to platforms (Electron build with minisign signature) + try { + const linuxAppImageURL = _getDownloadURLByNameSuffix(releaseAssets, LINUX_APPIMAGE_NAME_SUFFIX); + let linuxSignature = ""; + try { + const sigFileURL = _getDownloadURLByNameSuffix(releaseAssets, LINUX_APPIMAGE_SIG_SUFFIX); + linuxSignature = await _getTextHTTPS(sigFileURL); + console.log("Linux AppImage signature: ", linuxSignature); + } catch (sigErr) { + console.warn("Linux AppImage signature file not found, using empty signature"); + } + latestJSON.platforms["linux-x86_64"] = { + "signature": linuxSignature, + "url": linuxAppImageURL + }; + } catch (e) { + console.warn("Linux AppImage not found in release assets, skipping linux-x86_64 platform"); + } + const latestJsonPath = `${githubWorkspaceRoot}/docs/${_identifyUpdateJSONPath(releaseAssets)}`; const currentVersion = getCurrentVersion(latestJsonPath); const latestVersion = latestJSON.version; @@ -179,6 +203,12 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) const windowsDownloadURL = _getDownloadURLByNameSuffix(releaseAssets, WINDOWS_X64_NAME_SUFFIX); const macM1DownloadURL = _getDownloadURLByNameSuffix(releaseAssets, MAC_M1_NAME_SUFFIX); const macIntelDownloadURL = _getDownloadURLByNameSuffix(releaseAssets, MAC_INTEL_NAME_SUFFIX); + let linuxAppImageURL = null; + try { + linuxAppImageURL = _getDownloadURLByNameSuffix(releaseAssets, LINUX_APPIMAGE_NAME_SUFFIX); + } catch (e) { + console.warn("Linux AppImage not found in release assets, skipping linux_appimage in install.json"); + } let installJSON = { "phcode.io.DownloadURL": { "windows_x64": windowsDownloadURL, @@ -187,6 +217,9 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa" } }; + if (linuxAppImageURL) { + installJSON["phcode.io.DownloadURL"]["linux_appimage"] = linuxAppImageURL; + } installJSON = JSON.stringify(installJSON, null, 4); console.log("writing install.json to path: ", installJsonPath, " contents: ", installJSON) fs.writeFileSync(installJsonPath, installJSON); From e9313cebe0a3d3ff238ecd4ca0ee1dbe16819ebc Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 14:29:03 +0530 Subject: [PATCH 782/864] ci: prod and staging release, minisign not present in ubuntu --- .github/workflows/tauri-build-dev.yml | 7 ++- .github/workflows/tauri-build-prod.yml | 75 +++++++++++------------ .github/workflows/tauri-build-staging.yml | 73 +++++++++++----------- 3 files changed, 79 insertions(+), 76 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 420612f7..38ae4a3b 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -305,8 +305,11 @@ jobs: TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} run: | - # Install minisign - sudo apt-get update && sudo apt-get install -y minisign + # Download and install minisign + wget https://github.com/jedisct1/minisign/releases/download/0.11/minisign-0.11-linux.tar.gz + tar -xzf minisign-0.11-linux.tar.gz + sudo mv minisign-linux/x86_64/minisign /usr/local/bin/ + minisign -v # Write private key to temp file echo "$TAURI_PRIVATE_KEY" > /tmp/tauri_private.key diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 840757f6..d5f0c68d 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -326,35 +326,17 @@ jobs: permissions: contents: write timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - platform: [ ubuntu-22.04] - - runs-on: ${{ matrix.platform }} + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: get Git Tag + shell: bash run: echo "GIT_TAG_NAME=prod-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node uses: actions/setup-node@v4 with: node-version: 24 - - name: GLIBC version - run: | - ldd --version - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - - name: install dependencies (ubuntu only) - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - sudo apt-get install -y libwebrtc-audio-processing-dev - sudo apt-get install -y libunwind-dev - sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} @@ -363,27 +345,44 @@ jobs: run: | npm ci npm run _ci-release:prod - npm run tauri build - ls -alh ./src-tauri/target/release - mkdir ./src-tauri/target/release/binDist - cp ./src-tauri/target/release/phoenix-code ./src-tauri/target/release/binDist - cp ./src-build/linux/install-readme.txt ./src-tauri/target/release/binDist/readme.txt - cp ./src-tauri/target/release/phnode ./src-tauri/target/release/binDist - cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/binDist - ls -alh ./src-tauri/target/release/binDist - mv ./src-tauri/target/release/phoenix-code ./src-tauri/target/release/phoenix-code-backup - mv ./src-tauri/target/release/binDist ./src-tauri/target/release/phoenix-code - tar -cvzf phoenix-code.tar.gz -C ./src-tauri/target/release phoenix-code - ls -alh phoenix-code.tar.gz - GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') - OUTPUT_FILENAME="phoenix-code_$(node -p "require('./package.json').version")_amd64_linux_bin-GLIBC-${GLIBC_VER}.tar.gz" - mv phoenix-code.tar.gz "$OUTPUT_FILENAME" - echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV - ls + npm run _ci-releaseElectronApp + ls -alh ./src-electron/dist/ + echo "OUTPUT_FILENAME=$(ls ./src-electron/dist/*.AppImage | head -1 | xargs basename)" >> $GITHUB_ENV + + - name: Sign AppImage with minisign + env: + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + run: | + # Download and install minisign + wget https://github.com/jedisct1/minisign/releases/download/0.11/minisign-0.11-linux.tar.gz + tar -xzf minisign-0.11-linux.tar.gz + sudo mv minisign-linux/x86_64/minisign /usr/local/bin/ + minisign -v + + # Write private key to temp file + echo "$TAURI_PRIVATE_KEY" > /tmp/tauri_private.key + + # Sign the AppImage + APPIMAGE_PATH="./src-electron/dist/${{ env.OUTPUT_FILENAME }}" + echo "$TAURI_KEY_PASSWORD" | minisign -S -s /tmp/tauri_private.key -m "$APPIMAGE_PATH" -t "$(date +%s) file:${{ env.OUTPUT_FILENAME }}" + + # Clean up private key + rm /tmp/tauri_private.key + + # Show signature file + echo "Signature file contents:" + cat "${APPIMAGE_PATH}.minisig" + + # Rename .minisig to .sig for consistency + mv "${APPIMAGE_PATH}.minisig" "${APPIMAGE_PATH}.sig" + - name: Upload Release Asset uses: softprops/action-gh-release@v2 with: - files: ${{ env.OUTPUT_FILENAME }} + files: | + ./src-electron/dist/${{ env.OUTPUT_FILENAME }} + ./src-electron/dist/${{ env.OUTPUT_FILENAME }}.sig tag_name: ${{ env.GIT_TAG_NAME }} draft: true env: diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index ca5d28f2..641bf163 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -277,35 +277,17 @@ jobs: permissions: contents: write timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - platform: [ ubuntu-22.04] - - runs-on: ${{ matrix.platform }} + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 - name: get Git Tag + shell: bash run: echo "GIT_TAG_NAME=staging-app-v$(node -p "require('./package.json').version")" >> $GITHUB_ENV - name: setup node uses: actions/setup-node@v4 with: node-version: 24 - - name: GLIBC version - run: | - ldd --version - - name: install Rust stable - uses: dtolnay/rust-toolchain@stable - with: - toolchain: 1.85.1 - - name: install dependencies (ubuntu only) - run: | - sudo apt-get update - sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev - sudo apt-get install -y libwebrtc-audio-processing-dev - sudo apt-get install -y libunwind-dev - sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio - name: install frontend dependencies env: GH_TOKEN: ${{ github.token }} @@ -314,25 +296,44 @@ jobs: run: | npm ci npm run _ci-release:staging - npm run tauri build - ls -alh ./src-tauri/target/release - mkdir ./src-tauri/target/release/phoenix-code - cp ./src-tauri/target/release/phoenix-code-pre-release ./src-tauri/target/release/phoenix-code - cp ./src-build/linux/install-readme.txt ./src-tauri/target/release/phoenix-code/readme.txt - cp ./src-tauri/target/release/phnode ./src-tauri/target/release/phoenix-code - cp -r ./src-tauri/target/release/src-node ./src-tauri/target/release/phoenix-code - ls -alh ./src-tauri/target/release/phoenix-code - tar -cvzf phoenix-code.tar.gz -C ./src-tauri/target/release phoenix-code - ls -alh phoenix-code.tar.gz - GLIBC_VER=$(ldd --version | head -n1 | awk '{print $NF}') - OUTPUT_FILENAME="phoenix-code-pre-release_$(node -p "require('./package.json').version")_amd64_linux_bin-GLIBC-${GLIBC_VER}.tar.gz" - mv phoenix-code.tar.gz "$OUTPUT_FILENAME" - echo "OUTPUT_FILENAME=$OUTPUT_FILENAME" >> $GITHUB_ENV - ls + npm run _ci-releaseElectronApp + ls -alh ./src-electron/dist/ + echo "OUTPUT_FILENAME=$(ls ./src-electron/dist/*.AppImage | head -1 | xargs basename)" >> $GITHUB_ENV + + - name: Sign AppImage with minisign + env: + TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} + TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} + run: | + # Download and install minisign + wget https://github.com/jedisct1/minisign/releases/download/0.11/minisign-0.11-linux.tar.gz + tar -xzf minisign-0.11-linux.tar.gz + sudo mv minisign-linux/x86_64/minisign /usr/local/bin/ + minisign -v + + # Write private key to temp file + echo "$TAURI_PRIVATE_KEY" > /tmp/tauri_private.key + + # Sign the AppImage + APPIMAGE_PATH="./src-electron/dist/${{ env.OUTPUT_FILENAME }}" + echo "$TAURI_KEY_PASSWORD" | minisign -S -s /tmp/tauri_private.key -m "$APPIMAGE_PATH" -t "$(date +%s) file:${{ env.OUTPUT_FILENAME }}" + + # Clean up private key + rm /tmp/tauri_private.key + + # Show signature file + echo "Signature file contents:" + cat "${APPIMAGE_PATH}.minisig" + + # Rename .minisig to .sig for consistency + mv "${APPIMAGE_PATH}.minisig" "${APPIMAGE_PATH}.sig" + - name: Upload Release Asset uses: softprops/action-gh-release@v2 with: - files: ${{ env.OUTPUT_FILENAME }} + files: | + ./src-electron/dist/${{ env.OUTPUT_FILENAME }} + ./src-electron/dist/${{ env.OUTPUT_FILENAME }}.sig tag_name: ${{ env.GIT_TAG_NAME }} draft: true env: From 8096be5299cb301a57c18af32b8f047f8d311c6a Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 16:03:37 +0530 Subject: [PATCH 783/864] ci: linux signing key gen --- .github/workflows/tauri-build-dev.yml | 8 ++++++-- .github/workflows/tauri-build-prod.yml | 8 ++++++-- .github/workflows/tauri-build-staging.yml | 8 ++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 38ae4a3b..49cf7c8b 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -311,8 +311,12 @@ jobs: sudo mv minisign-linux/x86_64/minisign /usr/local/bin/ minisign -v - # Write private key to temp file - echo "$TAURI_PRIVATE_KEY" > /tmp/tauri_private.key + # Decode base64-encoded private key + echo "$TAURI_PRIVATE_KEY" | base64 -d > /tmp/tauri_private.key + + # Debug: show key file info (not contents) + echo "Key file size: $(wc -c < /tmp/tauri_private.key) bytes" + echo "Key file lines: $(wc -l < /tmp/tauri_private.key)" # Sign the AppImage APPIMAGE_PATH="./src-electron/dist/${{ env.OUTPUT_FILENAME }}" diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index d5f0c68d..634aaa0e 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -360,8 +360,12 @@ jobs: sudo mv minisign-linux/x86_64/minisign /usr/local/bin/ minisign -v - # Write private key to temp file - echo "$TAURI_PRIVATE_KEY" > /tmp/tauri_private.key + # Decode base64-encoded private key + echo "$TAURI_PRIVATE_KEY" | base64 -d > /tmp/tauri_private.key + + # Debug: show key file info (not contents) + echo "Key file size: $(wc -c < /tmp/tauri_private.key) bytes" + echo "Key file lines: $(wc -l < /tmp/tauri_private.key)" # Sign the AppImage APPIMAGE_PATH="./src-electron/dist/${{ env.OUTPUT_FILENAME }}" diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 641bf163..c52e0042 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -311,8 +311,12 @@ jobs: sudo mv minisign-linux/x86_64/minisign /usr/local/bin/ minisign -v - # Write private key to temp file - echo "$TAURI_PRIVATE_KEY" > /tmp/tauri_private.key + # Decode base64-encoded private key + echo "$TAURI_PRIVATE_KEY" | base64 -d > /tmp/tauri_private.key + + # Debug: show key file info (not contents) + echo "Key file size: $(wc -c < /tmp/tauri_private.key) bytes" + echo "Key file lines: $(wc -l < /tmp/tauri_private.key)" # Sign the AppImage APPIMAGE_PATH="./src-electron/dist/${{ env.OUTPUT_FILENAME }}" From 7830137a796b8b9f77698dad0ae622a1a384442c Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 16:11:00 +0530 Subject: [PATCH 784/864] chore: base64 encode signature --- .github/workflows/updateNotification.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/updateNotification.js b/.github/workflows/updateNotification.js index a26bc264..0c47b6e6 100644 --- a/.github/workflows/updateNotification.js +++ b/.github/workflows/updateNotification.js @@ -174,8 +174,10 @@ export default async function printStuff({github, context, githubWorkspaceRoot}) let linuxSignature = ""; try { const sigFileURL = _getDownloadURLByNameSuffix(releaseAssets, LINUX_APPIMAGE_SIG_SUFFIX); - linuxSignature = await _getTextHTTPS(sigFileURL); - console.log("Linux AppImage signature: ", linuxSignature); + const sigContent = await _getTextHTTPS(sigFileURL); + // Base64-encode the signature to match the format of other platforms + linuxSignature = Buffer.from(sigContent).toString('base64'); + console.log("Linux AppImage signature (base64): ", linuxSignature); } catch (sigErr) { console.warn("Linux AppImage signature file not found, using empty signature"); } From fb1aad38cd6645b4a03e23e06c180fbef5243835 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 10:42:27 +0000 Subject: [PATCH 785/864] ci: tauri release update notification json --- .../update-latest-experimental-build.json | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index ea084a50..241acedc 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -1,19 +1,35 @@ { - "version": "3.10.0", - "notes": "**Phoenix Code Release Notes**\r\n\r\nExperimental build for testing purposes -- do not use.", - "pub_date": "2024-11-25T06:56:04.373Z", + "version": "5.1.1", + "notes": "Testing new installer generation - do not install! -t2", + "pub_date": "2026-02-01T10:24:31.012Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnJiWksxckw2cG9SaTJIQmcySm45bEZqZnZlK3AwTGtmcjBiV09iU1BxWEpaYlhpK3grMjQ5aitQZkJwREdySThWWml3STIzeHM0Sm1CVzNGdjVqc3dVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE2ODA1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF8zLjEwLjBfeDY0LXNldHVwLm5zaXMuemlwCkF5Z3c0QjkxeDJiK3Nuc3dzTGhZL2pnd2ordkxCU2RaaWRTTmlSSUFiK0FYek1xRWNmTUtGcFlNS2RnZjBRMzhCRVJ1em9QbGFRbVBaNnNIQnIxdkF3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.10.0/Phoenix.Code.Experimental.Build_3.10.0_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm43d1FvWUxTSG9hNytaSXRuLzhwS1VVWjVrWUN6bi96NXliMTZvM1U0UnFzZXM5WFNqV2ltVFM5Q29QQlNkeEY0cGFjTDFKNW5LR3lhOHJYNTM1U3dnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY5OTM5ODA1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF81LjEuMV94NjQtc2V0dXAubnNpcy56aXAKYzd2QjZCd1hiMGlGSlFIMzN5RnFqU1c1UThIamZsaG02QXhGNzAyQVBSRWFOY0ErMHBneWY5MTdKUlA5Nmo1WnZMc2FTQVlKZ3hVeThaNkd6eFZXRFE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v5.1.1/Phoenix.Code.Experimental.Build_5.1.1_x64-setup.nsis.zip" + }, + "windows-x86_64-nsis": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm43d1FvWUxTSG9hNytaSXRuLzhwS1VVWjVrWUN6bi96NXliMTZvM1U0UnFzZXM5WFNqV2ltVFM5Q29QQlNkeEY0cGFjTDFKNW5LR3lhOHJYNTM1U3dnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY5OTM5ODA1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZF81LjEuMV94NjQtc2V0dXAubnNpcy56aXAKYzd2QjZCd1hiMGlGSlFIMzN5RnFqU1c1UThIamZsaG02QXhGNzAyQVBSRWFOY0ErMHBneWY5MTdKUlA5Nmo1WnZMc2FTQVlKZ3hVeThaNkd6eFZXRFE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v5.1.1/Phoenix.Code.Experimental.Build_5.1.1_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhYSTF1WTNVTGpQN3hmd3g3UTdVczYrS015UHdoakRQUkl1NzIxN0J6cnpMbGphTG5TS0VybXZqaVhVT0xCbXlka004NWNDeXJBN0JhZnFkU0tWd1FnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE3MTMxCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6ClBZN2pIclJsYmVMNFlYYi81aTMrd1prc1RYSVZaNktFT1U0NjczTlkyNEIvR0NZaElJODc1M1hRL0hmcVMyQlowTlcvN2FPVWx4QzJJVXV6Ly9Sb0JBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.10.0/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxuUFZJVUJ6U2xqaUU2aThjajBCME9GdWx2Tk9LRGxIZGJoQzVSbWp4U1R5cFgvQlFwTFoxRy9QR25MbVprV2x4ZllpaTI3MCtINTdHNEVXODVTandNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY5OTQwNDQ1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnB4NWxibjF6cHEwYlNqR3NVSGxJWEZsbWc4cE1YZlNlUDF3QTgrM3BoVWJwL2dCVnhtSjhCd3ZZK2ZPMDdMV3Erb2ZLRENIQjdRVWxJMWtxbVI2bENRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v5.1.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" + }, + "darwin-x86_64-app": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxuUFZJVUJ6U2xqaUU2aThjajBCME9GdWx2Tk9LRGxIZGJoQzVSbWp4U1R5cFgvQlFwTFoxRy9QR25MbVprV2x4ZllpaTI3MCtINTdHNEVXODVTandNPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY5OTQwNDQ1CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CnB4NWxibjF6cHEwYlNqR3NVSGxJWEZsbWc4cE1YZlNlUDF3QTgrM3BoVWJwL2dCVnhtSjhCd3ZZK2ZPMDdMV3Erb2ZLRENIQjdRVWxJMWtxbVI2bENRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v5.1.1/Phoenix.Code.Experimental.Build_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnZuMTBVUEIwZnJnT05ESlE4d3RkR3IyTDVYM1RCcUszOE1oL1F6NGlaRjhEc2xmT2plRi9IS20weWt3Q2JZblFxU0t6M1gwMSsrWHlKQlRHTDJKV3drPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzMyNTE3NzU2CWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CldUOGlLTThCckE0L2NTR2tVKy9OU3Y4M2ZYRmJVZkM1Vmc0UHVKQ0FqbTUvdXdxbDFqYzhkUGNyOTA0ZmxGUUhxd2ZOZ2YyTFFrS2lDRGN4ZUtkR0RBPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v3.10.0/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdXb2F0T3hhaWd3OFNrcHdMeXlZT3c4S0R6Qm50WXJ5MmNNZzBzd3pqQVFNem1DdEVaSmZPZEkxZ0lnNXdhblZRZ0taOUdDR2NzbFhoRXB5aVJwTVFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY5OTQxNDYyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmZ2ZGNVMWxDbWJxd01HVXJINXUvUlRTQTdnM256TEFjeXRzRHdsRlpYbU1lVmxmL2xKNU5ZN2ppdXVCWmU2NGpjMW9Qd2hNRGg1THR0YlNxZk1IMkNRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v5.1.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + }, + "darwin-aarch64-app": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdXb2F0T3hhaWd3OFNrcHdMeXlZT3c4S0R6Qm50WXJ5MmNNZzBzd3pqQVFNem1DdEVaSmZPZEkxZ0lnNXdhblZRZ0taOUdDR2NzbFhoRXB5aVJwTVFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY5OTQxNDYyCWZpbGU6UGhvZW5peCBDb2RlIEV4cGVyaW1lbnRhbCBCdWlsZC5hcHAudGFyLmd6CmZ2ZGNVMWxDbWJxd01HVXJINXUvUlRTQTdnM256TEFjeXRzRHdsRlpYbU1lVmxmL2xKNU5ZN2ppdXVCWmU2NGpjMW9Qd2hNRGg1THR0YlNxZk1IMkNRPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v5.1.1/Phoenix.Code.Experimental.Build_aarch64.app.tar.gz" + }, + "linux-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIG1pbmlzaWduIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1LT0Rla1BIK1l2akRaclI3TFhGMHZYTEVSbWxmSGt1UFRCeGRPY1BjVkJ3Nk9DMlgvYjZWSXlWSVhjVGR2S1dYa2RsYVF2SnZLY2lra2lObXZ3cWdRPQp0cnVzdGVkIGNvbW1lbnQ6IDE3Njk5Mzc4MDYJZmlsZTpwaG9lbml4LWNvZGUtZXhwZXJpbWVudGFsLWJ1aWxkXzUuMC41LkFwcEltYWdlCjhVR3BVVkFSV010dXZjZkExeDFnOTcrbjRWMW4wVlhmOFYzbmhWMGxUd1VaR0lhc2tmMTRpNTRHYzkyeVNNNnAydG9YSkZvQTJ1U3F1RU96akVsaEN3PT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v5.1.1/phoenix-code-experimental-build_5.0.5.AppImage" } } } \ No newline at end of file From 8f239dcc29f171f0dbee58271efa01b20f0f6c87 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 16:31:47 +0530 Subject: [PATCH 786/864] ci: version bump must bump electron version as well --- .github/workflows/update-phcode-build.yml | 1 + src-build/ci-setupDistFolders.js | 6 ++++++ src-build/createDistRelease.js | 6 ++++++ src-build/createDistTestRelease.js | 6 ++++++ src-build/createSrcRelease.js | 6 ++++++ src-build/serveForPlatform.js | 9 ++++++++- src-build/setupElectron.js | 11 +++++++++-- src-build/update-phcode-build.js | 10 +++++++++- src-electron/config.json | 1 - 9 files changed, 51 insertions(+), 5 deletions(-) diff --git a/.github/workflows/update-phcode-build.yml b/.github/workflows/update-phcode-build.yml index e06d6c88..94a10e63 100644 --- a/.github/workflows/update-phcode-build.yml +++ b/.github/workflows/update-phcode-build.yml @@ -45,6 +45,7 @@ jobs: package.json src-tauri/Cargo.toml src-tauri/tauri.conf.json + src-electron/package.json body: | A new version of phcode has been pushed to `${{github.event.client_payload.source}}` repo's `tauri` branch. This pull request updates the dependency to bring in the latest changes to phcode. diff --git a/src-build/ci-setupDistFolders.js b/src-build/ci-setupDistFolders.js index c0e8311a..e9b5b543 100644 --- a/src-build/ci-setupDistFolders.js +++ b/src-build/ci-setupDistFolders.js @@ -173,8 +173,14 @@ function createElectronReleaseAssets() { const envConfig = JSON.parse(fs.readFileSync(envConfigPath)); const effectiveConfig = { ...baseConfig, ...envConfig }; + // Inject version from src-electron/package.json + const electronPackagePath = join(electronDir, 'package.json'); + const electronPackage = JSON.parse(fs.readFileSync(electronPackagePath)); + effectiveConfig.version = electronPackage.version; + console.log('phoenixLoadURL:', effectiveConfig.phoenixLoadURL); console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); + console.log('version:', effectiveConfig.version); fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); } diff --git a/src-build/createDistRelease.js b/src-build/createDistRelease.js index 0c4e54be..a78db94c 100644 --- a/src-build/createDistRelease.js +++ b/src-build/createDistRelease.js @@ -155,8 +155,14 @@ function createElectronConfig() { const envConfig = JSON.parse(fs.readFileSync(envConfigPath)); const effectiveConfig = { ...baseConfig, ...envConfig }; + // Inject version from src-electron/package.json + const electronPackagePath = join(electronDir, 'package.json'); + const electronPackage = JSON.parse(fs.readFileSync(electronPackagePath)); + effectiveConfig.version = electronPackage.version; + console.log('phoenixLoadURL:', effectiveConfig.phoenixLoadURL); console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); + console.log('version:', effectiveConfig.version); fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); } diff --git a/src-build/createDistTestRelease.js b/src-build/createDistTestRelease.js index 9c70123b..da15019b 100644 --- a/src-build/createDistTestRelease.js +++ b/src-build/createDistTestRelease.js @@ -151,8 +151,14 @@ function createElectronConfig() { const envConfig = JSON.parse(fs.readFileSync(envConfigPath)); const effectiveConfig = { ...baseConfig, ...envConfig }; + // Inject version from src-electron/package.json + const electronPackagePath = join(electronDir, 'package.json'); + const electronPackage = JSON.parse(fs.readFileSync(electronPackagePath)); + effectiveConfig.version = electronPackage.version; + console.log('phoenixLoadURL:', effectiveConfig.phoenixLoadURL); console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); + console.log('version:', effectiveConfig.version); fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); } diff --git a/src-build/createSrcRelease.js b/src-build/createSrcRelease.js index 7c2070ac..0d978fea 100644 --- a/src-build/createSrcRelease.js +++ b/src-build/createSrcRelease.js @@ -127,8 +127,14 @@ function createElectronConfig() { // Merge: config-dev.json overrides config.json const effectiveConfig = { ...baseConfig, ...devConfig }; + // Inject version from src-electron/package.json + const electronPackagePath = join(electronDir, 'package.json'); + const electronPackage = JSON.parse(fs.readFileSync(electronPackagePath)); + effectiveConfig.version = electronPackage.version; + console.log('phoenixLoadURL:', effectiveConfig.phoenixLoadURL); console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); + console.log('version:', effectiveConfig.version); fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); } diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js index 6a6a6f37..bf1ff4c2 100644 --- a/src-build/serveForPlatform.js +++ b/src-build/serveForPlatform.js @@ -2,7 +2,7 @@ import {getPlatformDetails} from "./utils.js"; import {execa} from "execa"; import chalk from "chalk"; import {resolve} from "path"; -import {copyFileSync} from "fs"; +import {copyFileSync, readFileSync, writeFileSync} from "fs"; const {platform} = getPlatformDetails(); @@ -63,6 +63,13 @@ if (target === "tauri") { console.log('Copying config.json to config-effective.json...'); copyFileSync(configSrc, configDest); + // Inject version from package.json + const packageJsonPath = resolve(electronDir, "package.json"); + const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')); + const effectiveConfig = JSON.parse(readFileSync(configDest, 'utf8')); + effectiveConfig.version = packageJson.version; + writeFileSync(configDest, JSON.stringify(effectiveConfig, null, 2)); + console.log('Starting Electron...'); await execa("./src-electron/node_modules/.bin/electron", ["src-electron/main.js"], {stdio: "inherit"}); } diff --git a/src-build/setupElectron.js b/src-build/setupElectron.js index f98cd767..f4c991bb 100644 --- a/src-build/setupElectron.js +++ b/src-build/setupElectron.js @@ -1,7 +1,7 @@ import { execSync } from 'child_process'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; -import { copyFileSync } from 'fs'; +import { copyFileSync, readFileSync, writeFileSync } from 'fs'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -19,4 +19,11 @@ const configSrc = join(electronDir, 'config.json'); const configDest = join(electronDir, 'config-effective.json'); console.log('Copying config.json to config-effective.json...'); copyFileSync(configSrc, configDest); -console.log('Config file copied successfully!'); + +// Inject version from package.json +const packageJsonPath = join(electronDir, 'package.json'); +const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')); +const effectiveConfig = JSON.parse(readFileSync(configDest, 'utf8')); +effectiveConfig.version = packageJson.version; +writeFileSync(configDest, JSON.stringify(effectiveConfig, null, 2)); +console.log('Config file copied and version injected successfully!'); diff --git a/src-build/update-phcode-build.js b/src-build/update-phcode-build.js index 0ccd23d2..43dea28c 100644 --- a/src-build/update-phcode-build.js +++ b/src-build/update-phcode-build.js @@ -71,4 +71,12 @@ for(let i=0;i Date: Sun, 1 Feb 2026 11:08:19 +0000 Subject: [PATCH 787/864] ci: update phcode version to 5.1.2 --- package.json | 6 +++--- src-electron/package.json | 9 ++++++--- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 250ca0a7..f552d67e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.1", + "version": "5.1.2", "type": "module", "scripts": { "tauri": "tauri", @@ -47,6 +47,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "a6a2bcaaeadb8ad2a8320492640672dcdc1981f3" + "commit": "985db307292ad48648b5bfe6f2a5dbd556c9b573" } -} +} \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 391abf08..9b312c13 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -2,8 +2,11 @@ "name": "phoenix-code-electron-shell", "identifier": "io.phcode.dev", "stage": "dev", - "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/"], - "version": "5.0.5", + "trustedElectronDomains": [ + "phtauri://localhost/", + "https://phcode.dev/" + ], + "version": "5.1.2", "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", "main": "main.js", @@ -19,4 +22,4 @@ "electron": "^40.0.0", "electron-builder": "^24.13.3" } -} +} \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9779cb5a..2a931e50 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.1" +version = "5.1.2" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c044b0cc..1c786158 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.1" + "version": "5.1.2" }, "tauri": { "allowlist": { From 54ab29acb65dc3d8c296cd33f61e4c23c64a7e4d Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 18:03:03 +0530 Subject: [PATCH 788/864] chore: auto update in linux electron base tested --- src-electron/main.js | 39 +++++++++++++++++++++++++++++++++++++++ src-electron/preload.js | 8 +++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src-electron/main.js b/src-electron/main.js index 386314bf..086ddc91 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -225,6 +225,45 @@ ipcMain.on('send-health-metric', (event, payload) => { } }); +/** + * App updater IPC handlers + * These provide low-level APIs for the update-electron.js extension in Phoenix + */ + +// Get app version from config +ipcMain.handle('get-app-version', (event) => { + assertTrusted(event); + return version; +}); + +// Check if app is packaged (production build) +ipcMain.handle('is-packaged', (event) => { + assertTrusted(event); + return app.isPackaged; +}); + +// Get executable path (path to the AppImage on Linux) +ipcMain.handle('get-executable-path', (event) => { + assertTrusted(event); + return process.execPath; +}); + +// Run a shell command for update script execution +ipcMain.handle('run-shell-command', async (event, command) => { + assertTrusted(event); + const { exec } = require('child_process'); + return new Promise((resolve) => { + exec(command, { shell: '/bin/bash' }, (error, stdout, stderr) => { + if (error) { + console.error('Shell command error:', error); + resolve({ code: error.code || 1, stdout, stderr }); + } else { + resolve({ code: 0, stdout, stderr }); + } + }); + }); +}); + // Handle quit request from renderer app.on('quit-requested', (exitCode) => { gracefulShutdown(exitCode); diff --git a/src-electron/preload.js b/src-electron/preload.js index 6ef2ef49..d73aeb5e 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -160,5 +160,11 @@ contextBridge.exposeInMainWorld('electronAPI', { // Health metrics for Google Analytics (sends to hidden metrics window) sendHealthMetric: (payload) => ipcRenderer.send('send-health-metric', payload), - onHealthMetric: (callback) => ipcRenderer.on('health-metric', (_event, payload) => callback(payload)) + onHealthMetric: (callback) => ipcRenderer.on('health-metric', (_event, payload) => callback(payload)), + + // App updater APIs - just expose primitives, logic is in update-electron.js + getAppVersion: () => ipcRenderer.invoke('get-app-version'), + isPackaged: () => ipcRenderer.invoke('is-packaged'), + getExecutablePath: () => ipcRenderer.invoke('get-executable-path'), + runShellCommand: (command) => ipcRenderer.invoke('run-shell-command', command) }); From 7ba8c6da2b2fc49b3499dc6694a5d64395c1e35b Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 1 Feb 2026 18:55:03 +0530 Subject: [PATCH 789/864] feat: electron supporting apis for auto update in linux --- src-electron/main.js | 26 ++++++++++++-------------- src-electron/package.json | 2 +- src-electron/preload.js | 8 ++++++-- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src-electron/main.js b/src-electron/main.js index 086ddc91..b548c491 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -78,9 +78,12 @@ function getSrcNodePath() { } // In-memory key-value store shared across all windows (mirrors Tauri's put_item/get_all_items) -// Used for multi-window storage synchronization +// Used for multi-window storage synchronization - ONLY for use by storage.js const sharedStorageMap = new Map(); +// Update scheduled flag - shared across all windows for app updater +let updateScheduled = false; + // Hidden metrics window for Google Analytics let metricsWindow = null; @@ -248,20 +251,15 @@ ipcMain.handle('get-executable-path', (event) => { return process.execPath; }); -// Run a shell command for update script execution -ipcMain.handle('run-shell-command', async (event, command) => { +// Update scheduled state - shared across windows for multi-window update persistence +ipcMain.handle('set-update-scheduled', (event, scheduled) => { assertTrusted(event); - const { exec } = require('child_process'); - return new Promise((resolve) => { - exec(command, { shell: '/bin/bash' }, (error, stdout, stderr) => { - if (error) { - console.error('Shell command error:', error); - resolve({ code: error.code || 1, stdout, stderr }); - } else { - resolve({ code: 0, stdout, stderr }); - } - }); - }); + updateScheduled = scheduled; +}); + +ipcMain.handle('get-update-scheduled', (event) => { + assertTrusted(event); + return updateScheduled; }); // Handle quit request from renderer diff --git a/src-electron/package.json b/src-electron/package.json index 9b312c13..6d3a0c57 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -22,4 +22,4 @@ "electron": "^40.0.0", "electron-builder": "^24.13.3" } -} \ No newline at end of file +} diff --git a/src-electron/preload.js b/src-electron/preload.js index d73aeb5e..0a2a9a64 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -79,7 +79,10 @@ contextBridge.exposeInMainWorld('electronAPI', { // Set zoom factor on the webview (mirrors Tauri's zoom_window) zoomWindow: (scaleFactor) => ipcRenderer.invoke('zoom-window', scaleFactor), - // In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) + /** + * In-memory storage for multi-window sync (mirrors Tauri's put_item/get_all_items) + * WARNING: These APIs are ONLY for use by storage.js - do not use elsewhere + */ putItem: (key, value) => ipcRenderer.invoke('put-item', key, value), getAllItems: () => ipcRenderer.invoke('get-all-items'), @@ -166,5 +169,6 @@ contextBridge.exposeInMainWorld('electronAPI', { getAppVersion: () => ipcRenderer.invoke('get-app-version'), isPackaged: () => ipcRenderer.invoke('is-packaged'), getExecutablePath: () => ipcRenderer.invoke('get-executable-path'), - runShellCommand: (command) => ipcRenderer.invoke('run-shell-command', command) + setUpdateScheduled: (scheduled) => ipcRenderer.invoke('set-update-scheduled', scheduled), + getUpdateScheduled: () => ipcRenderer.invoke('get-update-scheduled') }); From 77fd2d9e9fc9176dc400906eca2a74c07d64c31f Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 5 Feb 2026 13:33:00 +0530 Subject: [PATCH 790/864] chore: pro offer notification --- docs/appNotifications/prod/de/banner.json | 7 +++++++ docs/appNotifications/prod/fr/banner.json | 7 +++++++ docs/appNotifications/prod/it/banner.json | 7 +++++++ docs/appNotifications/prod/ja/banner.json | 7 +++++++ docs/appNotifications/prod/ko/banner.json | 7 +++++++ docs/appNotifications/prod/pt-BR/banner.json | 7 +++++++ docs/appNotifications/prod/root/banner.json | 7 +++++++ 7 files changed, 49 insertions(+) diff --git a/docs/appNotifications/prod/de/banner.json b/docs/appNotifications/prod/de/banner.json index 5b881470..5a3e4088 100644 --- a/docs/appNotifications/prod/de/banner.json +++ b/docs/appNotifications/prod/de/banner.json @@ -4,5 +4,12 @@ "HTML_CONTENT": "
Wir stellen vor Phoenix Code Desktop-Apps für Windows, Mac und Linux. Klicken Sie hier, um es jetzt zu erhalten!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "LIFETIME_DEAL_V_5_0_0_DEAL": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Phoenix Pro Lifetime-Angebot
Besitzen Sie Phoenix Pro dauerhaft mit einer einmaligen Zahlung. Endet in 14 Tagen.
", + "FOR_VERSIONS": ">=5.0.0", + "PLATFORM": "allDesktop", + "USER_TYPE": ["trial"] } } diff --git a/docs/appNotifications/prod/fr/banner.json b/docs/appNotifications/prod/fr/banner.json index 02bc291b..6b47e286 100644 --- a/docs/appNotifications/prod/fr/banner.json +++ b/docs/appNotifications/prod/fr/banner.json @@ -4,5 +4,12 @@ "HTML_CONTENT": "
Présentation des applications de bureau de Phoenix Code pour Windows, Mac et Linux. Cliquez ici pour l'obtenir maintenant !
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "LIFETIME_DEAL_V_5_0_0_DEAL": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Offre à vie Phoenix Pro
Obtenez Phoenix Pro pour toujours avec un paiement unique. Se termine dans 14 jours.
", + "FOR_VERSIONS": ">=5.0.0", + "PLATFORM": "allDesktop", + "USER_TYPE": ["trial"] } } diff --git a/docs/appNotifications/prod/it/banner.json b/docs/appNotifications/prod/it/banner.json index 3df5cd36..4b9e1c5e 100644 --- a/docs/appNotifications/prod/it/banner.json +++ b/docs/appNotifications/prod/it/banner.json @@ -4,5 +4,12 @@ "HTML_CONTENT": "
Presentazione delle app desktop di Phoenix Code per Windows, Mac e Linux. Fai clic qui per ottenerlo ora!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "LIFETIME_DEAL_V_5_0_0_DEAL": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Offerta a vita Phoenix Pro
Ottieni Phoenix Pro per sempre con un pagamento unico. Scade tra 14 giorni.
", + "FOR_VERSIONS": ">=5.0.0", + "PLATFORM": "allDesktop", + "USER_TYPE": ["trial"] } } diff --git a/docs/appNotifications/prod/ja/banner.json b/docs/appNotifications/prod/ja/banner.json index ac401425..90a23339 100644 --- a/docs/appNotifications/prod/ja/banner.json +++ b/docs/appNotifications/prod/ja/banner.json @@ -4,5 +4,12 @@ "HTML_CONTENT": "
Windows、Mac、Linux 用の Phoenix Code のデスクトップ アプリを紹介します。 ここをクリックして今すぐ入手してください。
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "LIFETIME_DEAL_V_5_0_0_DEAL": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Phoenix Pro 永久ライセンス
一度の支払いで Phoenix Pro を永久に利用できます。14日後に終了します。
", + "FOR_VERSIONS": ">=5.0.0", + "PLATFORM": "allDesktop", + "USER_TYPE": ["trial"] } } diff --git a/docs/appNotifications/prod/ko/banner.json b/docs/appNotifications/prod/ko/banner.json index 2b37f804..1ac5e441 100644 --- a/docs/appNotifications/prod/ko/banner.json +++ b/docs/appNotifications/prod/ko/banner.json @@ -4,5 +4,12 @@ "HTML_CONTENT": "
Windows, Mac 및 Linux용 소개 Phoenix Code 데스크톱 앱. 지금 다운로드하려면 여기를 클릭하세요!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "LIFETIME_DEAL_V_5_0_0_DEAL": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Phoenix Pro 평생 이용권
한 번의 결제로 Phoenix Pro 를 평생 사용하세요. 14일 후 종료됩니다.
", + "FOR_VERSIONS": ">=5.0.0", + "PLATFORM": "allDesktop", + "USER_TYPE": ["trial"] } } diff --git a/docs/appNotifications/prod/pt-BR/banner.json b/docs/appNotifications/prod/pt-BR/banner.json index 674888d4..61ef5d1b 100644 --- a/docs/appNotifications/prod/pt-BR/banner.json +++ b/docs/appNotifications/prod/pt-BR/banner.json @@ -4,5 +4,12 @@ "HTML_CONTENT": "
Apresentamos os aplicativos de desktop Phoenix Code para Windows, Mac e Linux. Clique aqui para obtê-lo agora!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "LIFETIME_DEAL_V_5_0_0_DEAL": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Oferta vitalícia do Phoenix Pro
Tenha Phoenix Pro para sempre com um pagamento único. Termina em 14 dias.
", + "FOR_VERSIONS": ">=5.0.0", + "PLATFORM": "allDesktop", + "USER_TYPE": ["trial"] } } diff --git a/docs/appNotifications/prod/root/banner.json b/docs/appNotifications/prod/root/banner.json index 19c29552..31063ca4 100644 --- a/docs/appNotifications/prod/root/banner.json +++ b/docs/appNotifications/prod/root/banner.json @@ -4,5 +4,12 @@ "HTML_CONTENT": "
Introducing Phoenix Code Desktop Apps for Windows, Mac & Linux. Click here to get it now!
", "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" + }, + "LIFETIME_DEAL_V_5_0_0_DEAL": { + "DANGER_SHOW_ON_EVERY_BOOT": false, + "HTML_CONTENT": "
Phoenix Pro Lifetime Deal
Own Phoenix Pro forever with a one-time purchase. Ends in 14 days.
", + "FOR_VERSIONS": ">=5.0.0", + "PLATFORM": "allDesktop", + "USER_TYPE": ["trial"] } } From be7d1f97909b741b04a77c1c86928f272c5e907f Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 5 Feb 2026 14:53:41 +0530 Subject: [PATCH 791/864] fix: trust ring in electron app was not getting shut down properly --- docs/appNotifications/readme.md | 4 ++-- src-electron/main-cred-ipc.js | 12 ++++++++++-- src-electron/main-window-ipc.js | 10 +++++++++- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/appNotifications/readme.md b/docs/appNotifications/readme.md index 7d22285f..041d3447 100644 --- a/docs/appNotifications/readme.md +++ b/docs/appNotifications/readme.md @@ -50,5 +50,5 @@ A sample json is as follows: 5. `PLATFORM`: A comma seperated list(no spaces) of all platforms in which the message will be shown. allowed values are: `mac,win,linux,allDesktop,firefox,chrome,safari,allBrowser,all` 6. `USER_TYPE`: An array of all user types in which the message will be shown. - allowed values are: [`all`, `notLoggedIn`, `loggedIn`, `trial`, `paidSubscriber`]. This filter is only available - in versions > 5, else it is ignored in older versions. combine with `FOR_VERSIONS` to filter based on user type. + allowed values are: [`all`, `notLoggedIn`, `loggedIn`, `trial`, `paidSubscriber`, `notPaidsubscriber`]. This filter + is only available in versions > 5, else it is ignored in older versions. combine with `FOR_VERSIONS` to filter based on user type. diff --git a/src-electron/main-cred-ipc.js b/src-electron/main-cred-ipc.js index f05ebca1..d5e04a03 100644 --- a/src-electron/main-cred-ipc.js +++ b/src-electron/main-cred-ipc.js @@ -17,7 +17,7 @@ try { const PHOENIX_CRED_PREFIX = 'phcode_electron_'; function registerCredIpcHandlers() { - // Trust window AES key - can only be called once per window + // Trust window AES key - can only be called once per page load ipcMain.handle('trust-window-aes-key', (event, key, iv) => { assertTrusted(event); const webContentsId = event.sender.id; @@ -140,4 +140,12 @@ function cleanupWindowTrust(webContentsId, windowLabel) { } } -module.exports = { registerCredIpcHandlers, cleanupWindowTrust }; +// Clear trust on navigation (page reload) - allows fresh trust to be established after reload +function clearTrustOnNavigation(webContentsId, windowLabel) { + if (windowTrustMap.has(webContentsId)) { + windowTrustMap.delete(webContentsId); + console.log(`AES trust cleared for navigation in window: ${windowLabel} (webContentsId: ${webContentsId})`); + } +} + +module.exports = { registerCredIpcHandlers, cleanupWindowTrust, clearTrustOnNavigation }; diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index f244ccf7..0a94f49e 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -1,7 +1,7 @@ const { ipcMain, BrowserWindow, shell, clipboard } = require('electron'); const path = require('path'); const { spawn } = require('child_process'); -const { cleanupWindowTrust } = require('./main-cred-ipc'); +const { cleanupWindowTrust, clearTrustOnNavigation } = require('./main-cred-ipc'); const { isTrustedOrigin, updateTrustStatus, cleanupTrust, assertTrusted } = require('./ipc-security'); const { DEFAULTS, trackWindowState } = require('./window-state'); @@ -39,6 +39,14 @@ function registerWindow(win, label) { // Initial trust evaluation updateTrustStatus(webContents); + // Clear AES trust before navigation starts (page reload/navigate) + // This allows the new page to establish fresh trust with its own keys + webContents.on('did-start-navigation', (event, url, isInPlace, isMainFrame) => { + if (isMainFrame) { + clearTrustOnNavigation(webContentsId, label); + } + }); + // Re-evaluate trust on navigation webContents.on('did-navigate', () => { updateTrustStatus(webContents); From 56fd27bbed2213e4b0ab48d4d3807b1803c31378 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 6 Feb 2026 17:02:28 +0530 Subject: [PATCH 792/864] fix: npm run serve not working in windows --- src-build/serveForPlatform.js | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js index bf1ff4c2..8dffc936 100644 --- a/src-build/serveForPlatform.js +++ b/src-build/serveForPlatform.js @@ -6,6 +6,31 @@ import {copyFileSync, readFileSync, writeFileSync} from "fs"; const {platform} = getPlatformDetails(); +function createTauriDevConfig() { + const tauriDir = resolve("src-tauri"); + const tauriConfigPath = resolve(tauriDir, "tauri.conf.json"); + const tauriLocalConfigPath = resolve(tauriDir, "tauri-local.conf.json"); + + console.log('Creating Tauri dev config...'); + const configJson = JSON.parse(readFileSync(tauriConfigPath, 'utf8')); + + // Override window URLs for dev mode + const devUrl = configJson.build.devPath; // "http://localhost:8000/src/" + + // Main window - remove hardcoded URL so devPath is used + if (configJson.tauri.windows[0]) { + delete configJson.tauri.windows[0].url; + } + + // fileDrop window - point to dev server + if (configJson.tauri.windows[2]) { + configJson.tauri.windows[2].url = devUrl + "drop-files.html"; + } + + writeFileSync(tauriLocalConfigPath, JSON.stringify(configJson, null, 4)); + console.log('Dev config written to:', tauriLocalConfigPath); +} + // Get target from CLI arg, or detect from platform const cliArg = process.argv[2]; let target; @@ -49,8 +74,10 @@ if (target === "tauri") { console.log('Setting up src-node...'); await execa("npm", ["run", "_make_src-node"], {stdio: "inherit"}); + createTauriDevConfig(); + console.log('Starting Tauri dev server...'); - await execa("npx", ["tauri", "dev"], {stdio: "inherit"}); + await execa("npx", ["tauri", "dev", "--config", "./src-tauri/tauri-local.conf.json"], {stdio: "inherit"}); } else { const srcNodePath = resolve("../phoenix/src-node"); console.log(`Running "npm install" in ${srcNodePath}`); From d26305c605e811648aa1d23eb786a4d882efbc13 Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 7 Feb 2026 11:24:07 +0530 Subject: [PATCH 793/864] fix: in electron metrics was not being sent in dev builds --- src-electron/config-dev.json | 2 +- src-electron/config.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-electron/config-dev.json b/src-electron/config-dev.json index b2d784ea..90dc03c7 100644 --- a/src-electron/config-dev.json +++ b/src-electron/config-dev.json @@ -1,4 +1,4 @@ { "phoenixLoadURL": "phtauri://localhost/", - "gaMetricsURL": "phtauri://localhost/desktop-metrics.html" + "gaMetricsURL": "https://dev.phcode.dev/desktop-metrics.html" } diff --git a/src-electron/config.json b/src-electron/config.json index 22f16542..283a4210 100644 --- a/src-electron/config.json +++ b/src-electron/config.json @@ -4,5 +4,5 @@ "productName": "Phoenix Code Experimental Build", "phoenixLoadURL": "phtauri://localhost/src/", "trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/"], - "gaMetricsURL": "phtauri://localhost/src/desktop-metrics.html" + "gaMetricsURL": "http://localhost:8000/src/desktop-metrics.html" } From 23a003556cd6f30d235c42a2f89c82f9cd41b21f Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 7 Feb 2026 20:31:35 +0530 Subject: [PATCH 794/864] chore: update back new user survey to 20 minutes --- docs/appNotifications/prod/de/banner.json | 2 +- docs/appNotifications/prod/fr/banner.json | 2 +- docs/appNotifications/prod/it/banner.json | 2 +- docs/appNotifications/prod/ja/banner.json | 2 +- docs/appNotifications/prod/ko/banner.json | 2 +- docs/appNotifications/prod/pt-BR/banner.json | 2 +- docs/appNotifications/prod/root/banner.json | 2 +- docs/surveys.json | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/appNotifications/prod/de/banner.json b/docs/appNotifications/prod/de/banner.json index 5a3e4088..9cf1b65d 100644 --- a/docs/appNotifications/prod/de/banner.json +++ b/docs/appNotifications/prod/de/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro Lifetime-Angebot
Besitzen Sie Phoenix Pro dauerhaft mit einer einmaligen Zahlung. Endet in 14 Tagen.
", + "HTML_CONTENT": "
Phoenix Pro Lifetime-Angebot
Besitzen Sie Phoenix Pro dauerhaft mit einer einmaligen Zahlung. Endet in 11 Tagen.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/fr/banner.json b/docs/appNotifications/prod/fr/banner.json index 6b47e286..f3a6b80c 100644 --- a/docs/appNotifications/prod/fr/banner.json +++ b/docs/appNotifications/prod/fr/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Offre à vie Phoenix Pro
Obtenez Phoenix Pro pour toujours avec un paiement unique. Se termine dans 14 jours.
", + "HTML_CONTENT": "
Offre à vie Phoenix Pro
Obtenez Phoenix Pro pour toujours avec un paiement unique. Se termine dans 11 jours.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/it/banner.json b/docs/appNotifications/prod/it/banner.json index 4b9e1c5e..8ecfba6e 100644 --- a/docs/appNotifications/prod/it/banner.json +++ b/docs/appNotifications/prod/it/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Offerta a vita Phoenix Pro
Ottieni Phoenix Pro per sempre con un pagamento unico. Scade tra 14 giorni.
", + "HTML_CONTENT": "
Offerta a vita Phoenix Pro
Ottieni Phoenix Pro per sempre con un pagamento unico. Scade tra 11 giorni.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/ja/banner.json b/docs/appNotifications/prod/ja/banner.json index 90a23339..78a590e1 100644 --- a/docs/appNotifications/prod/ja/banner.json +++ b/docs/appNotifications/prod/ja/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro 永久ライセンス
一度の支払いで Phoenix Pro を永久に利用できます。14日後に終了します。
", + "HTML_CONTENT": "
Phoenix Pro 永久ライセンス
一度の支払いで Phoenix Pro を永久に利用できます。11日後に終了します。
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/ko/banner.json b/docs/appNotifications/prod/ko/banner.json index 1ac5e441..406d4174 100644 --- a/docs/appNotifications/prod/ko/banner.json +++ b/docs/appNotifications/prod/ko/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro 평생 이용권
한 번의 결제로 Phoenix Pro 를 평생 사용하세요. 14일 후 종료됩니다.
", + "HTML_CONTENT": "
Phoenix Pro 평생 이용권
한 번의 결제로 Phoenix Pro 를 평생 사용하세요. 11일 후 종료됩니다.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/pt-BR/banner.json b/docs/appNotifications/prod/pt-BR/banner.json index 61ef5d1b..4b789a02 100644 --- a/docs/appNotifications/prod/pt-BR/banner.json +++ b/docs/appNotifications/prod/pt-BR/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Oferta vitalícia do Phoenix Pro
Tenha Phoenix Pro para sempre com um pagamento único. Termina em 14 dias.
", + "HTML_CONTENT": "
Oferta vitalícia do Phoenix Pro
Tenha Phoenix Pro para sempre com um pagamento único. Termina em 11 dias.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/root/banner.json b/docs/appNotifications/prod/root/banner.json index 31063ca4..b15d0455 100644 --- a/docs/appNotifications/prod/root/banner.json +++ b/docs/appNotifications/prod/root/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro Lifetime Deal
Own Phoenix Pro forever with a one-time purchase. Ends in 14 days.
", + "HTML_CONTENT": "
Phoenix Pro Lifetime Deal
Own Phoenix Pro forever with a one-time purchase. Ends in 11 days.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/surveys.json b/docs/surveys.json index 2d97d7b6..75d8b1bd 100644 --- a/docs/surveys.json +++ b/docs/surveys.json @@ -1,12 +1,12 @@ { "newUser": "https://s.surveyplanet.com/9y5p5azy", "powerUser": "https://s.surveyplanet.com/dfy15wgk", - "newUserShowDelayMS": 2100000, + "newUserShowDelayMS": 1200000, "powerUserShowIntervalDays": 45, "browser": { "newUser": "https://s.surveyplanet.com/d7vk6wq5", "powerUser": "https://s.surveyplanet.com/e3r7fm8c", - "newUserShowDelayMS": 2100000, + "newUserShowDelayMS": 1200000, "powerUserShowIntervalDays": 45 } } From 280aaa40fc09a7ecd9fe8bbdb8e79f99f0e4ddd8 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 7 Feb 2026 15:13:41 +0000 Subject: [PATCH 795/864] ci: update phcode version to 5.1.3 --- package.json | 4 ++-- src-electron/package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index f552d67e..6d5b7522 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.2", + "version": "5.1.3", "type": "module", "scripts": { "tauri": "tauri", @@ -47,6 +47,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "985db307292ad48648b5bfe6f2a5dbd556c9b573" + "commit": "deb309997d34383ffc01c623902537ad095c79f3" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 6d3a0c57..96cab372 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.2", + "version": "5.1.3", "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", "main": "main.js", @@ -22,4 +22,4 @@ "electron": "^40.0.0", "electron-builder": "^24.13.3" } -} +} \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 2a931e50..ea3a1f97 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.2" +version = "5.1.3" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1c786158..fb7234fe 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.2" + "version": "5.1.3" }, "tauri": { "allowlist": { From 058b859968b775cab2ee1527b50c34c803c04d4e Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 12 Feb 2026 11:01:40 +0530 Subject: [PATCH 796/864] build: add npm run serve:dist to server from dist folder for quick testing in electron --- package.json | 3 ++- src-build/serveForPlatform.js | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 6d5b7522..335aa652 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "_ci-releaseElectronApp": "cd src-electron && npm run build:appimage && cd ..", "_ci-update-phcode-build": "node src-build/update-phcode-build.js", "serve": "node src-build/serveForPlatform.js", + "serve:dist": "node src-build/serveForPlatform.js --dist", "serve:tauri": "node src-build/serveForPlatform.js tauri", "serve:electron": "node src-build/serveForPlatform.js electron", "postinstall": "node ./src-build/downloadNodeBinary.js && node ./src-build/setupElectron.js", @@ -49,4 +50,4 @@ "branch": "tauri", "commit": "deb309997d34383ffc01c623902537ad095c79f3" } -} \ No newline at end of file +} diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js index 8dffc936..bdbb0dad 100644 --- a/src-build/serveForPlatform.js +++ b/src-build/serveForPlatform.js @@ -32,14 +32,15 @@ function createTauriDevConfig() { } // Get target from CLI arg, or detect from platform -const cliArg = process.argv[2]; +const cliArgs = process.argv.slice(2).filter(arg => !arg.startsWith('--')); +const cliArg = cliArgs[0]; let target; if (cliArg === 'tauri' || cliArg === 'electron') { target = cliArg; } else if (cliArg) { console.error(`Unknown target: ${cliArg}`); - console.error('Usage: npm run serve [tauri|electron]'); + console.error('Usage: npm run serve [tauri|electron] [--dist]'); process.exit(1); } else { // Auto-detect: Linux uses Electron, Windows/Mac use Tauri @@ -79,6 +80,7 @@ if (target === "tauri") { console.log('Starting Tauri dev server...'); await execa("npx", ["tauri", "dev", "--config", "./src-tauri/tauri-local.conf.json"], {stdio: "inherit"}); } else { + const serveDist = process.argv.includes('--dist'); const srcNodePath = resolve("../phoenix/src-node"); console.log(`Running "npm install" in ${srcNodePath}`); await execa("npm", ["install"], {cwd: srcNodePath, stdio: "inherit"}); @@ -95,6 +97,13 @@ if (target === "tauri") { const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')); const effectiveConfig = JSON.parse(readFileSync(configDest, 'utf8')); effectiveConfig.version = packageJson.version; + + // When --dist flag is passed, serve from ../phoenix/dist instead of ../phoenix/src + if (serveDist) { + console.log('Serving from ../phoenix/dist (--dist mode)'); + effectiveConfig.phoenixLoadURL = effectiveConfig.phoenixLoadURL.replace('/src/', '/dist/'); + } + writeFileSync(configDest, JSON.stringify(effectiveConfig, null, 2)); console.log('Starting Electron...'); From f8018b2df5ef47e6de0c514e22a2dcf40ef4c1d7 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 12 Feb 2026 11:03:02 +0530 Subject: [PATCH 797/864] build: add npm run serve:dist to server from dist folder for quick testing in electron --- src-build/serveForPlatform.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src-build/serveForPlatform.js b/src-build/serveForPlatform.js index bdbb0dad..6616c7d0 100644 --- a/src-build/serveForPlatform.js +++ b/src-build/serveForPlatform.js @@ -66,6 +66,13 @@ if (target !== recommendedTarget) { console.warn(y(`╚${border}╝\n`)); } +const serveDist = process.argv.includes('--dist'); + +if (serveDist && target === "tauri") { + console.error('Error: --dist flag is only supported with Electron, not Tauri.'); + process.exit(1); +} + console.log(`Platform: ${platform}, target: ${target}`); // Run platform-specific command @@ -80,7 +87,6 @@ if (target === "tauri") { console.log('Starting Tauri dev server...'); await execa("npx", ["tauri", "dev", "--config", "./src-tauri/tauri-local.conf.json"], {stdio: "inherit"}); } else { - const serveDist = process.argv.includes('--dist'); const srcNodePath = resolve("../phoenix/src-node"); console.log(`Running "npm install" in ${srcNodePath}`); await execa("npm", ["install"], {cwd: srcNodePath, stdio: "inherit"}); From 978f11f25103038c9a85e1bac08dafd6b8861135 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 6 Feb 2026 16:10:25 +0530 Subject: [PATCH 798/864] feat: screenshot api in electron(tauri not tested) --- src-electron/main-window-ipc.js | 12 ++ src-electron/preload.js | 4 + src-tauri/Cargo.lock | 5 +- src-tauri/Cargo.toml | 5 +- src-tauri/src/main.rs | 208 +++++++++++++++++++++++++++++++- 5 files changed, 231 insertions(+), 3 deletions(-) diff --git a/src-electron/main-window-ipc.js b/src-electron/main-window-ipc.js index 0a94f49e..3ce627c9 100644 --- a/src-electron/main-window-ipc.js +++ b/src-electron/main-window-ipc.js @@ -370,6 +370,18 @@ function registerWindowIpcHandlers() { win.close(); } }); + + // Capture a region of the current window as PNG + // rect is optional {x, y, width, height} — if omitted, captures the full visible page + ipcMain.handle('capture-page', async (event, rect) => { + assertTrusted(event); + const win = BrowserWindow.fromWebContents(event.sender); + if (!win) { + throw new Error('No window found for capture'); + } + const nativeImage = await event.sender.capturePage(rect); + return nativeImage.toPNG(); + }); } function getWindowLabel(webContentsId) { diff --git a/src-electron/preload.js b/src-electron/preload.js index 0a2a9a64..99467063 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -139,6 +139,10 @@ contextBridge.exposeInMainWorld('electronAPI', { setWindowTitle: (title) => ipcRenderer.invoke('set-window-title', title), getWindowTitle: () => ipcRenderer.invoke('get-window-title'), + // Screenshot API — capture a region of the current window as PNG buffer + // rect is optional {x, y, width, height} — if omitted, captures the full visible page + capturePage: (rect) => ipcRenderer.invoke('capture-page', rect), + // Clipboard APIs clipboardReadText: () => ipcRenderer.invoke('clipboard-read-text'), clipboardWriteText: (text) => ipcRenderer.invoke('clipboard-write-text', text), diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index d0cd12aa..3ec98a5a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3407,12 +3407,14 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "5.1.0" +version = "5.1.2" dependencies = [ "aes-gcm", "backtrace", + "block", "chrono", "clipboard-files", + "cocoa 0.25.0", "dialog", "fix-path-env", "gtk", @@ -3424,6 +3426,7 @@ dependencies = [ "once_cell", "os_info", "percent-encoding", + "png", "regex", "reqwest 0.12.15", "serde", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ea3a1f97..ffffac21 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -28,7 +28,8 @@ webbrowser = "1.0" backtrace = "0.3.73" serde = { version = "1.0.200", features = ["derive"] } tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools", "linux-protocol-headers"] } -winapi = { version = "0.3.9", features = ["fileapi"] } +winapi = { version = "0.3.9", features = ["fileapi", "wingdi", "winuser", "windef"] } +png = "0.17" tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } @@ -50,6 +51,8 @@ dialog = "0.3.0" [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2.7" +block = "0.1" +cocoa = "0.25" tauri-plugin-deep-link = "0.1.2" lazy_static = "1.4" native-dialog = "0.7.0" diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 0564025c..c78254bf 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -25,6 +25,9 @@ extern crate webkit2gtk; #[macro_use] extern crate objc; +#[cfg(target_os = "macos")] +extern crate cocoa; + use clipboard_files; #[cfg(target_os = "linux")] @@ -387,6 +390,209 @@ fn get_mac_deep_link_requests() -> Vec { } } +// Screenshot capture types +#[derive(serde::Deserialize)] +struct CaptureRect { + x: f64, + y: f64, + width: f64, + height: f64, +} + +#[tauri::command] +async fn capture_page(window: tauri::Window, rect: Option) -> Result, String> { + #[cfg(target_os = "linux")] + { + let _ = (&window, &rect); + return Err("capture_page is not implemented on Linux".to_string()); + } + + #[cfg(target_os = "macos")] + { + let (tx, rx) = tokio::sync::oneshot::channel::, String>>(); + + let _ = window.with_webview(move |webview| { + unsafe { + let wk_webview = webview.inner(); + + // Create WKSnapshotConfiguration + let config: *mut objc::runtime::Object = msg_send![class!(WKSnapshotConfiguration), new]; + + // Set capture rect if provided + if let Some(r) = &rect { + // CGRect layout: {origin.x, origin.y, size.width, size.height} + #[repr(C)] + struct CGRect { x: f64, y: f64, w: f64, h: f64 } + unsafe impl objc::Encode for CGRect { + fn encode() -> objc::Encoding { + unsafe { objc::Encoding::from_str("{CGRect={CGPoint=dd}{CGSize=dd}}") } + } + } + let cg_rect = CGRect { x: r.x, y: r.y, w: r.width, h: r.height }; + let () = msg_send![config, setRect: cg_rect]; + } + + // Wrap sender in Arc> so the closure is Fn (not FnOnce) + let tx = std::sync::Arc::new(std::sync::Mutex::new(Some(tx))); + + let handler = block::ConcreteBlock::new(move |image: cocoa::base::id, error: cocoa::base::id| { + let mut guard = tx.lock().unwrap(); + let tx = match guard.take() { + Some(tx) => tx, + None => return, + }; + if !image.is_null() { + // NSImage -> TIFF -> NSBitmapImageRep -> PNG + let tiff_data: cocoa::base::id = msg_send![image, TIFFRepresentation]; + if tiff_data.is_null() { + let _ = tx.send(Err("Failed to get TIFF representation".to_string())); + return; + } + let bitmap_rep: cocoa::base::id = msg_send![ + class!(NSBitmapImageRep), imageRepWithData: tiff_data + ]; + if bitmap_rep.is_null() { + let _ = tx.send(Err("Failed to create bitmap representation".to_string())); + return; + } + let empty_dict: cocoa::base::id = msg_send![class!(NSDictionary), dictionary]; + // NSBitmapImageFileTypePNG = 4 + let png_data: cocoa::base::id = msg_send![ + bitmap_rep, representationUsingType: 4usize properties: empty_dict + ]; + if png_data.is_null() { + let _ = tx.send(Err("Failed to create PNG data".to_string())); + return; + } + let length: usize = msg_send![png_data, length]; + let bytes: *const u8 = msg_send![png_data, bytes]; + let vec = std::slice::from_raw_parts(bytes, length).to_vec(); + let _ = tx.send(Ok(vec)); + } else { + let err_msg = if !error.is_null() { + let desc: cocoa::base::id = msg_send![error, localizedDescription]; + let utf8: *const std::os::raw::c_char = msg_send![desc, UTF8String]; + if !utf8.is_null() { + std::ffi::CStr::from_ptr(utf8).to_string_lossy().to_string() + } else { + "Screenshot failed".to_string() + } + } else { + "Screenshot failed with unknown error".to_string() + }; + let _ = tx.send(Err(err_msg)); + } + }); + let handler = handler.copy(); + let completion_handler: &block::Block<(cocoa::base::id, cocoa::base::id), ()> = &handler; + + let () = msg_send![ + wk_webview, + takeSnapshotWithConfiguration: config + completionHandler: completion_handler + ]; + } + }).map_err(|e| e.to_string())?; + + return rx.await.map_err(|_| "Capture channel closed".to_string())?; + } + + #[cfg(windows)] + { + return capture_page_windows(window, rect); + } +} + +#[cfg(windows)] +fn capture_page_windows(window: tauri::Window, rect: Option) -> Result, String> { + use winapi::um::winuser::{GetDC, ReleaseDC, GetClientRect, PrintWindow}; + use winapi::um::wingdi::{ + CreateCompatibleDC, CreateCompatibleBitmap, SelectObject, GetDIBits, + DeleteDC, DeleteObject, BITMAPINFOHEADER, BITMAPINFO, BI_RGB, DIB_RGB_COLORS, + }; + use winapi::shared::windef::{RECT, HGDIOBJ}; + + unsafe { + let hwnd = window.hwnd().map_err(|e| e.to_string())?; + let hwnd = hwnd.0 as winapi::shared::windef::HWND; + + let mut client_rect: RECT = std::mem::zeroed(); + GetClientRect(hwnd, &mut client_rect); + let full_width = client_rect.right - client_rect.left; + let full_height = client_rect.bottom - client_rect.top; + + if full_width <= 0 || full_height <= 0 { + return Err("Window has zero client area".to_string()); + } + + let hdc_screen = GetDC(hwnd); + let hdc_mem = CreateCompatibleDC(hdc_screen); + let hbitmap = CreateCompatibleBitmap(hdc_screen, full_width, full_height); + let old_bitmap = SelectObject(hdc_mem, hbitmap as HGDIOBJ); + + // PW_CLIENTONLY=1 | PW_RENDERFULLCONTENT=2 (captures HW-accelerated content) + PrintWindow(hwnd, hdc_mem, 1 | 2); + + let mut bmi: BITMAPINFO = std::mem::zeroed(); + bmi.bmiHeader.biSize = std::mem::size_of::() as u32; + bmi.bmiHeader.biWidth = full_width; + bmi.bmiHeader.biHeight = -full_height; // negative = top-down + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; + bmi.bmiHeader.biCompression = BI_RGB; + + let mut pixels = vec![0u8; (full_width * full_height * 4) as usize]; + GetDIBits( + hdc_mem, hbitmap, 0, full_height as u32, + pixels.as_mut_ptr() as *mut _, + &mut bmi, DIB_RGB_COLORS, + ); + + SelectObject(hdc_mem, old_bitmap); + DeleteObject(hbitmap as HGDIOBJ); + DeleteDC(hdc_mem); + ReleaseDC(hwnd, hdc_screen); + + // BGRA -> RGBA + for chunk in pixels.chunks_exact_mut(4) { + chunk.swap(0, 2); + } + + // Extract the requested region (or full image) + let (cap_x, cap_y, cap_w, cap_h) = if let Some(r) = &rect { + let x = (r.x as i32).max(0).min(full_width); + let y = (r.y as i32).max(0).min(full_height); + let w = (r.width as i32).min(full_width - x).max(0); + let h = (r.height as i32).min(full_height - y).max(0); + (x, y, w, h) + } else { + (0, 0, full_width, full_height) + }; + + if cap_w <= 0 || cap_h <= 0 { + return Err("Capture region is empty".to_string()); + } + + let mut region_pixels = Vec::with_capacity((cap_w * cap_h * 4) as usize); + for y in cap_y..(cap_y + cap_h) { + let start = ((y * full_width + cap_x) * 4) as usize; + let end = start + (cap_w * 4) as usize; + region_pixels.extend_from_slice(&pixels[start..end]); + } + + // Encode as PNG + let mut png_bytes: Vec = Vec::new(); + { + let mut encoder = png::Encoder::new(&mut png_bytes, cap_w as u32, cap_h as u32); + encoder.set_color(png::ColorType::Rgba); + encoder.set_depth(png::BitDepth::Eight); + let mut writer = encoder.write_header().map_err(|e| e.to_string())?; + writer.write_image_data(®ion_pixels).map_err(|e| e.to_string())?; + } + Ok(png_bytes) + } +} + const PHOENIX_CRED_PREFIX: &str = "phcode_"; fn get_username() -> String { @@ -627,7 +833,7 @@ fn main() { put_item, get_item, get_all_items, delete_item, trust_window_aes_key, remove_trust_window_aes_key, _get_windows_drives, _rename_path, show_in_folder, move_to_trash, zoom_window, - _get_clipboard_files, _open_url_in_browser_win]) + _get_clipboard_files, _open_url_in_browser_win, capture_page]) .setup(|app| { init::init_app(app); #[cfg(target_os = "linux")] From 55b9aa2c854363baab6d83ab74bffd682c091e37 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 13 Feb 2026 20:28:47 +0530 Subject: [PATCH 799/864] chore: deal update --- docs/appNotifications/prod/de/banner.json | 4 ++-- docs/appNotifications/prod/fr/banner.json | 4 ++-- docs/appNotifications/prod/it/banner.json | 4 ++-- docs/appNotifications/prod/ja/banner.json | 4 ++-- docs/appNotifications/prod/ko/banner.json | 4 ++-- docs/appNotifications/prod/pt-BR/banner.json | 4 ++-- docs/appNotifications/prod/root/banner.json | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/appNotifications/prod/de/banner.json b/docs/appNotifications/prod/de/banner.json index 9cf1b65d..a4a2306a 100644 --- a/docs/appNotifications/prod/de/banner.json +++ b/docs/appNotifications/prod/de/banner.json @@ -5,9 +5,9 @@ "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" }, - "LIFETIME_DEAL_V_5_0_0_DEAL": { + "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro Lifetime-Angebot
Besitzen Sie Phoenix Pro dauerhaft mit einer einmaligen Zahlung. Endet in 11 Tagen.
", + "HTML_CONTENT": "
Phoenix Pro Lifetime-Angebot
Besitzen Sie Phoenix Pro dauerhaft mit einer einmaligen Zahlung. Endet in 5 Tagen.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/fr/banner.json b/docs/appNotifications/prod/fr/banner.json index f3a6b80c..218584f1 100644 --- a/docs/appNotifications/prod/fr/banner.json +++ b/docs/appNotifications/prod/fr/banner.json @@ -5,9 +5,9 @@ "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" }, - "LIFETIME_DEAL_V_5_0_0_DEAL": { + "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Offre à vie Phoenix Pro
Obtenez Phoenix Pro pour toujours avec un paiement unique. Se termine dans 11 jours.
", + "HTML_CONTENT": "
Offre à vie Phoenix Pro
Obtenez Phoenix Pro pour toujours avec un paiement unique. Se termine dans 5 jours.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/it/banner.json b/docs/appNotifications/prod/it/banner.json index 8ecfba6e..8acd0435 100644 --- a/docs/appNotifications/prod/it/banner.json +++ b/docs/appNotifications/prod/it/banner.json @@ -5,9 +5,9 @@ "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" }, - "LIFETIME_DEAL_V_5_0_0_DEAL": { + "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Offerta a vita Phoenix Pro
Ottieni Phoenix Pro per sempre con un pagamento unico. Scade tra 11 giorni.
", + "HTML_CONTENT": "
Offerta a vita Phoenix Pro
Ottieni Phoenix Pro per sempre con un pagamento unico. Scade tra 5 giorni.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/ja/banner.json b/docs/appNotifications/prod/ja/banner.json index 78a590e1..4578db3b 100644 --- a/docs/appNotifications/prod/ja/banner.json +++ b/docs/appNotifications/prod/ja/banner.json @@ -5,9 +5,9 @@ "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" }, - "LIFETIME_DEAL_V_5_0_0_DEAL": { + "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro 永久ライセンス
一度の支払いで Phoenix Pro を永久に利用できます。11日後に終了します。
", + "HTML_CONTENT": "
Phoenix Pro 永久ライセンス
一度の支払いで Phoenix Pro を永久に利用できます。5日後に終了します。
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/ko/banner.json b/docs/appNotifications/prod/ko/banner.json index 406d4174..53a30e45 100644 --- a/docs/appNotifications/prod/ko/banner.json +++ b/docs/appNotifications/prod/ko/banner.json @@ -5,9 +5,9 @@ "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" }, - "LIFETIME_DEAL_V_5_0_0_DEAL": { + "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro 평생 이용권
한 번의 결제로 Phoenix Pro 를 평생 사용하세요. 11일 후 종료됩니다.
", + "HTML_CONTENT": "
Phoenix Pro 평생 이용권
한 번의 결제로 Phoenix Pro 를 평생 사용하세요. 5일 후 종료됩니다.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/pt-BR/banner.json b/docs/appNotifications/prod/pt-BR/banner.json index 4b789a02..44cbe221 100644 --- a/docs/appNotifications/prod/pt-BR/banner.json +++ b/docs/appNotifications/prod/pt-BR/banner.json @@ -5,9 +5,9 @@ "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" }, - "LIFETIME_DEAL_V_5_0_0_DEAL": { + "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Oferta vitalícia do Phoenix Pro
Tenha Phoenix Pro para sempre com um pagamento único. Termina em 11 dias.
", + "HTML_CONTENT": "
Oferta vitalícia do Phoenix Pro
Tenha Phoenix Pro para sempre com um pagamento único. Termina em 5 dias.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/root/banner.json b/docs/appNotifications/prod/root/banner.json index b15d0455..4546a275 100644 --- a/docs/appNotifications/prod/root/banner.json +++ b/docs/appNotifications/prod/root/banner.json @@ -5,9 +5,9 @@ "FOR_VERSIONS": ">=3.0.0", "PLATFORM" : "allBrowser" }, - "LIFETIME_DEAL_V_5_0_0_DEAL": { + "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro Lifetime Deal
Own Phoenix Pro forever with a one-time purchase. Ends in 11 days.
", + "HTML_CONTENT": "
Phoenix Pro Lifetime Deal
Own Phoenix Pro forever with a one-time purchase. Ends in 5 days.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] From 43b36fad39d28143cc86880ccb00c74b6e58509d Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 16 Feb 2026 07:48:31 +0530 Subject: [PATCH 800/864] chore: deal update --- docs/appNotifications/prod/de/banner.json | 2 +- docs/appNotifications/prod/fr/banner.json | 2 +- docs/appNotifications/prod/it/banner.json | 2 +- docs/appNotifications/prod/ja/banner.json | 2 +- docs/appNotifications/prod/ko/banner.json | 2 +- docs/appNotifications/prod/pt-BR/banner.json | 2 +- docs/appNotifications/prod/root/banner.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/appNotifications/prod/de/banner.json b/docs/appNotifications/prod/de/banner.json index a4a2306a..81979de3 100644 --- a/docs/appNotifications/prod/de/banner.json +++ b/docs/appNotifications/prod/de/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro Lifetime-Angebot
Besitzen Sie Phoenix Pro dauerhaft mit einer einmaligen Zahlung. Endet in 5 Tagen.
", + "HTML_CONTENT": "
Phoenix Pro Lifetime-Angebot
Besitzen Sie Phoenix Pro dauerhaft mit einer einmaligen Zahlung. Endet in 3 Tagen.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/fr/banner.json b/docs/appNotifications/prod/fr/banner.json index 218584f1..9eed6749 100644 --- a/docs/appNotifications/prod/fr/banner.json +++ b/docs/appNotifications/prod/fr/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Offre à vie Phoenix Pro
Obtenez Phoenix Pro pour toujours avec un paiement unique. Se termine dans 5 jours.
", + "HTML_CONTENT": "
Offre à vie Phoenix Pro
Obtenez Phoenix Pro pour toujours avec un paiement unique. Se termine dans 3 jours.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/it/banner.json b/docs/appNotifications/prod/it/banner.json index 8acd0435..691773e6 100644 --- a/docs/appNotifications/prod/it/banner.json +++ b/docs/appNotifications/prod/it/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Offerta a vita Phoenix Pro
Ottieni Phoenix Pro per sempre con un pagamento unico. Scade tra 5 giorni.
", + "HTML_CONTENT": "
Offerta a vita Phoenix Pro
Ottieni Phoenix Pro per sempre con un pagamento unico. Scade tra 3 giorni.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/ja/banner.json b/docs/appNotifications/prod/ja/banner.json index 4578db3b..71a2e050 100644 --- a/docs/appNotifications/prod/ja/banner.json +++ b/docs/appNotifications/prod/ja/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro 永久ライセンス
一度の支払いで Phoenix Pro を永久に利用できます。5日後に終了します。
", + "HTML_CONTENT": "
Phoenix Pro 永久ライセンス
一度の支払いで Phoenix Pro を永久に利用できます。3日後に終了します。
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/ko/banner.json b/docs/appNotifications/prod/ko/banner.json index 53a30e45..f666a6ff 100644 --- a/docs/appNotifications/prod/ko/banner.json +++ b/docs/appNotifications/prod/ko/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro 평생 이용권
한 번의 결제로 Phoenix Pro 를 평생 사용하세요. 5일 후 종료됩니다.
", + "HTML_CONTENT": "
Phoenix Pro 평생 이용권
한 번의 결제로 Phoenix Pro 를 평생 사용하세요. 3일 후 종료됩니다.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/pt-BR/banner.json b/docs/appNotifications/prod/pt-BR/banner.json index 44cbe221..8b0142f8 100644 --- a/docs/appNotifications/prod/pt-BR/banner.json +++ b/docs/appNotifications/prod/pt-BR/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Oferta vitalícia do Phoenix Pro
Tenha Phoenix Pro para sempre com um pagamento único. Termina em 5 dias.
", + "HTML_CONTENT": "
Oferta vitalícia do Phoenix Pro
Tenha Phoenix Pro para sempre com um pagamento único. Termina em 3 dias.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/root/banner.json b/docs/appNotifications/prod/root/banner.json index 4546a275..39fe7eb2 100644 --- a/docs/appNotifications/prod/root/banner.json +++ b/docs/appNotifications/prod/root/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro Lifetime Deal
Own Phoenix Pro forever with a one-time purchase. Ends in 5 days.
", + "HTML_CONTENT": "
Phoenix Pro Lifetime Deal
Own Phoenix Pro forever with a one-time purchase. Ends in 3 days.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] From 27f7b3c22248766a5bc32dc11093ea5c9f7aef87 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 23 Feb 2026 16:18:34 +0000 Subject: [PATCH 801/864] ci: update phcode version to 5.1.4 --- package.json | 6 +++--- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 335aa652..8815ca3a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.3", + "version": "5.1.4", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "deb309997d34383ffc01c623902537ad095c79f3" + "commit": "cd1d3c85338c863d811ceb642de4cd704fde0a59" } -} +} \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 96cab372..0f6598e4 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.3", + "version": "5.1.4", "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", "main": "main.js", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ffffac21..4fb1e663 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.3" +version = "5.1.4" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index fb7234fe..fff66118 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.3" + "version": "5.1.4" }, "tauri": { "allowlist": { From af50d3ac3b3aa5a709852cd4b89a11219be104b1 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 24 Feb 2026 08:12:25 +0530 Subject: [PATCH 802/864] fix: mac notarization errors --- src-build/mac/filesToSign | 8 ++++++++ src-build/makeSrcNode.js | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src-build/mac/filesToSign b/src-build/mac/filesToSign index 5ced227e..9291cf46 100644 --- a/src-build/mac/filesToSign +++ b/src-build/mac/filesToSign @@ -10,3 +10,11 @@ src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/no src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.abi108.glibc.node src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/node.napi.glibc.node src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.napi.glibc.node +src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/x64-darwin/ripgrep.node +src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/x64-darwin/rg +src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/arm64-darwin/ripgrep.node +src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/arm64-darwin/rg +src-node/node_modules/@img/sharp-darwin-x64/lib/sharp-darwin-x64.node +src-node/node_modules/@img/sharp-libvips-darwin-x64/lib/libvips-cpp.42.dylib +src-node/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node +src-node/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.42.dylib diff --git a/src-build/makeSrcNode.js b/src-build/makeSrcNode.js index 5d7f3f08..32adaa1a 100644 --- a/src-build/makeSrcNode.js +++ b/src-build/makeSrcNode.js @@ -34,6 +34,10 @@ function setupTarget(srcPath, destPath) { execSync(`shx rm -f ${destPath}/node_modules/@msgpackr-extract/msgpackr-extract-linux-*/*.musl.node`, { stdio: 'pipe' }); execSync(`shx rm -f ${destPath}/node_modules/@lmdb/lmdb-linux-*/*.musl.node`, { stdio: 'pipe' }); + // Remove JetBrains plugin (not needed in Phoenix Code, contains unsigned native binaries that block macOS notarization) + console.log('Removing claude-code JetBrains plugin...'); + execSync(`shx rm -rf ${destPath}/node_modules/@anthropic-ai/claude-code/vendor/claude-code-jetbrains-plugin`, { stdio: 'pipe' }); + console.log(`${destPath} setup complete!`); } From ac51227b7d009bb5b2bd5a96dcc01de71652a608 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 24 Feb 2026 08:26:36 +0530 Subject: [PATCH 803/864] fix: mac notarization errors --- .github/workflows/tauri-build-dev.yml | 2 +- .github/workflows/tauri-build-prod.yml | 2 +- .github/workflows/tauri-build-staging.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 49cf7c8b..87c7d6ae 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -205,7 +205,7 @@ jobs: # Sign the files specified in src-build/mac/filesToSign while IFS= read -r file; do if [ -f "$file" ]; then - codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" + codesign --force --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" else echo "File to sign not found, ignoring: $file" fi diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index 634aaa0e..c028c1c0 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -206,7 +206,7 @@ jobs: # Sign the files specified in src-build/mac/filesToSign while IFS= read -r file; do if [ -f "$file" ]; then - codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" + codesign --force --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" else echo "File to sign not found, ignoring: $file" fi diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index c52e0042..33d86303 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -205,7 +205,7 @@ jobs: # Sign the files specified in src-build/mac/filesToSign while IFS= read -r file; do if [ -f "$file" ]; then - codesign --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" + codesign --force --sign "$APPLE_KEY_IDENTITY_NAME" --keychain build.keychain --timestamp --options runtime "$file" else echo "File to sign not found, ignoring: $file" fi From cadb0f9c44129f2a445fb1e27afcb3062da1bd44 Mon Sep 17 00:00:00 2001 From: abose Date: Tue, 24 Feb 2026 08:53:24 +0530 Subject: [PATCH 804/864] fix: mac notarization errors --- src-build/mac/filesToSign | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src-build/mac/filesToSign b/src-build/mac/filesToSign index 9291cf46..a5055f24 100644 --- a/src-build/mac/filesToSign +++ b/src-build/mac/filesToSign @@ -10,11 +10,19 @@ src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/no src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.abi108.glibc.node src-tauri/src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64/node.napi.glibc.node src-node/node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64/node.napi.glibc.node +src-tauri/src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/x64-darwin/ripgrep.node src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/x64-darwin/ripgrep.node +src-tauri/src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/x64-darwin/rg src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/x64-darwin/rg +src-tauri/src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/arm64-darwin/ripgrep.node src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/arm64-darwin/ripgrep.node +src-tauri/src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/arm64-darwin/rg src-node/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/arm64-darwin/rg +src-tauri/src-node/node_modules/@img/sharp-darwin-x64/lib/sharp-darwin-x64.node src-node/node_modules/@img/sharp-darwin-x64/lib/sharp-darwin-x64.node +src-tauri/src-node/node_modules/@img/sharp-libvips-darwin-x64/lib/libvips-cpp.42.dylib src-node/node_modules/@img/sharp-libvips-darwin-x64/lib/libvips-cpp.42.dylib +src-tauri/src-node/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node src-node/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node +src-tauri/src-node/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.42.dylib src-node/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.42.dylib From ac4195d572cda7e6abda30e2a1e91db0c8fc7f87 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 2 Mar 2026 15:58:28 +0530 Subject: [PATCH 805/864] fix: disable browser accelerator keys (F5 reload) in Windows webviews Uses WebView2 ICoreWebView2Settings3 API via on_page_load to disable browser accelerator keys in all windows, preventing F5 from reloading the app. Applies to both config-defined and dynamically created windows. Co-Authored-By: Claude Opus 4.6 --- src-tauri/Cargo.lock | 4 +++- src-tauri/Cargo.toml | 2 ++ src-tauri/src/main.rs | 19 +++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 3ec98a5a..6fd45394 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3407,7 +3407,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "5.1.2" +version = "5.1.4" dependencies = [ "aes-gcm", "backtrace", @@ -3441,8 +3441,10 @@ dependencies = [ "trash", "webbrowser", "webkit2gtk", + "webview2-com", "whoami", "winapi 0.3.9", + "windows 0.39.0", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 4fb1e663..5a2dbdc4 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -43,6 +43,8 @@ hex = "0.4.3" [target.'cfg(target_os = "windows")'.dependencies] native-dialog = "0.7.0" +webview2-com = "0.19" +windows = { version = "0.39", features = ["Win32_Foundation"] } [target.'cfg(target_os = "linux")'.dependencies] gtk = "0.15" diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c78254bf..c344024b 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -819,6 +819,25 @@ fn main() { app.emit_all("single-instance", Payload { args: argv, cwd }).unwrap(); })) + .on_page_load(|window, _payload| { + // Disable browser accelerator keys (F5 reload, Ctrl+R, etc.) in all webviews + // to prevent the window from reloading on F5 key press + #[cfg(target_os = "windows")] + { + let _ = window.with_webview(|webview| { + unsafe { + use webview2_com::Microsoft::Web::WebView2::Win32::ICoreWebView2Settings3; + use windows::core::Interface; + let core_webview = webview.controller().CoreWebView2().unwrap(); + let settings = core_webview.Settings().unwrap(); + let settings3: ICoreWebView2Settings3 = settings.cast().unwrap(); + settings3.SetAreBrowserAcceleratorKeysEnabled(false).unwrap(); + } + }); + } + #[cfg(not(target_os = "windows"))] + let _ = window; // suppress unused warning on non-windows + }) .on_window_event(|event| { // Get the trust state from the app handle let app_handle = event.window().app_handle(); From aab53fa6906534403556d761e84cb4a21be69df3 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 2 Mar 2026 20:34:35 +0530 Subject: [PATCH 806/864] fix: restore custom window position/size persistence across restarts Replace non-functional tauri-plugin-window-state with a custom implementation that saves window x, y, width, height, and maximized state to boot_config.json on close and restores on launch. - Add window state fields to BootConfig struct - Add restore_window_state() with multi-monitor awareness: validates saved position against connected monitors, maximizes if saved size exceeds current screen, falls back to 1366x900 on first launch - Save outer_size (not inner_size) to avoid progressive shrinking from title bar/border mismatch - Remove tauri-plugin-window-state dependency and plugin registration Co-Authored-By: Claude Opus 4.6 --- src-tauri/Cargo.lock | 24 ------- src-tauri/Cargo.toml | 1 - src-tauri/src/boot_config.rs | 45 +++++++++++-- src-tauri/src/init.rs | 118 ++++++++++++++++++++++++++++++++++- src-tauri/src/main.rs | 18 ++++-- 5 files changed, 169 insertions(+), 37 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 6fd45394..dfa1a4cd 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -380,15 +380,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -3436,7 +3427,6 @@ dependencies = [ "tauri-plugin-deep-link", "tauri-plugin-fs-extra", "tauri-plugin-single-instance", - "tauri-plugin-window-state", "tokio", "trash", "webbrowser", @@ -4828,20 +4818,6 @@ dependencies = [ "zbus", ] -[[package]] -name = "tauri-plugin-window-state" -version = "0.1.1" -source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#184f4edbbcfed8f8c057a15e02318e0ddcaab132" -dependencies = [ - "bincode", - "bitflags 2.5.0", - "log", - "serde", - "serde_json", - "tauri", - "thiserror", -] - [[package]] name = "tauri-runtime" version = "0.14.6" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5a2dbdc4..6c8709e5 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -31,7 +31,6 @@ tauri = { version = "1.6.2", features = [ "updater", "cli", "api-all", "devtools winapi = { version = "0.3.9", features = ["fileapi", "wingdi", "winuser", "windef"] } png = "0.17" tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } -tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } fix-path-env = { git = "https://github.com/tauri-apps/fix-path-env-rs" } keyring = "2.3.3" diff --git a/src-tauri/src/boot_config.rs b/src-tauri/src/boot_config.rs index 19b61742..e965984f 100644 --- a/src-tauri/src/boot_config.rs +++ b/src-tauri/src/boot_config.rs @@ -15,7 +15,12 @@ pub static APP_CONSTANTS: OnceCell = OnceCell::new(); #[derive(Serialize)] pub struct BootConfig { - pub version: u32 + pub version: u32, + pub last_window_x: i32, + pub last_window_y: i32, + pub last_window_width: u32, + pub last_window_height: u32, + pub last_window_maximized: bool, } static BOOT_CONFIG_FILE_NAME: &'static str = "boot_config.json"; @@ -30,11 +35,36 @@ fn _set_boot_config(boot_config: &mut BootConfig, value: &Value) { Some(value) => value as u32, None => 0 }; + boot_config.last_window_x = match value["last_window_x"].as_i64() { + Some(v) => v as i32, + None => 0 + }; + boot_config.last_window_y = match value["last_window_y"].as_i64() { + Some(v) => v as i32, + None => 0 + }; + boot_config.last_window_width = match value["last_window_width"].as_u64() { + Some(v) => v as u32, + None => 0 + }; + boot_config.last_window_height = match value["last_window_height"].as_u64() { + Some(v) => v as u32, + None => 0 + }; + boot_config.last_window_maximized = match value["last_window_maximized"].as_bool() { + Some(v) => v, + None => false + }; } pub fn read_boot_config() -> BootConfig { let mut boot_config = BootConfig { - version: 1 + version: 1, + last_window_x: 0, + last_window_y: 0, + last_window_width: 0, + last_window_height: 0, + last_window_maximized: false, }; if let Some(app_constants) = APP_CONSTANTS.get() { let boot_config_file_path = get_boot_config_file_path(&app_constants.app_local_data_dir); @@ -62,8 +92,13 @@ fn _write_boot_config(boot_config: &BootConfig) { } // WARNING: If there are multiple windows, this will be called on each window close. -pub fn write_boot_config(version: u32) { +pub fn write_boot_config(version: u32, x: i32, y: i32, width: u32, height: u32, maximized: bool) { _write_boot_config(&BootConfig { - version - }) + version, + last_window_x: x, + last_window_y: y, + last_window_width: width, + last_window_height: height, + last_window_maximized: maximized, + }) } \ No newline at end of file diff --git a/src-tauri/src/init.rs b/src-tauri/src/init.rs index 1532a8c8..363d6e66 100644 --- a/src-tauri/src/init.rs +++ b/src-tauri/src/init.rs @@ -1,7 +1,118 @@ use crate::utilities::ensure_dir_exists; -use crate::boot_config::read_boot_config; +use crate::boot_config::{read_boot_config, BootConfig}; use crate::boot_config::APP_CONSTANTS; use crate::boot_config::AppConstants; +use tauri::Manager; + +/// Returns true if the point (x, y) falls within any of the available monitors. +fn is_position_on_any_monitor(x: i32, y: i32, monitors: &[tauri::Monitor]) -> bool { + for monitor in monitors { + let mon_pos = monitor.position(); + let mon_size = monitor.size(); + if x >= mon_pos.x + && x < mon_pos.x + mon_size.width as i32 + && y >= mon_pos.y + && y < mon_pos.y + mon_size.height as i32 + { + return true; + } + } + false +} + +/// Restores the main window's position, size, and maximized state from boot_config. +/// This is intentionally fault-tolerant: any failure is logged and silently ignored +/// so the app always starts, even with a corrupted or missing config. +fn restore_window_state(app: &mut tauri::App, boot_config: &BootConfig) { + let win = match app.get_window("main") { + Some(w) => w, + None => { + eprintln!("restore_window_state: could not find main window"); + return; + } + }; + + if boot_config.last_window_maximized { + if let Err(e) = win.maximize() { + eprintln!("restore_window_state: failed to maximize window: {}", e); + } + return; + } + + let saved_w = boot_config.last_window_width; + let saved_h = boot_config.last_window_height; + + if saved_w > 0 && saved_h > 0 { + // If the saved size exceeds the current screen, maximize instead of clamping. + // Clamping to raw pixels would still ignore taskbar/dock; maximizing lets the + // OS place the window correctly within the usable work area. + let fits_screen = match win.current_monitor() { + Ok(Some(monitor)) => { + let screen = monitor.size(); + saved_w <= screen.width && saved_h <= screen.height + } + _ => true, // can't determine screen size, assume it fits + }; + + if !fits_screen { + if let Err(e) = win.maximize() { + eprintln!("restore_window_state: failed to maximize for oversized saved state: {}", e); + } + } else { + if let Err(e) = win.set_size(tauri::Size::Physical(tauri::PhysicalSize { + width: saved_w, + height: saved_h, + })) { + eprintln!("restore_window_state: failed to set window size: {}", e); + } + + // Restore position only if the saved position is on a currently connected monitor + let saved_x = boot_config.last_window_x; + let saved_y = boot_config.last_window_y; + match win.available_monitors() { + Ok(monitors) => { + if is_position_on_any_monitor(saved_x, saved_y, &monitors) { + if let Err(e) = win.set_position(tauri::Position::Physical( + tauri::PhysicalPosition { x: saved_x, y: saved_y }, + )) { + eprintln!("restore_window_state: failed to set window position: {}", e); + } + } + // else: monitor disconnected, let the OS place the window + } + Err(e) => { + eprintln!("restore_window_state: failed to list monitors: {}", e); + // Cannot validate position; skip position restore, size is already set + } + } + } + } else { + // First launch (no saved state) - use preferred size or maximize if screen is too small + match win.current_monitor() { + Ok(Some(monitor)) => { + let screen = monitor.size(); + if screen.width > 1366 && screen.height > 900 { + if let Err(e) = win.set_size(tauri::Size::Physical(tauri::PhysicalSize { + width: 1366, + height: 900, + })) { + eprintln!("restore_window_state: failed to set default size: {}", e); + } + } else { + if let Err(e) = win.maximize() { + eprintln!("restore_window_state: failed to maximize on small screen: {}", e); + } + } + } + Ok(None) => { + eprintln!("restore_window_state: no current monitor detected"); + } + Err(e) => { + eprintln!("restore_window_state: failed to get current monitor: {}", e); + } + } + } +} pub fn init_app(app: &mut tauri::App) { let config = app.config().clone(); @@ -19,9 +130,10 @@ pub fn init_app(app: &mut tauri::App) { println!("Bundle ID is {}", app_constants.tauri_config.tauri.bundle.identifier); } ensure_dir_exists(&app_constants.app_local_data_dir); - read_boot_config(); + let boot_config = read_boot_config(); #[cfg(debug_assertions)]{ - println!("Bootconfig version is {}", read_boot_config().version); + println!("Bootconfig version is {}", boot_config.version); } + restore_window_state(app, &boot_config); } } \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index c344024b..51a37bf4 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -47,7 +47,6 @@ mod boot_config; use trash; mod platform; -use tauri_plugin_window_state::StateFlags; use keyring::Entry; use whoami; @@ -352,8 +351,20 @@ fn process_window_event(event: &GlobalWindowEvent, trust_state: &State (pos.x, pos.y), + Err(_) => (0, 0), + }; + let (width, height) = match window.outer_size() { + Ok(size) => (size.width, size.height), + Err(_) => (0, 0), + }; + boot_config::write_boot_config(1, x, y, width, height, maximized); + } } } @@ -813,7 +824,6 @@ fn main() { Ok(response) }) .plugin(tauri_plugin_fs_extra::init()) - .plugin(tauri_plugin_window_state::Builder::default().with_state_flags(StateFlags::all() & !StateFlags::VISIBLE).build()) .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| { println!("{}, {argv:?}, {cwd}", app.package_info().name); From 61693b356a89bd700f59874f84172230b7e34dca Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 4 Mar 2026 15:42:35 +0530 Subject: [PATCH 807/864] fix: use inner_size on Windows to prevent window growing on each restart On Windows, set_size() sets the client area but outer_size() includes decorations, causing the window to grow by the decoration size on each save/restore cycle. Use inner_size() on Windows for consistent round-trip. Co-Authored-By: Claude Opus 4.6 --- src-tauri/src/main.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 51a37bf4..5793f430 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -359,9 +359,24 @@ fn process_window_event(event: &GlobalWindowEvent, trust_state: &State (pos.x, pos.y), Err(_) => (0, 0), }; - let (width, height) = match window.outer_size() { - Ok(size) => (size.width, size.height), - Err(_) => (0, 0), + // On Windows, set_size() sets the inner (client) area, so we must save + // inner_size() to avoid the window growing by the decoration size on each restart. + // On macOS, outer_size()/set_size() are consistent, so we keep outer_size(). + let (width, height) = { + #[cfg(target_os = "windows")] + { + match window.inner_size() { + Ok(size) => (size.width, size.height), + Err(_) => (0, 0), + } + } + #[cfg(not(target_os = "windows"))] + { + match window.outer_size() { + Ok(size) => (size.width, size.height), + Err(_) => (0, 0), + } + } }; boot_config::write_boot_config(1, x, y, width, height, maximized); } From 1a26b8fb2b7f2b487872120f346036b5a69f1c12 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 3 Apr 2026 13:47:24 +0000 Subject: [PATCH 808/864] ci: update phcode version to 5.1.5 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8815ca3a..7cb51d17 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.4", + "version": "5.1.5", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "cd1d3c85338c863d811ceb642de4cd704fde0a59" + "commit": "31ea5ae5623623586d8d39d84e43cc61af9b3b05" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 0f6598e4..85811d88 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.4", + "version": "5.1.5", "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", "main": "main.js", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 6c8709e5..135d6a54 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.4" +version = "5.1.5" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index fff66118..37563321 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.4" + "version": "5.1.5" }, "tauri": { "allowlist": { From a4f87ff0e1b4654a5b4a502adcc7ae1802f9537c Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 4 Apr 2026 00:30:26 +0530 Subject: [PATCH 809/864] build: update electron version --- package-lock.json | 5 ++- src-electron/package-lock.json | 60 ++++++++++++++++++++++++---------- src-electron/package.json | 4 +-- 3 files changed, 47 insertions(+), 22 deletions(-) diff --git a/package-lock.json b/package-lock.json index 99aa4e7a..a1412225 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "5.1.0", + "version": "5.1.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "5.1.0", + "version": "5.1.5", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.3", @@ -453,7 +453,6 @@ "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", diff --git a/src-electron/package-lock.json b/src-electron/package-lock.json index d722b9ba..19b2ec2c 100644 --- a/src-electron/package-lock.json +++ b/src-electron/package-lock.json @@ -1,17 +1,17 @@ { "name": "phoenix-code-electron-shell", - "version": "5.0.5", + "version": "5.1.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-electron-shell", - "version": "5.0.5", + "version": "5.1.5", "dependencies": { "keytar": "^7.9.0" }, "devDependencies": { - "electron": "^40.0.0", + "electron": "^41.1.1", "electron-builder": "^24.13.3" } }, @@ -669,7 +669,6 @@ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -824,6 +823,7 @@ "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "archiver-utils": "^2.1.0", "async": "^3.2.4", @@ -843,6 +843,7 @@ "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "glob": "^7.1.4", "graceful-fs": "^4.2.0", @@ -865,6 +866,7 @@ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -880,7 +882,8 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/archiver-utils/node_modules/string_decoder": { "version": "1.1.1", @@ -888,6 +891,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -1349,6 +1353,7 @@ "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "buffer-crc32": "^0.2.13", "crc32-stream": "^4.0.2", @@ -1448,6 +1453,7 @@ "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "crc32": "bin/crc32.njs" }, @@ -1461,6 +1467,7 @@ "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^3.4.0" @@ -1647,7 +1654,6 @@ "integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "app-builder-lib": "24.13.3", "builder-util": "24.13.1", @@ -1781,11 +1787,12 @@ } }, "node_modules/electron": { - "version": "40.0.0", - "resolved": "https://registry.npmjs.org/electron/-/electron-40.0.0.tgz", - "integrity": "sha512-UyBy5yJ0/wm4gNugCtNPjvddjAknMTuXR2aCHioXicH7aKRKGDBPp4xqTEi/doVcB3R+MN3wfU9o8d/9pwgK2A==", + "version": "41.1.1", + "resolved": "https://registry.npmjs.org/electron/-/electron-41.1.1.tgz", + "integrity": "sha512-8bgvDhBjli+3Z2YCKgzzoBPh6391pr7Xv2h/tTJG4ETgvPvUxZomObbZLs31mUzYb6VrlcDDd9cyWyNKtPm3tA==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^24.9.0", @@ -1831,6 +1838,7 @@ "integrity": "sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "app-builder-lib": "24.13.3", "archiver": "^5.3.1", @@ -1844,6 +1852,7 @@ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -1859,6 +1868,7 @@ "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "universalify": "^2.0.0" }, @@ -1872,6 +1882,7 @@ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 10.0.0" } @@ -2690,7 +2701,8 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/isbinaryfile": { "version": "5.0.7", @@ -2834,6 +2846,7 @@ "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "readable-stream": "^2.0.5" }, @@ -2847,6 +2860,7 @@ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -2862,7 +2876,8 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lazystream/node_modules/string_decoder": { "version": "1.1.1", @@ -2870,6 +2885,7 @@ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -2886,35 +2902,40 @@ "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.difference": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lowercase-keys": { "version": "2.0.0", @@ -3132,6 +3153,7 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -3285,7 +3307,8 @@ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/progress": { "version": "2.0.3", @@ -3394,6 +3417,7 @@ "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "minimatch": "^5.1.0" } @@ -4166,6 +4190,7 @@ "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "archiver-utils": "^3.0.4", "compress-commons": "^4.1.2", @@ -4181,6 +4206,7 @@ "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "glob": "^7.2.3", "graceful-fs": "^4.2.0", diff --git a/src-electron/package.json b/src-electron/package.json index 85811d88..9a2c0e38 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -19,7 +19,7 @@ "keytar": "^7.9.0" }, "devDependencies": { - "electron": "^40.0.0", + "electron": "^41.1.1", "electron-builder": "^24.13.3" } -} \ No newline at end of file +} From cae436d0d14614657ebb9ab33f59dcdc2d68727e Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 4 Apr 2026 00:33:08 +0530 Subject: [PATCH 810/864] fix: add node-pty binaries to macOS code signing list Fixes notarization failures by signing pty.node and spawn-helper for both darwin-x64 and darwin-arm64 architectures. Co-Authored-By: Claude Opus 4.6 (1M context) --- src-build/mac/filesToSign | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src-build/mac/filesToSign b/src-build/mac/filesToSign index a5055f24..b575e2aa 100644 --- a/src-build/mac/filesToSign +++ b/src-build/mac/filesToSign @@ -26,3 +26,11 @@ src-tauri/src-node/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.n src-node/node_modules/@img/sharp-darwin-arm64/lib/sharp-darwin-arm64.node src-tauri/src-node/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.42.dylib src-node/node_modules/@img/sharp-libvips-darwin-arm64/lib/libvips-cpp.42.dylib +src-tauri/src-node/node_modules/node-pty/prebuilds/darwin-x64/pty.node +src-node/node_modules/node-pty/prebuilds/darwin-x64/pty.node +src-tauri/src-node/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +src-node/node_modules/node-pty/prebuilds/darwin-x64/spawn-helper +src-tauri/src-node/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +src-node/node_modules/node-pty/prebuilds/darwin-arm64/pty.node +src-tauri/src-node/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper +src-node/node_modules/node-pty/prebuilds/darwin-arm64/spawn-helper From 9e0af05b52c66ea38ec35885d9453143f30f49c8 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 3 Apr 2026 19:28:35 +0000 Subject: [PATCH 811/864] ci: update phcode version to 5.1.6 --- package.json | 4 ++-- src-electron/package.json | 4 ++-- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 7cb51d17..fd19e292 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.5", + "version": "5.1.6", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "31ea5ae5623623586d8d39d84e43cc61af9b3b05" + "commit": "a97d1a64c4ed53237c37dabc724c087151ae1c44" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 9a2c0e38..5b3bdb4f 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.5", + "version": "5.1.6", "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", "main": "main.js", @@ -22,4 +22,4 @@ "electron": "^41.1.1", "electron-builder": "^24.13.3" } -} +} \ No newline at end of file diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 135d6a54..d05e93e1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.5" +version = "5.1.6" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 37563321..e80b12ab 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.5" + "version": "5.1.6" }, "tauri": { "allowlist": { From 9faabfd6956262daa29ad7945e3450bcf1a91765 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sun, 19 Apr 2026 05:54:35 +0000 Subject: [PATCH 812/864] ci: update phcode version to 5.1.7 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index fd19e292..3656a33f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.6", + "version": "5.1.7", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "a97d1a64c4ed53237c37dabc724c087151ae1c44" + "commit": "8a39ffbfe173dc5401fa0e1af52f6d04b59b9333" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 5b3bdb4f..5f782aa5 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.6", + "version": "5.1.7", "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", "main": "main.js", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d05e93e1..218f96a7 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.6" +version = "5.1.7" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index e80b12ab..b527e084 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.6" + "version": "5.1.7" }, "tauri": { "allowlist": { From 8b0f1fa44f7cf8b57eac8200835be639911122a6 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 19 Apr 2026 19:57:29 +0530 Subject: [PATCH 813/864] fix: markdown viewer doesnt appear in prod windows builds --- src-tauri/src/main.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 5793f430..03ca5d0c 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -829,8 +829,12 @@ fn main() { #[cfg(not(windows))] let window_origin = "phtauri://localhost"; + // Wildcard ACAO so CORS succeeds for null-origin sandboxed iframes (the + // markdown viewer is sandboxed without allow-same-origin to contain + // untrusted markdown). Safe: phtauri://localhost isn't reachable from + // outside the Tauri webview, and these responses carry no credentials. let builder = ResponseBuilder::new() - .header("Access-Control-Allow-Origin", window_origin) + .header("Access-Control-Allow-Origin", "*") .header("Origin", window_origin) .header("Cache-Control", "private, max-age=7776000, immutable") // 3 month cache age expiry .mimetype(&asset.mime_type); From db4c65d4b5a3576cc367010d9452cd21f162c05b Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 1 May 2026 16:03:15 +0000 Subject: [PATCH 814/864] ci: update phcode version to 5.1.8 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3656a33f..81a75ba7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.7", + "version": "5.1.8", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "8a39ffbfe173dc5401fa0e1af52f6d04b59b9333" + "commit": "28a97522a6e852ed5f6da59053f1c5ddd966ad14" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 5f782aa5..bc299305 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.7", + "version": "5.1.8", "productName": "Phoenix Code Experimental Build", "description": "Phoenix Code Experimental Build", "main": "main.js", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 218f96a7..ea6f4509 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.7" +version = "5.1.8" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index b527e084..c992ee97 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.7" + "version": "5.1.8" }, "tauri": { "allowlist": { From 1aab1b672e1f2514e899e9a73fe3ceff9d2e255e Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 1 May 2026 18:15:29 +0000 Subject: [PATCH 815/864] ci: update phcode version to 5.1.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 81a75ba7..307a50cb 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "28a97522a6e852ed5f6da59053f1c5ddd966ad14" + "commit": "c0e3776e806c2c9d153b4b7bd8d35b153cc68361" } } \ No newline at end of file From 9b4eb0bc0f179b4222e3594f17dbf8aa49574acb Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 11 May 2026 20:18:16 +0530 Subject: [PATCH 816/864] chore: update linux for linux install script --- docs/tauri/update-latest-experimental-build.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index 241acedc..c1c67770 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -29,7 +29,7 @@ }, "linux-x86_64": { "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIG1pbmlzaWduIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1LT0Rla1BIK1l2akRaclI3TFhGMHZYTEVSbWxmSGt1UFRCeGRPY1BjVkJ3Nk9DMlgvYjZWSXlWSVhjVGR2S1dYa2RsYVF2SnZLY2lra2lObXZ3cWdRPQp0cnVzdGVkIGNvbW1lbnQ6IDE3Njk5Mzc4MDYJZmlsZTpwaG9lbml4LWNvZGUtZXhwZXJpbWVudGFsLWJ1aWxkXzUuMC41LkFwcEltYWdlCjhVR3BVVkFSV010dXZjZkExeDFnOTcrbjRWMW4wVlhmOFYzbmhWMGxUd1VaR0lhc2tmMTRpNTRHYzkyeVNNNnAydG9YSkZvQTJ1U3F1RU96akVsaEN3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/dev-app-v5.1.1/phoenix-code-experimental-build_5.0.5.AppImage" + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.3/phoenix-code_5.1.3.AppImage" } } -} \ No newline at end of file +} From 83b0363025b30efd227b4ef008883cda3708d10f Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Tue, 12 May 2026 15:20:23 +0530 Subject: [PATCH 817/864] feat: migrate Linux installer to AppImage with Electron build Replace the GLIBC-versioned tar.gz + bundled GTK/WebKit2GTK installer with a single AppImage flow driven by the Tauri-format update JSON. Probe-driven dependency install: - After download, probe the AppImage with --no-sandbox --version. If it exits cleanly, system libraries are sufficient and apt/dnf/pacman is skipped entirely. - gnome-keyring daemon presence checked independently (binary check; --version doesn't exercise keytar). - AppArmor profile presence checked independently (Ubuntu 24.04+ / Debian 13+ where unprivileged user namespaces are restricted). - Each probe gates its own install step, so sudo is only requested for pieces actually missing. Cross-distro robustness: - apt-cache probe picks libfuse2 (Ubuntu 20.04-22.04, Debian 11-12, Mint 20-21, Neon 22) vs libfuse2t64 (Noble+, Trixie+, Kali, Mint 22+). - KDE sessions skip gnome-keyring to avoid the kwallet/Secret Service D-Bus race. - RHEL 10's missing libXScrnSaver is intentionally not requested (Wayland-only; Electron no-ops gracefully). - Arch gets libxss + libnotify explicitly (not pulled by gtk3). Wrapper script (~/.local/bin/phcode) handles runtime failure modes: - Falls back to --appimage-extract-and-run on FUSE errors. - Falls back to --no-sandbox on userns/AppArmor errors. Other UX improvements: - SIGINT/SIGTERM trap so Ctrl+C cleans up the tmpdir and exits 130. - apt-get install uses --force-confdef/--force-confold + DEBIAN_FRONTEND so an unrelated pending upgrade can't trigger config-file prompts. - Replaced the `yes | sudo apt install` pipeline that silently aborted the script under set -o pipefail when yes died of SIGPIPE. - AppArmor profile preserved across reinstall and --upgrade (only removed by explicit --uninstall) so routine version bumps don't need sudo just to recreate the same profile content. - Post-install hint when the keyring is locked (autologin sessions) explaining the one-time unlock prompt users will see. Removed dead code: check_os_version, download_and_install_gtk, create_launch_script_with_gtk, the GLIBC-version search loop in downloadAndInstall. --- docs/linux/installer.sh | 1205 ++++++++++++++------------------------- 1 file changed, 433 insertions(+), 772 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 87f8b54e..417efa43 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,25 +1,36 @@ #!/bin/bash -set -euo pipefail # Exit immediately if a command exits with a non-zero status. -# Define common variables -DESKTOP_DIR=$HOME/.local/share/applications # Directory for desktop entries -GITHUB_REPO="phcode-dev/phoenix-desktop" -API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" +set -euo pipefail + +# Phoenix Code Linux installer. +# +# Downloads the latest Phoenix Code AppImage from the update JSON, then probes +# the downloaded AppImage with `--version` (early-exit handler at +# src-electron/main.js:23-26). If the probe succeeds, no apt/dnf/pacman install +# is attempted — the system already has every shared library Phoenix Code +# needs at startup, regardless of which package name provides it. +# +# Two things are checked independently of the --version probe: +# - gnome-keyring daemon presence (libsecret needs the daemon for keytar +# credential storage; --version exits before keytar is required). +# - AppArmor unprivileged-userns profile on Ubuntu 24.04+ / Debian 13+ +# (required for Chromium's sandbox; --version exits before the zygote). +# +# Sudo is only requested if at least one of the three checks fails, and only +# the missing piece gets installed. Also wires up a desktop entry + `phcode` +# wrapper script that handles AppImage launch fallbacks. + +DESKTOP_DIR=$HOME/.local/share/applications +UPDATE_JSON_URL="https://updates.phcode.io/tauri/update-latest-experimental-build.json" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" -GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/gtk.tar.xz" -WEBKIT2GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/webkit2gtk-4.0.tar.xz" INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" DESKTOP_ENTRY_NAME="PhoenixCode.desktop" DESKTOP_APP_NAME="Phoenix Code" DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" -SCRIPT_NAME="phcode" # Name of the script to invoke the binary +SCRIPT_NAME="phcode" BINARY_NAME="phoenix-code" -# STARTUP_WM_CLASS is set to the binary name and used as the application's class name in the desktop file. -# This class name helps the desktop environment manage application windows. If native libraries are missing -# and the application needs to be launched via a script instead of directly, this variable is updated -# accordingly before the desktop file is created. -STARTUP_WM_CLASS=$BINARY_NAME - +APPIMAGE_NAME="phoenix-code.AppImage" +APPARMOR_PROFILE_PATH="/etc/apparmor.d/phoenix-code" declare -a MIME_TYPES=( "text/html" @@ -48,460 +59,368 @@ declare -a MIME_TYPES=( "text/cjs" ) - -# Define color variables for easy reference GREEN="\e[32m" YELLOW="\e[33m" RED="\e[31m" RESET="\e[0m" -# Cleanup Function -# -# Purpose: -# The cleanup function is designed to ensure that the script cleans up any temporary -# resources it used during its execution. Specifically, it removes the temporary directory -# created at the beginning of the script, along with all its contents. This is crucial for -# maintaining a clean file system and avoiding the accumulation of unused files. -# -# Behavior: -# - The function targets a temporary directory specified by the `$TMP_DIR` variable. -# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. -# This includes any temporary files, downloaded assets, or other data generated during the script's execution. -# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes -# automatically when the script exits, regardless of the exit point. This includes normal completion, -# errors, or manual termination via signals like SIGINT (Ctrl+C). -# -# Considerations: -# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. -# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. -# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` -# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. -# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within -# `$TMP_DIR` is expendable and safe to delete. -# -# Usage: -# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` -# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` -# is correctly set to the temporary directory path before invoking the function. -# cleanup() { - rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. + rm -rf "$TMP_DIR" +} +# Surface user interrupts (Ctrl+C / kill) with a clear message and exit 130, +# while still running cleanup. Without this, dpkg unpacks and sudo prompts can +# make the script look unresponsive to SIGINT for a beat. +on_interrupt() { + echo + echo -e "${RED}Interrupted by user. Cleaning up...${RESET}" + cleanup + exit 130 } +trap cleanup EXIT +trap on_interrupt INT TERM -trap cleanup EXIT # Register the cleanup function to be called on script exit. +TMP_DIR=$(mktemp -d) +configure_wget_options() { + local wget_version + wget_version=$(wget --version | head -n1 | awk '{print $3}') + local major_version + major_version=$(echo "$wget_version" | cut -d. -f1) -TMP_DIR=$(mktemp -d) + if [[ "$major_version" -ge 2 ]]; then + echo "-c --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" + else + echo "-c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO" + fi +} -# Check OS Version Function -# -# Purpose: -# This function checks if the current operating system is Ubuntu 24.04, Linux Mint 22, or Kali Linux 2024.2 or newer. -# It reads the /etc/os-release file, which contains identification data for the operating system. -# -# Behavior: -# 1. The function first checks if the /etc/os-release file exists. -# 2. If the file exists, it sources the file to load the OS identification variables. -# 3. It then checks if: -# - The ID variable is set to "ubuntu" and the VERSION_ID variable is "24.04", -# - The ID variable is "linuxmint" and the VERSION_ID is "22", -# - The ID variable is "kali" and the VERSION_ID is "2024.2" or newer. -# 4. If any of these conditions are met, the function returns 0 (indicating success). -# 5. If none of these conditions are met, the function returns 1 (indicating failure). -# -# Usage: -# This function can be called to determine if special handling is needed for these specific versions of -# Ubuntu, Linux Mint, or Kali Linux, such as installing additional libraries or making compatibility adjustments. -# -# Example: -# if check_os_version; then -# echo "Supported OS version detected." -# else -# echo "Unsupported OS version." -# fi -# -# Notes: -# - This function assumes that the /etc/os-release file follows the standard format for Linux OS -# identification and that the distribution's identifiers are consistent with those specified in the script. - -check_os_version() { - if [ -f /etc/os-release ]; then - . /etc/os-release - # Set VERSION_ID to empty string if not defined (for rolling releases) - VERSION_ID="${VERSION_ID:-}" - # Define supported OS and version combinations - case "$ID:${VERSION_ID%%.*}" in # Extract major version number - ubuntu:24) # Ubuntu 24.x - return 0 - ;; - ubuntu:25) # Ubuntu 25.x - return 0 - ;; - linuxmint:22) # Linux Mint 22.x - return 0 - ;; - neon:24) # KDE Neon 24.x - return 0 - ;; - debian:13) # Debian 13.x (Trixie) - return 0 - ;; - kali:2024|kali:20[2-9][0-9]) # Kali 2024.x or newer - return 0 - ;; - esac +check_architecture() { + local arch + arch=$(uname -m) + if [ "$arch" != "x86_64" ]; then + echo -e "${RED}This installer only supports 64-bit x86 (x86_64). Detected: $arch.${RESET}" + exit 1 fi - return 1 } -# Create Invocation Script Function -# -# Purpose: -# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. -# This script is intended to simplify the execution of Phoenix Code by providing a more accessible -# command interface. The generated script is placed in a user-accessible binary directory, making it -# possible to run Phoenix Code from anywhere in the system without needing to specify the full path -# to the binary. -# -# Parameters: -# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. -# - script_name: The name to be given to the invocation script. This name is used both for the -# script file itself and for the symlink created in the user's binary directory. -# - link_dir: The directory where a symlink to the invocation script will be placed, typically -# a location in the user's PATH, such as ~/.local/bin, for easy access. -# -# Behavior: -# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. -# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a -# command to execute the Phoenix Code binary with any passed arguments ("$@"). -# 3. Sets executable permissions on the newly created script. -# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. -# -# Considerations: -# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' -# does not conflict with existing files in these directories to prevent unintended overwrites. -# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes -# these directories are already created and accessible. -# - The generated script includes a warning comment advising against deletion, as it is -# essential for the proper functioning of Phoenix Code when invoked through this script. -# -# Usage: -# This function is intended to be called during the installation or upgrade process of Phoenix Code, -# after the binary has been placed in its final location. It should not be called arbitrarily, as it -# assumes a specific setup and context established by the installer script. -# +# Runtime-library probe: ask the AppImage to print its version and exit. This +# is handled at src-electron/main.js:23-26, but `require('electron')` runs +# before that handler — which means Chromium initializes its sandbox bits even +# for --version. On Ubuntu 24.04+ / Debian 13+ without our AppArmor profile, +# that init can SIGTRAP. Pass --no-sandbox so the probe ALSO works on systems +# where the AppArmor profile isn't installed yet — this isolates the probe to +# "are the system shared libraries present and loadable?" and decouples it +# from the AppArmor concern (which is handled separately). +# +# The `{ … } 2>/dev/null` wrapper suppresses bash's own "Trace/breakpoint trap +# (core dumped)" report when the subprocess dies on signal — those messages +# look alarming but are harmless: we already detect failure via the exit code. +verify_appimage_launches() { + { "$1" --no-sandbox --version >/dev/null 2>&1; } 2>/dev/null +} + +# Returns 0 if the gnome-keyring secret-service daemon binary is on PATH. +# `--version` can't test this because keytar is only require()d at first use, +# so we need an independent presence check. +gnome_keyring_present() { + command -v gnome-keyring-daemon >/dev/null 2>&1 +} + +# Returns 0 if this system's kernel restricts unprivileged user namespaces +# (Ubuntu 24.04+ / Debian 13+ / Kali rolling default), which blocks Chromium's +# sandbox inside Electron AppImages unless an AppArmor profile grants userns. +apparmor_userns_restricted() { + [ -d /etc/apparmor.d ] || return 1 + command -v apparmor_parser >/dev/null 2>&1 || return 1 + [ "$(sysctl -n kernel.apparmor_restrict_unprivileged_userns 2>/dev/null || echo 0)" = "1" ] +} + +downloadLatestReleaseInfo() { + local release_info_file="$TMP_DIR/latest_release.json" + if [ ! -f "$release_info_file" ]; then + >&2 echo -e "${GREEN}Fetching the latest release information...${RESET}" + wget -qO "$release_info_file" "$UPDATE_JSON_URL" || { + >&2 echo -e "${RED}Failed to fetch release info from $UPDATE_JSON_URL. Check your internet connection.${RESET}" + exit 1 + } + fi + grep -Po '"version"\s*:\s*"\K[^"]+' "$release_info_file" | head -n1 +} + +# Parses the linux-x86_64 download URL out of the update JSON without needing jq. +getLinuxAppImageUrl() { + awk ' + /"linux-x86_64"[[:space:]]*:/ { in_linux=1 } + in_linux && /"url"[[:space:]]*:/ { + if (match($0, /"url"[[:space:]]*:[[:space:]]*"[^"]+"/)) { + s = substr($0, RSTART, RLENGTH) + sub(/^"url"[[:space:]]*:[[:space:]]*"/, "", s) + sub(/"$/, "", s) + print s + exit + } + } + ' "$TMP_DIR/latest_release.json" +} + +# Generates the `phcode` wrapper script. The wrapper runs the AppImage directly, +# falling back to --appimage-extract-and-run on FUSE failure or to --no-sandbox +# on userns/AppArmor failure (Ubuntu 24.04+ / Debian 13+ blocks Chromium's +# unprivileged user namespace sandbox unless our AppArmor profile is loaded). create_invocation_script() { - local binary_path="$1" + local install_dir="$1" local script_name="$2" local link_dir="$3" - echo "Creating an invocation script for the binary..." - # Start of the generated script - echo "#!/bin/bash" > "$binary_path/$script_name.sh" - # Add a warning comment about the script being auto-generated - echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" - echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" - chmod +x "$binary_path/$script_name" - - echo "Copying the invocation script to $link_dir..." - mkdir -p "$link_dir" # Ensure the directory exists - cp "$binary_path/$script_name" "$link_dir/$script_name" + echo "Creating an invocation script for the AppImage..." + cat > "$install_dir/$script_name" <"\$ERR"; then + if grep -qiE 'fuse|libfuse|dlopen' "\$ERR"; then + rm -f "\$ERR" + exec "\$APPIMAGE" --appimage-extract-and-run "\$@" + fi + if grep -qiE 'userns|apparmor|sandbox|setuid|namespace' "\$ERR"; then + rm -f "\$ERR" + exec "\$APPIMAGE" --no-sandbox "\$@" + fi + cat "\$ERR" >&2 + rm -f "\$ERR" + exit 1 +fi +rm -f "\$ERR" +EOF + chmod +x "$install_dir/$script_name" + mkdir -p "$link_dir" + cp "$install_dir/$script_name" "$link_dir/$script_name" echo -e "Invocation script created at: $link_dir/$script_name" } -# Install Dependencies Function -# -# Purpose: -# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. -# This function identifies the user's Linux distribution and installs the appropriate packages -# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and -# Arch Linux distributions. -# -# Behavior: -# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. -# If the command fails, it prompts the user to enter their password for `sudo` access. -# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. -# 3. Based on the identified distribution, executes the appropriate package manager command -# with the required packages. Supported package managers are `apt` for Debian-based systems, -# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. -# 4. Updates the package index (if applicable) and installs the packages. -# -# Considerations: -# - The function requires internet access to fetch package information and install packages. -# - It assumes that the user has `sudo` privileges to install packages system-wide. -# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, -# this function must be updated accordingly. -# - Unsupported distributions will result in an error message and termination of the script, -# as the required dependencies cannot be installed automatically. -# - This function does not handle potential errors from package installation commands. It's -# recommended to monitor the output for any issues that may require manual intervention. -# -# Usage: -# This function is intended to be called during the Phoenix Code installation process, typically -# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites -# are met for a successful Phoenix Code execution. -# -install_dependencies() { - echo "Attempting to install required dependencies..." - # Inform the user that the next steps require administrative access - echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." +# Returns "gnome-keyring" unless the current session is KDE. +# On KDE, kwallet implements the Secret Service interface (KF 5.97+ / ksecretd +# in 2026), and installing gnome-keyring causes a D-Bus activation race for +# org.freedesktop.secrets — see VSCode issue #189672. +gnome_keyring_pkg_if_needed() { + if [[ "${XDG_CURRENT_DESKTOP:-}" =~ KDE ]]; then + echo "" + else + echo "gnome-keyring" + fi +} - # Check if the script can execute sudo commands without interaction - if ! sudo -n true 2>/dev/null; then - echo "Please enter your password to proceed with the installation of dependencies." +# Installs an AppArmor profile that allows the AppImage to use unprivileged +# user namespaces. Required on Ubuntu 24.04+ / Debian 13+ where the kernel knob +# kernel.apparmor_restrict_unprivileged_userns=1 blocks Chromium's sandbox in +# every Electron AppImage. No-op elsewhere, and a no-op if the profile is +# already present (idempotent across re-runs and --upgrade). +install_apparmor_profile_if_needed() { + apparmor_userns_restricted || return 0 + [ -f "$APPARMOR_PROFILE_PATH" ] && return 0 + + sudo tee "$APPARMOR_PROFILE_PATH" >/dev/null <, +include +profile phoenix-code "$INSTALL_DIR/$APPIMAGE_NAME" flags=(unconfined) { + userns, + include if exists +} +EOF + if ! sudo apparmor_parser -r "$APPARMOR_PROFILE_PATH" 2>/dev/null; then + echo -e "${YELLOW}AppArmor profile reload failed; the wrapper will fall back to --no-sandbox if needed.${RESET}" fi +} - # Attempt to identify the Linux distribution - if [ -f /etc/os-release ]; then - . /etc/os-release - DISTRO=$ID +# Picks the libfuse2 package name for whatever Ubuntu/Debian release we're on. +# Ubuntu 24.04 Noble+ / Debian 13 Trixie+ / Kali rolling / Mint 22+ / Neon 24+ +# ship libfuse2t64 (the post-y2038 rename); older releases (Ubuntu 20.04 Focal +# / 22.04 Jammy, Debian 11/12, Mint 20/21, Neon 22) ship the pre-rename +# libfuse2. Both provide the same libfuse.so.2 SONAME, so picking by repo +# availability is correct. +choose_fuse_package_apt() { + if apt-cache show libfuse2t64 >/dev/null 2>&1; then + echo libfuse2t64 else - echo "Unable to identify the operating system." - exit 1 + echo libfuse2 fi +} - # Install dependencies based on the distribution - case "$DISTRO" in - ubuntu|debian|linuxmint|kali) - echo "Detected an Ubuntu/Debian based distribution." - sudo apt update - yes | sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ - gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ - gstreamer1.0-tools +# Per-distro package install. Only called when verify_appimage_launches failed +# OR the keyring daemon is missing — i.e., we've already decided we need sudo. +install_packages_for_distro() { + local distro="$1" keyring="$2" + # RHEL 10 does not ship libXScrnSaver in any default channel — left off the + # dnf list intentionally; Electron's XScreenSaver calls no-op on Wayland. + # libxss + libnotify are listed for Arch because gtk3 does NOT pull them in + # transitively but Electron dlopen's them at runtime. + local -a pkgs=() + case "$distro" in + ubuntu|debian|linuxmint|kali|neon) pkgs=("$(choose_fuse_package_apt)" libsecret-1-0) ;; + fedora|rhel|centos) pkgs=(fuse-libs fuse3-libs libsecret) ;; + arch|manjaro|cachyos) pkgs=(fuse2 libsecret libxss libnotify) ;; + esac + [ -n "$keyring" ] && pkgs+=("$keyring") + + case "$distro" in + ubuntu|debian|linuxmint|kali|neon) + # No `yes |` pipeline: under `set -o pipefail`, `yes` dies of SIGPIPE + # after apt exits and the pipeline returns 141, silently aborting the + # installer. Use apt-get -y, and keep user /etc config files via the + # force-conf* options so an unrelated pending upgrade can't prompt. + echo "Detected an Ubuntu/Debian-based distribution." + sudo apt-get update + # shellcheck disable=SC2068 + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ + -o Dpkg::Options::="--force-confdef" \ + -o Dpkg::Options::="--force-confold" \ + ${pkgs[@]} ;; fedora|rhel|centos) - echo "Detected a Fedora/Red Hat based distribution." - yes | sudo dnf install webkit2gtk3 gtk3 \ - gstreamer1-plugins-base gstreamer1-plugins-good - yes | sudo dnf upgrade webkit2gtk3 gtk3 \ - gstreamer1 gstreamer1-plugins-base gstreamer1-plugins-good + echo "Detected a Fedora/Red Hat-based distribution." + # shellcheck disable=SC2068 + sudo dnf install -y ${pkgs[@]} ;; arch|manjaro|cachyos) - echo "Detected an Arch Linux based distribution." - echo "Updating package database..." + echo "Detected an Arch-based distribution." sudo pacman -Sy - yes | sudo pacman -S webkit2gtk gtk3 libxml2 + # shellcheck disable=SC2068 + sudo pacman -S --noconfirm --needed ${pkgs[@]} ;; + esac +} + +# Decides what (if anything) the user's system is missing for Phoenix Code to +# run, then installs only the missing piece(s). Three independent probes: +# +# 1. System shared libraries — probed by running the downloaded AppImage +# with `--version`. main.js exits immediately on this flag, AFTER libfuse +# mounts the AppImage and AFTER the Electron binary loads its NEEDED libs. +# 2. gnome-keyring daemon — binary-presence check; `--version` doesn't +# exercise keytar so it can't verify libsecret/Secret Service end-to-end. +# 3. AppArmor unprivileged-userns profile — Chromium sandbox prereq on +# Ubuntu 24.04+ / Debian 13+. Independent of the other two. +# +# Sudo is requested ONLY if at least one of the three probes fails, and only +# the failing pieces are installed. +ensure_runtime_dependencies() { + local appimage="$1" + if [ ! -f /etc/os-release ]; then + echo -e "${RED}Unable to identify the operating system (no /etc/os-release).${RESET}" + exit 1 + fi + . /etc/os-release + local distro="${ID:-}" + case "$distro" in + ubuntu|debian|linuxmint|kali|neon|fedora|rhel|centos|arch|manjaro|cachyos) ;; *) - echo "Unsupported distribution. Please manually install the required dependencies." + echo -e "${RED}Unsupported distribution: $distro. Please install libfuse2/fuse2, libsecret, and (on non-KDE) gnome-keyring manually.${RESET}" exit 1 ;; esac -} -download_and_install_gtk() { - # Function: create_launch_script_with_gtk - # - # Purpose: - # This function creates a launch script for the Phoenix Code application that sets the required - # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that - # the Phoenix Code application uses the correct GTK libraries, which are included in the - # application's installation directory. - # - # Parameters: - # - binary_path: The path to the directory containing the Phoenix Code binary. - # - binary_name: The name of the Phoenix Code binary file. - # - # Behavior: - # 1. The function renames the original Phoenix Code binary to append ".real" to its name. - # 2. It then creates a new launch script with the original binary name in the same directory. - # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the - # GTK libraries located in the same directory as the binary. - # 4. The launch script executes the original Phoenix Code binary (now renamed) with any - # arguments passed to the script. - # 5. The function sets the appropriate executable permissions on the launch script. - # - # Usage: - # This function should be called after the Phoenix Code binary and its required GTK libraries - # have been installed. It ensures that the application uses the correct libraries when launched. - # - # Example: - # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" - # - # Notes: - # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within - # the same directory as the Phoenix Code binary. - # - The function requires the mv, chmod, and cat commands to be available in the environment. - # - This piece of code should only be executed if the package manager does not distribute - # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. - - local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.5/" - local GTK_FILE="gtk.tar.xz" - local WEBKIT2GTK_FILE="webkit2gtk-4.0.tar.xz" - - local GTK_URL="${URL_PREFIX}${GTK_FILE}" - local WEBKIT2GTK_URL="${URL_PREFIX}${WEBKIT2GTK_FILE}" - - echo -e "${YELLOW}Downloading GTK from $GTK_URL...${RESET}" - local destination="$TMP_DIR/$BINARY_NAME" - WGET_OPTS=$(configure_wget_options) - - wget $WGET_OPTS "$TMP_DIR/gtk.tar.xz" "$GTK_URL" || { - echo -e "${RED}Failed to download GTK. Please check your internet connection and try again.${RESET}" - exit 1 - } - echo "Extracting GTK..." - tar -xJf "$TMP_DIR/$GTK_FILE" -C "$destination" || { - echo -e "${RED}Failed to extract GTK. The downloaded file might be corrupt.${RESET}" - exit 1 - } + local keyring; keyring=$(gnome_keyring_pkg_if_needed) + + local libs_ok=1 keyring_ok=1 apparmor_ok=1 + verify_appimage_launches "$appimage" || libs_ok=0 + if [ -n "$keyring" ] && ! gnome_keyring_present; then keyring_ok=0; fi + case "$distro" in + ubuntu|debian|linuxmint|kali|neon) + if apparmor_userns_restricted && [ ! -f "$APPARMOR_PROFILE_PATH" ]; then + apparmor_ok=0 + fi + ;; + esac - if [ ! -d "/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0" ]; then - echo -e "${YELLOW}Downloading WebKit2GTK from $WEBKIT2GTK_URL...${RESET}" - wget $WGET_OPTS "$TMP_DIR/$WEBKIT2GTK_FILE" "$WEBKIT2GTK_URL" || { - echo -e "${RED}Failed to download WebKit2GTK. Please check your internet connection and try again.${RESET}" - exit 1 - } - echo "Extracting WebKit2GTK..." - tar -xJf "$TMP_DIR/$WEBKIT2GTK_FILE" -C "$TMP_DIR" || { - echo -e "${RED}Failed to extract WebKit2GTK. The downloaded file might be corrupt.${RESET}" - exit 1 - } + if [ "$libs_ok" = 1 ] && [ "$keyring_ok" = 1 ] && [ "$apparmor_ok" = 1 ]; then + echo -e "${GREEN}All runtime dependencies already present.${RESET}" + return 0 + fi - # Inform the user that the next steps require administrative access - echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." + local need_pkgs=0 + [ "$libs_ok" = 0 ] || [ "$keyring_ok" = 0 ] && need_pkgs=1 + if [ "$need_pkgs" = 1 ] && [ "$apparmor_ok" = 0 ]; then + echo "Installing runtime packages and AppArmor sandbox profile..." + elif [ "$libs_ok" = 0 ]; then + echo "Installing missing runtime libraries..." + elif [ "$keyring_ok" = 0 ]; then + echo "Installing system keychain daemon..." + else + echo "Installing AppArmor sandbox profile (keeps Chromium's sandbox enabled on Ubuntu 24.04+)..." + fi + echo "This step requires administrative access." + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed." + fi - # Check if the script can execute sudo commands without interaction - if ! sudo -n true 2>/dev/null; then - echo "Please enter your password to proceed with the installation of dependencies." + if [ "$need_pkgs" = 1 ]; then + install_packages_for_distro "$distro" "$keyring" + # Re-probe libraries; if still failing, surface a clear warning but don't + # abort — the AppImage may have a runtime-specific issue we can't fix here. + if [ "$libs_ok" = 0 ] && ! verify_appimage_launches "$appimage"; then + echo -e "${YELLOW}WARN: AppImage still fails --version after dep install.${RESET}" fi + fi - echo "Installing WebKit2GTK..." - sudo cp -r "$TMP_DIR/webkit2gtk-4.0" /usr/lib/x86_64-linux-gnu/ || { - echo -e "${RED}Failed to install WebKit2GTK. Please check the permissions and try again.${RESET}" - exit 1 - } - echo -e "${GREEN}WebKit2GTK installed successfully.${RESET}" - else - echo -e "${GREEN}WebKit2GTK already installed.${RESET}" + if [ "$apparmor_ok" = 0 ]; then + install_apparmor_profile_if_needed fi } - -create_launch_script_with_gtk() { - # Function: create_launch_script_with_gtk - # - # Purpose: - # This function creates a launch script for the Phoenix Code application that sets the required - # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that - # the Phoenix Code application uses the correct GTK libraries, which are included in the - # application's installation directory. - # - # Parameters: - # - binary_path: The path to the directory containing the Phoenix Code binary. - # - binary_name: The name of the Phoenix Code binary file. - # - # Behavior: - # 1. The function renames the original Phoenix Code binary to append ".real" to its name. - # 2. It then creates a new launch script with the original binary name in the same directory. - # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the - # GTK libraries located in the same directory as the binary. - # 4. The launch script executes the original Phoenix Code binary (now renamed) with any - # arguments passed to the script. - # 5. The function sets the appropriate executable permissions on the launch script. - # - # Usage: - # This function should be called after the Phoenix Code binary and its required GTK libraries - # have been installed. It ensures that the application uses the correct libraries when launched. - # - # Example: - # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" - # - # Notes: - # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within - # the same directory as the Phoenix Code binary. - # - The function requires the mv, chmod, and cat commands to be available in the environment. - # - This piece of code should only be executed if the package manager does not distribute - # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. - - local binary_path="$1" - local binary_name="$BINARY_NAME" - local original_bin=$binary_name.app - local realBin="$binary_path/$original_bin" - mv "$binary_path/$binary_name" "$realBin" - echo "Creating a launch script for Phoenix Code with GTK libraries..." - cat > "$binary_path/$binary_name" </dev/null 2>&1 || return 0 + local locked + locked=$(busctl --user --no-pager call org.freedesktop.secrets \ + /org/freedesktop/secrets/collection/login \ + org.freedesktop.DBus.Properties Get \ + ss org.freedesktop.Secret.Collection Locked 2>/dev/null \ + | awk '/^b /{print $NF}') + [ "$locked" = "true" ] || return 0 - if "$TMP_DIR/phoenix-code/phoenix-code" --runVerify; then - echo "Application launch verification successful after installing dependencies." - return 0 - else - echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." - return 1 + echo + echo -e "${YELLOW}Note: your system keychain is currently locked.${RESET}" + echo -e "${YELLOW}The first time Phoenix Code stores or reads a credential, gnome-keyring${RESET}" + echo -e "${YELLOW}will ask once for your login password to unlock it. This is a one-time${RESET}" + echo -e "${YELLOW}per-session Linux behavior — not a Phoenix Code prompt.${RESET}" + if autologin_detected; then + echo -e "${YELLOW}(Autologin is enabled on this machine, which is why PAM did not${RESET}" + echo -e "${YELLOW} auto-unlock the keyring at session start.)${RESET}" fi } -# Set Phoenix Code as the default application for specified MIME types + set_default_application() { - local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file + local desktop_file="$DESKTOP_ENTRY_NAME" - # Dynamically detect qtpaths if KDE is running and qtpaths is not in PATH if [ "${KDE_SESSION_VERSION:-0}" -gt 0 ] && ! command -v qtpaths &> /dev/null; then - # Common locations where qtpaths might be installed local qtpaths_locations=( "/usr/lib/qt6/bin" "/usr/lib/qt5/bin" @@ -510,7 +429,6 @@ set_default_application() { "/opt/qt6/bin" "/opt/qt5/bin" ) - for qtpath_dir in "${qtpaths_locations[@]}"; do if [ -x "$qtpath_dir/qtpaths" ] || [ -x "$qtpath_dir/qtpaths6" ]; then export PATH="$qtpath_dir:$PATH" @@ -520,82 +438,36 @@ set_default_application() { fi for mime_type in "${MIME_TYPES[@]}"; do - # Skip setting default application for text/html - if [ "$mime_type" = "text/html" ]; then - continue # Skip to the next iteration - fi - - xdg-mime default "$desktop_file" "$mime_type" + if [ "$mime_type" = "text/html" ]; then + continue + fi + xdg-mime default "$desktop_file" "$mime_type" done echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" } -# Copy Files to Destination Function -# -# Purpose: -# This function is responsible for setting up the final installation directory for Phoenix Code, -# moving the necessary files into place, creating the invocation script, and setting up the desktop -# entry for the application. It ensures that all components of Phoenix Code are correctly installed -# and configured in the user's environment. -# -# Behavior: -# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files -# will reside. -# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. -# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from -# the temporary directory (`$TMP_DIR`) to the installation directory. -# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. -# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. -# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. -# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and -# launchers, and places this file in the desktop entry directory. -# 8. Updates the system's desktop database to ensure the new application entry is recognized and available -# in application menus and launchers. This step might involve commands like `update-desktop-database` -# or `kbuildsycoca5`, depending on the desktop environment. -# -# Considerations: -# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and -# that this directory is correctly set. -# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and -# accessible. If these variables are unset or incorrect, the function may not perform as intended. -# - Administrative privileges may be required for certain operations, such as updating the desktop database -# or setting permissions, depending on the system's configuration. -# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function -# does perform significant file system operations that could potentially conflict with existing user data -# or system settings. -# -# Usage: -# This function is intended to be called as part of the Phoenix Code installation process, after the -# application's binary and other necessary files have been prepared in a temporary location. It finalizes -# the installation by placing all components in their appropriate locations within the user's system. -# -copyFilesToDestination(){ +copyFilesToDestination() { echo "Setting up the installation directory at $INSTALL_DIR..." mkdir -p "$INSTALL_DIR" mkdir -p "$DESKTOP_DIR" - echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" - echo "Moving the necessary files to the installation directory..." - echo -e "Phoenix Code files moved to: $INSTALL_DIR" - mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { - echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" + mv "$TMP_DIR/$APPIMAGE_NAME" "$INSTALL_DIR/$APPIMAGE_NAME" || { + echo -e "${RED}Failed to move the AppImage to the installation directory. Please check the permissions and try again.${RESET}" exit 1 } - # Move the icon to the installation directory mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" - echo "Setting the correct permissions for the executable..." - chmod +x "$INSTALL_DIR/phoenix-code" || { - echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" + chmod +x "$INSTALL_DIR/$APPIMAGE_NAME" || { + echo -e "${RED}Failed to set executable permissions on the AppImage.${RESET}" exit 1 } - echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" + echo -e "AppImage installed at: $INSTALL_DIR/$APPIMAGE_NAME" - mkdir -p "$LINK_DIR" # Ensure the directory exists - # Call the function to create and copy the invocation script + mkdir -p "$LINK_DIR" create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" - # Convert MIME types array to semicolon-separated string for the desktop entry - MIME_TYPES_STRING=$(IFS=";"; echo "${MIME_TYPES[*]}") + + local mime_types_string + mime_types_string=$(IFS=";"; echo "${MIME_TYPES[*]}") echo "Creating desktop entry..." cat > "$DESKTOP_ENTRY" < /dev/null; then - update-desktop-database "$DESKTOP_DIR" - echo -e "Desktop database updated in: $DESKTOP_DIR" + update-desktop-database "$DESKTOP_DIR" fi - - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if [ "${XDG_CURRENT_DESKTOP:-}" = "KDE" ]; then if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 + kbuildsycoca5 fi fi - - if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then + if [[ "${XDG_CURRENT_DESKTOP:-}" =~ LXQt ]]; then if command -v xdg-desktop-menu &> /dev/null; then - xdg-desktop-menu forceupdate - echo -e "${YELLOW}Please log out and log back in to see Phoenix Code in the panel.${RESET}" + xdg-desktop-menu forceupdate + echo -e "${YELLOW}Please log out and log back in to see Phoenix Code in the panel.${RESET}" else - echo -e "${RED}Failed to update LXQt menu. Please log out and log back in to see Phoenix Code in the panel.${RESET}" + echo -e "${RED}Failed to update LXQt menu. Please log out and log back in to see Phoenix Code in the panel.${RESET}" fi fi - # Set Phoenix Code as the default application for the MIME types + set_default_application echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" - -} - -downloadLatestReleaseInfo() { - local release_info_file="$TMP_DIR/latest_release.json" - - if [ -f "$release_info_file" ]; then - # Only extract and echo the version number, without any additional messages - grep -Po '"tag_name":\s*"prod-app-v\K[\d.]+(?=")' "$release_info_file" - return - fi - - # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly - >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" - wget -qO "$release_info_file" "$API_URL" || { - >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" - exit 1 - } - - # Only extract and echo the version number after successful download - grep -Po '"tag_name":\s*"prod-app-v\K[\d.]+(?=")' "$release_info_file" + print_keyring_hint_if_locked } -# Function to check if the architecture is 64-bit x86 -check_architecture() { - ARCHITECTURE=$(uname -m) - if [ "$ARCHITECTURE" != "x86_64" ]; then - local latestFileUrl - latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") - WGET_OPTS=$(configure_wget_options) - wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { - echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" - } - echo -e "${RED}This script can only be run on 64-bit x86 architecture.${RESET}" - exit 1 - fi -} -# Download Latest Release Information Function -# -# Purpose: -# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function -# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to -# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. -# -# Behavior: -# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary -# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already -# been fetched and proceeds to extract the version number from this file without re-downloading. -# 2. If the release information file does not exist, the function uses `wget` to download the JSON data -# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint -# of the Phoenix Code GitHub repository. -# 3. The JSON data is saved to `latest_release.json` in the temporary directory. -# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular -# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version -# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number -# portion. -# 5. Echoes the extracted version number for use by the calling context. -# -# Considerations: -# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available -# in the execution environment. -# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code -# repository for this function to work as intended. -# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, -# the `grep` pattern used to extract the version number may need to be updated. -# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an -# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the -# latest release information. -# - The function does not perform error handling for the `wget` command. If the download fails, the script may -# exit or behave unexpectedly depending on the `set -e` setting. -# -# Usage: -# This function is intended to be called during the installation or upgrade process to determine the latest -# version of Phoenix Code. The extracted version number can be used to compare with the currently installed -# version and decide whether an upgrade is necessary. -# -downloadAndInstall(){ +downloadAndInstall() { echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null check_architecture - CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') - echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" - - BEST_MATCH_URL="" - BEST_MATCH_VERSION=0 - echo "Searching for a compatible binary..." - - while read -r BINARY_URL; do - BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') - if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then - BEST_MATCH_URL="$BINARY_URL" - BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" - echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" - fi - done < <(grep -oP '"browser_download_url"\s*:\s*"\K[^"]*_linux_bin-GLIBC-[\d\.]+\.tar\.gz(?=")' "$TMP_DIR/latest_release.json") - if [ -z "$BEST_MATCH_URL" ]; then - echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" + local appimage_url + appimage_url=$(getLinuxAppImageUrl) + if [ -z "$appimage_url" ]; then + echo -e "${RED}Could not find a linux-x86_64 AppImage URL in the release info.${RESET}" exit 1 fi - echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" - # Set options based on wget version - WGET_OPTS=$(configure_wget_options) - - wget $WGET_OPTS "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { - echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" + echo -e "${YELLOW}Downloading the AppImage from $appimage_url...${RESET}" + local wget_opts + wget_opts=$(configure_wget_options) + # shellcheck disable=SC2086 + wget $wget_opts "$TMP_DIR/$APPIMAGE_NAME" "$appimage_url" || { + echo -e "${RED}Failed to download the AppImage. Please check your internet connection and try again.${RESET}" exit 1 } - # Download the icon - echo -e "Downloading the icon..." - wget $WGET_OPTS "$TMP_DIR/icon.png" "$ICON_URL" || { - echo -e "${RED}Failed to download the icon${RESET}" - exit 1 - } - echo "Extracting the binary to $TMP_DIR..." - tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { - echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" + echo "Downloading the icon..." + # shellcheck disable=SC2086 + wget $wget_opts "$TMP_DIR/icon.png" "$ICON_URL" || { + echo -e "${RED}Failed to download the icon.${RESET}" exit 1 } - # Verify binary execution and install dependencies if necessary - if ! verify_and_install_dependencies; then - echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" - exit 1 - fi + chmod +x "$TMP_DIR/$APPIMAGE_NAME" + + ensure_runtime_dependencies "$TMP_DIR/$APPIMAGE_NAME" } -# Function to check wget version and configure options -configure_wget_options() { - local wget_version=$(wget --version | head -n1 | awk '{print $3}') - local major_version=$(echo "$wget_version" | cut -d. -f1) - if [[ "$major_version" -ge 2 ]]; then - echo "-c --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" - else - echo "-c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO" - fi +# Temporary cleanup for files from older installer versions. +uninstallBetaAppImage() { + rm -f "$LINK_DIR"/phoenix_icon.png } -# Install Function -# -# Purpose: -# Facilitates the entire installation process of Phoenix Code on the user's system. This includes -# checking for previous installations, downloading and installing the latest version, setting up -# necessary directories, and ensuring that all dependencies are met. It also handles user prompts -# for repair or reinstallation options if Phoenix Code is already installed. -# -# Behavior: -# 1. Checks if Phoenix Code is already installed by looking for specific files or directories -# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main -# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). -# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and -# then reinstalls the application, ensuring the user ends up with the latest version. -# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest -# release and install it. This step involves downloading the binary, setting permissions, and -# moving files to their correct locations. -# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, -# create an invocation script, and perform other necessary post-installation configurations. -# -# Considerations: -# - The function assumes that the user has sufficient permissions to write to the target directories -# and install Phoenix Code. Administrative privileges may be required for certain operations. -# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation -# directory will be replaced. Users should ensure that any custom configurations or data are backed up -# before proceeding. -# - Network connectivity is required to download the latest version of Phoenix Code from the repository. -# - The function does not explicitly handle all potential error scenarios, such as download failures or -# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. -# -# Usage: -# This function is intended to be invoked when the script is run without specific options (e.g., not an -# uninstall or upgrade). It can be directly called from the command line when the user wishes to install -# Phoenix Code, or it may be triggered by default when the script is executed without arguments. -# + install() { - # Check if the application is already installed if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" - # Checking if the shell has a controlling terminal if its non interactive reinstall phoenix with latest version if [ ! -t 0 ]; then echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" - uninstall + uninstall keep_apparmor downloadAndInstall copyFilesToDestination else - # Simplified prompt for reinstall without detailed explanation read -r -p "Would you like to reinstall it? (y/N): " response case "$response" in [Yy]* ) - echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" - uninstall - downloadAndInstall - copyFilesToDestination - ;; + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + uninstall keep_apparmor + downloadAndInstall + copyFilesToDestination + ;; * ) - echo -e "${RED}Reinstall aborted by the user.${RESET}" - exit 0 - ;; + echo -e "${RED}Reinstall aborted by the user.${RESET}" + exit 0 + ;; esac fi else @@ -844,115 +576,46 @@ install() { fi } -# Temporary code to clean up earlier beta installations -function uninstallBetaAppImage() { - rm -f "$LINK_DIR"/phoenix_icon.png -} -# Upgrade Function -# -# Purpose: -# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated -# to the latest version available. This function checks the currently installed version against -# the latest version available in the GitHub repository. If a newer version is found, it proceeds -# to download and install the update, effectively replacing the old version with the new one. -# -# Behavior: -# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation -# directory and the invocation script. If not found, it exits with an error message indicating that -# Phoenix Code must be installed before it can be upgraded. -# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version -# check command (e.g., `phoenix-code --version`) and captures the output. -# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` -# function, which retrieves the version number of the latest release. -# 4. Compares the currently installed version with the latest version. If the installed version is older, -# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and -# installation of the new version. -# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. -# -# Considerations: -# - The function relies on the correct implementation of version checking in the Phoenix Code binary. -# The binary must support a command-line option to output its version, and the output format must be -# consistent for correct parsing and comparison. -# - Network connectivity is required to fetch the latest release information from the GitHub repository. -# The upgrade process will fail if the script cannot connect to GitHub. -# - The user must have sufficient permissions to overwrite the existing installation files and to -# execute network requests (e.g., downloading the latest release). -# - The upgrade process replaces the existing installation files. Users should ensure that any -# necessary backups or custom configurations are saved before proceeding with the upgrade. -# -# Usage: -# This function is intended to be called when the user explicitly wants to upgrade their installation -# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the -# script, as defined in the script's main case statement handling command-line arguments. -# upgrade() { echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" - # Ensure Phoenix Code is installed if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" exit 1 fi - # Get the current installed version - CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) - echo "Current installed version: $CURRENT_VERSION" - LATEST_VERSION=$(downloadLatestReleaseInfo) - # Now LATEST_VERSION should only contain the version number without extra messages - echo "Latest available version: $LATEST_VERSION" + local current_version + current_version=$("$INSTALL_DIR/$APPIMAGE_NAME" --version 2>/dev/null || true) + echo "Current installed version: ${current_version:-unknown}" - # Compare versions and upgrade if the latest version is greater - if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then + local latest_version + latest_version=$(downloadLatestReleaseInfo) + echo "Latest available version: $latest_version" + + if [ -n "$latest_version" ] && [ "$(printf '%s\n' "$latest_version" "$current_version" | sort -V | tail -n1)" = "$latest_version" ] && [ "$latest_version" != "$current_version" ]; then echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" downloadAndInstall - uninstall + uninstall keep_apparmor copyFilesToDestination echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" else echo "Your Phoenix Code installation is up-to-date." fi - } -# Uninstall Function -# -# Purpose: -# Handles the removal of Phoenix Code from the user's system. This function is responsible for -# cleaning up all files, directories, and links created during the installation process, effectively -# reverting any changes made by the installer script. It ensures that Phoenix Code and its components -# are uninstalled cleanly, leaving no residual files or configurations. -# -# Behavior: -# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). -# This step prevents the Phoenix Code command from being accessible after uninstallation. -# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus -# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. -# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. -# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. -# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including -# the main binary, configuration files, and any other related files placed during installation. -# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. -# -# Considerations: -# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately -# reflect the locations used during the installation. If these variables are incorrect, the uninstallation -# process may not remove all components. -# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed -# in system-wide directories. -# - Users should be advised to back up any important data or configurations related to Phoenix Code before -# initiating the uninstallation process, as this function will remove all associated files without recovery options. -# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot -# be reversed through this script. -# -# Usage: -# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. -# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement -# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this -# function is executed to prevent accidental data loss. -# + uninstall() { + # mode: + # "full" (default) — remove every artifact, including the + # system-level AppArmor profile under /etc/apparmor.d/. + # Used by the --uninstall CLI entry-point. + # "keep_apparmor" — remove user-scope artifacts only; leave the AppArmor + # profile in place. Used by the internal reinstall and + # --upgrade flows so a routine version bump doesn't need + # sudo just to recreate the same profile content. + local mode="${1:-full}" echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" uninstallBetaAppImage - # Remove the invocation script from ~/.local/bin + if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" rm "$LINK_DIR/$SCRIPT_NAME" @@ -960,40 +623,41 @@ uninstall() { echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" fi - # Delete the desktop entry if [ -f "$DESKTOP_ENTRY" ]; then echo -e "${YELLOW}Removing desktop entry...${RESET}" rm "$DESKTOP_ENTRY" - - # Update the desktop database for GNOME, Unity, XFCE, etc. - echo -e "${YELLOW}Updating desktop database...${RESET}" if command -v update-desktop-database &> /dev/null; then - update-desktop-database "$DESKTOP_DIR" + update-desktop-database "$DESKTOP_DIR" fi - - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 - fi + if [ "${XDG_CURRENT_DESKTOP:-}" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi fi - - if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then + if [[ "${XDG_CURRENT_DESKTOP:-}" =~ LXQt ]]; then if command -v xdg-desktop-menu &> /dev/null; then - xdg-desktop-menu forceupdate + xdg-desktop-menu forceupdate fi fi else - echo -e "${RED}Desktop entry not found. Skipping...${RESET}" + echo -e "${RED}Desktop entry not found. Skipping...${RESET}" fi - # Remove the installation directory and its contents if [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" rm -rf "$INSTALL_DIR" else echo -e "${RED}Installation directory not found. Skipping...${RESET}" fi + + if [ "$mode" != "keep_apparmor" ] && [ -f "$APPARMOR_PROFILE_PATH" ]; then + echo -e "${YELLOW}Removing AppArmor profile...${RESET}" + sudo rm -f "$APPARMOR_PROFILE_PATH" || true + if command -v apparmor_parser >/dev/null 2>&1; then + sudo apparmor_parser -R "$APPARMOR_PROFILE_PATH" 2>/dev/null || true + fi + fi + echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" } @@ -1009,7 +673,6 @@ show_help() { echo "Without any options, the script will install Phoenix Code." } -# Check for GUI session by looking for DISPLAY or WAYLAND_DISPLAY variables if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then echo "This script should only be run from terminals in GUI sessions." exit 1 @@ -1017,22 +680,20 @@ fi case "${1-}" in -h|--help) - show_help # Function to show help + show_help ;; --uninstall) - uninstall # Function to uninstall + uninstall ;; --upgrade) - upgrade # Function to upgrade + upgrade ;; "") - # This case handles when $1 is unset (acts as a default action) - install # Function to install + install ;; *) - # This case handles unexpected arguments echo "Invalid option: $1" >&2 - show_help # Assuming you have a function to show usage information + show_help exit 1 ;; esac From 188d8e4b9c626b99e6f28c644791075e9761a622 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 13 May 2026 00:13:47 +0530 Subject: [PATCH 818/864] refactor: drop AppArmor profile install, tighten wrapper fallback regex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phoenix Code's Electron renderer is already locked down (contextIsolation + nodeIntegration:false + local-only phtauri:// protocol). The kernel-side AppArmor profile only adds defense-in-depth against renderer V8 RCE → raw-syscall escape, which is a narrow class. The IPC-bridge attack surface (electronFSAPI, keytar via electronAPI) is not gated by the kernel sandbox either way. Removing the profile install matches what every other Electron AppImage in the wild does (Cursor, Obsidian, Discord, VSCode-AppImage), removes ~70 LOC, and stops requesting sudo to write under /etc/. Wrapper-script fallbacks stay (verified load-bearing by reading Chromium and AppImage type-2 runtime source): - Sandbox: Chromium LOG(FATAL)s when AppArmor blocks the userns clone on Ubuntu 24.04+ / Debian 13+; it does NOT auto-fall-back. Our --no-sandbox re-exec is the actual recovery and now the only one. - FUSE: the AppImage runtime self-recovers only when libfuse.so.2 can't dlopen; when /dev/fuse is missing or fusermount is denied (Docker/Podman containers, older WSL2, SELinux-restricted kernels), it prints "Cannot mount AppImage, please check your FUSE setup" and exits. Our --appimage-extract-and-run re-exec is the recovery. Wrapper regex tightened: - Drop `dlopen` from the FUSE branch (too broad, could match unrelated library-load failures and route them into a useless retry). - Add `Check failed` to the sandbox branch to catch Chromium's actual NamespaceSandbox / SUID-helper FATAL phrasing. uninstall() reverted to a single behavior (the keep_apparmor mode arg is no longer needed since there's no profile to preserve). --- docs/linux/installer.sh | 135 ++++++++++------------------------------ 1 file changed, 32 insertions(+), 103 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 417efa43..8c442ddc 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -9,15 +9,20 @@ set -euo pipefail # is attempted — the system already has every shared library Phoenix Code # needs at startup, regardless of which package name provides it. # -# Two things are checked independently of the --version probe: -# - gnome-keyring daemon presence (libsecret needs the daemon for keytar -# credential storage; --version exits before keytar is required). -# - AppArmor unprivileged-userns profile on Ubuntu 24.04+ / Debian 13+ -# (required for Chromium's sandbox; --version exits before the zygote). +# Beyond the --version probe, the installer also checks for the gnome-keyring +# daemon binary — libsecret needs the daemon for keytar credential storage, +# and --version exits before keytar is require()d. Sudo is only requested if +# libs or the keyring daemon are actually missing. # -# Sudo is only requested if at least one of the three checks fails, and only -# the missing piece gets installed. Also wires up a desktop entry + `phcode` -# wrapper script that handles AppImage launch fallbacks. +# On Ubuntu 24.04+ / Debian 13+, Chromium's unprivileged userns sandbox can +# be blocked by the kernel sysctl. The app still launches because the wrapper +# script falls back to --no-sandbox; we no longer install an AppArmor profile +# to keep the kernel sandbox enabled (the renderer-RCE-to-syscall threat the +# kernel sandbox guards against is narrow, and Phoenix Code's actual attack +# surface flows through the IPC bridge which the kernel sandbox doesn't gate). +# +# Also wires up a desktop entry + `phcode` wrapper script that handles +# AppImage launch fallbacks. DESKTOP_DIR=$HOME/.local/share/applications UPDATE_JSON_URL="https://updates.phcode.io/tauri/update-latest-experimental-build.json" @@ -30,7 +35,6 @@ DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" SCRIPT_NAME="phcode" BINARY_NAME="phoenix-code" APPIMAGE_NAME="phoenix-code.AppImage" -APPARMOR_PROFILE_PATH="/etc/apparmor.d/phoenix-code" declare -a MIME_TYPES=( "text/html" @@ -106,11 +110,10 @@ check_architecture() { # Runtime-library probe: ask the AppImage to print its version and exit. This # is handled at src-electron/main.js:23-26, but `require('electron')` runs # before that handler — which means Chromium initializes its sandbox bits even -# for --version. On Ubuntu 24.04+ / Debian 13+ without our AppArmor profile, -# that init can SIGTRAP. Pass --no-sandbox so the probe ALSO works on systems -# where the AppArmor profile isn't installed yet — this isolates the probe to -# "are the system shared libraries present and loadable?" and decouples it -# from the AppArmor concern (which is handled separately). +# for --version. On Ubuntu 24.04+ / Debian 13+ where unprivileged user +# namespaces are restricted, that init can SIGTRAP. Pass --no-sandbox so the +# probe isolates to "are the system shared libraries present and loadable?" +# regardless of the kernel's userns policy. # # The `{ … } 2>/dev/null` wrapper suppresses bash's own "Trace/breakpoint trap # (core dumped)" report when the subprocess dies on signal — those messages @@ -126,15 +129,6 @@ gnome_keyring_present() { command -v gnome-keyring-daemon >/dev/null 2>&1 } -# Returns 0 if this system's kernel restricts unprivileged user namespaces -# (Ubuntu 24.04+ / Debian 13+ / Kali rolling default), which blocks Chromium's -# sandbox inside Electron AppImages unless an AppArmor profile grants userns. -apparmor_userns_restricted() { - [ -d /etc/apparmor.d ] || return 1 - command -v apparmor_parser >/dev/null 2>&1 || return 1 - [ "$(sysctl -n kernel.apparmor_restrict_unprivileged_userns 2>/dev/null || echo 0)" = "1" ] -} - downloadLatestReleaseInfo() { local release_info_file="$TMP_DIR/latest_release.json" if [ ! -f "$release_info_file" ]; then @@ -179,11 +173,11 @@ create_invocation_script() { APPIMAGE="$install_dir/$APPIMAGE_NAME" ERR=\$(mktemp) if ! "\$APPIMAGE" "\$@" 2>"\$ERR"; then - if grep -qiE 'fuse|libfuse|dlopen' "\$ERR"; then + if grep -qiE 'fuse|libfuse|fusermount|/dev/fuse' "\$ERR"; then rm -f "\$ERR" exec "\$APPIMAGE" --appimage-extract-and-run "\$@" fi - if grep -qiE 'userns|apparmor|sandbox|setuid|namespace' "\$ERR"; then + if grep -qiE 'userns|apparmor|sandbox|setuid|namespace|Check failed' "\$ERR"; then rm -f "\$ERR" exec "\$APPIMAGE" --no-sandbox "\$@" fi @@ -212,32 +206,6 @@ gnome_keyring_pkg_if_needed() { fi } -# Installs an AppArmor profile that allows the AppImage to use unprivileged -# user namespaces. Required on Ubuntu 24.04+ / Debian 13+ where the kernel knob -# kernel.apparmor_restrict_unprivileged_userns=1 blocks Chromium's sandbox in -# every Electron AppImage. No-op elsewhere, and a no-op if the profile is -# already present (idempotent across re-runs and --upgrade). -install_apparmor_profile_if_needed() { - apparmor_userns_restricted || return 0 - [ -f "$APPARMOR_PROFILE_PATH" ] && return 0 - - sudo tee "$APPARMOR_PROFILE_PATH" >/dev/null <, -include -profile phoenix-code "$INSTALL_DIR/$APPIMAGE_NAME" flags=(unconfined) { - userns, - include if exists -} -EOF - if ! sudo apparmor_parser -r "$APPARMOR_PROFILE_PATH" 2>/dev/null; then - echo -e "${YELLOW}AppArmor profile reload failed; the wrapper will fall back to --no-sandbox if needed.${RESET}" - fi -} - # Picks the libfuse2 package name for whatever Ubuntu/Debian release we're on. # Ubuntu 24.04 Noble+ / Debian 13 Trixie+ / Kali rolling / Mint 22+ / Neon 24+ # ship libfuse2t64 (the post-y2038 rename); older releases (Ubuntu 20.04 Focal @@ -304,11 +272,8 @@ install_packages_for_distro() { # mounts the AppImage and AFTER the Electron binary loads its NEEDED libs. # 2. gnome-keyring daemon — binary-presence check; `--version` doesn't # exercise keytar so it can't verify libsecret/Secret Service end-to-end. -# 3. AppArmor unprivileged-userns profile — Chromium sandbox prereq on -# Ubuntu 24.04+ / Debian 13+. Independent of the other two. # -# Sudo is requested ONLY if at least one of the three probes fails, and only -# the failing pieces are installed. +# Sudo is requested ONLY if at least one of the probes fails. ensure_runtime_dependencies() { local appimage="$1" if [ ! -f /etc/os-release ]; then @@ -326,49 +291,30 @@ ensure_runtime_dependencies() { esac local keyring; keyring=$(gnome_keyring_pkg_if_needed) - local libs_ok=1 keyring_ok=1 apparmor_ok=1 + local libs_ok=1 keyring_ok=1 verify_appimage_launches "$appimage" || libs_ok=0 if [ -n "$keyring" ] && ! gnome_keyring_present; then keyring_ok=0; fi - case "$distro" in - ubuntu|debian|linuxmint|kali|neon) - if apparmor_userns_restricted && [ ! -f "$APPARMOR_PROFILE_PATH" ]; then - apparmor_ok=0 - fi - ;; - esac - if [ "$libs_ok" = 1 ] && [ "$keyring_ok" = 1 ] && [ "$apparmor_ok" = 1 ]; then + if [ "$libs_ok" = 1 ] && [ "$keyring_ok" = 1 ]; then echo -e "${GREEN}All runtime dependencies already present.${RESET}" return 0 fi - local need_pkgs=0 - [ "$libs_ok" = 0 ] || [ "$keyring_ok" = 0 ] && need_pkgs=1 - if [ "$need_pkgs" = 1 ] && [ "$apparmor_ok" = 0 ]; then - echo "Installing runtime packages and AppArmor sandbox profile..." - elif [ "$libs_ok" = 0 ]; then + if [ "$libs_ok" = 0 ]; then echo "Installing missing runtime libraries..." - elif [ "$keyring_ok" = 0 ]; then - echo "Installing system keychain daemon..." else - echo "Installing AppArmor sandbox profile (keeps Chromium's sandbox enabled on Ubuntu 24.04+)..." + echo "Installing system keychain daemon..." fi echo "This step requires administrative access." if ! sudo -n true 2>/dev/null; then echo "Please enter your password to proceed." fi - if [ "$need_pkgs" = 1 ]; then - install_packages_for_distro "$distro" "$keyring" - # Re-probe libraries; if still failing, surface a clear warning but don't - # abort — the AppImage may have a runtime-specific issue we can't fix here. - if [ "$libs_ok" = 0 ] && ! verify_appimage_launches "$appimage"; then - echo -e "${YELLOW}WARN: AppImage still fails --version after dep install.${RESET}" - fi - fi - - if [ "$apparmor_ok" = 0 ]; then - install_apparmor_profile_if_needed + install_packages_for_distro "$distro" "$keyring" + # Re-probe libraries; if still failing, surface a clear warning but don't + # abort — the AppImage may have a runtime-specific issue we can't fix here. + if [ "$libs_ok" = 0 ] && ! verify_appimage_launches "$appimage"; then + echo -e "${YELLOW}WARN: AppImage still fails --version after dep install.${RESET}" fi } @@ -552,7 +498,7 @@ install() { echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" if [ ! -t 0 ]; then echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" - uninstall keep_apparmor + uninstall downloadAndInstall copyFilesToDestination else @@ -560,7 +506,7 @@ install() { case "$response" in [Yy]* ) echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" - uninstall keep_apparmor + uninstall downloadAndInstall copyFilesToDestination ;; @@ -595,7 +541,7 @@ upgrade() { if [ -n "$latest_version" ] && [ "$(printf '%s\n' "$latest_version" "$current_version" | sort -V | tail -n1)" = "$latest_version" ] && [ "$latest_version" != "$current_version" ]; then echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" downloadAndInstall - uninstall keep_apparmor + uninstall copyFilesToDestination echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" else @@ -604,15 +550,6 @@ upgrade() { } uninstall() { - # mode: - # "full" (default) — remove every artifact, including the - # system-level AppArmor profile under /etc/apparmor.d/. - # Used by the --uninstall CLI entry-point. - # "keep_apparmor" — remove user-scope artifacts only; leave the AppArmor - # profile in place. Used by the internal reinstall and - # --upgrade flows so a routine version bump doesn't need - # sudo just to recreate the same profile content. - local mode="${1:-full}" echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" uninstallBetaAppImage @@ -650,14 +587,6 @@ uninstall() { echo -e "${RED}Installation directory not found. Skipping...${RESET}" fi - if [ "$mode" != "keep_apparmor" ] && [ -f "$APPARMOR_PROFILE_PATH" ]; then - echo -e "${YELLOW}Removing AppArmor profile...${RESET}" - sudo rm -f "$APPARMOR_PROFILE_PATH" || true - if command -v apparmor_parser >/dev/null 2>&1; then - sudo apparmor_parser -R "$APPARMOR_PROFILE_PATH" 2>/dev/null || true - fi - fi - echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" } From 816373b7958f7c5cd08951f597391a1130b38c22 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 13 May 2026 11:03:12 +0530 Subject: [PATCH 819/864] feat: linux app image dekstopName for icons in taskbar --- src-electron/package-lock.json | 12 ++++++------ src-electron/package.json | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src-electron/package-lock.json b/src-electron/package-lock.json index 19b2ec2c..776f661f 100644 --- a/src-electron/package-lock.json +++ b/src-electron/package-lock.json @@ -1,17 +1,17 @@ { "name": "phoenix-code-electron-shell", - "version": "5.1.5", + "version": "5.1.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-electron-shell", - "version": "5.1.5", + "version": "5.1.8", "dependencies": { "keytar": "^7.9.0" }, "devDependencies": { - "electron": "^41.1.1", + "electron": "^41.5.1", "electron-builder": "^24.13.3" } }, @@ -1787,9 +1787,9 @@ } }, "node_modules/electron": { - "version": "41.1.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-41.1.1.tgz", - "integrity": "sha512-8bgvDhBjli+3Z2YCKgzzoBPh6391pr7Xv2h/tTJG4ETgvPvUxZomObbZLs31mUzYb6VrlcDDd9cyWyNKtPm3tA==", + "version": "41.5.2", + "resolved": "https://registry.npmjs.org/electron/-/electron-41.5.2.tgz", + "integrity": "sha512-bxlZeH/1WzvKbijmT7dH5MCqlJ/h2SfDJczNhHJe5srDJzZboiOQpwTlUFBecqDbGoBpmEekhDfjbubPnM8G7g==", "dev": true, "hasInstallScript": true, "license": "MIT", diff --git a/src-electron/package.json b/src-electron/package.json index bc299305..f54a70e7 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -8,6 +8,7 @@ ], "version": "5.1.8", "productName": "Phoenix Code Experimental Build", + "desktopName": "phoenix-code", "description": "Phoenix Code Experimental Build", "main": "main.js", "scripts": { @@ -19,7 +20,7 @@ "keytar": "^7.9.0" }, "devDependencies": { - "electron": "^41.1.1", + "electron": "^41.5.1", "electron-builder": "^24.13.3" } } \ No newline at end of file From 9ea3249755bc348e1d051cf75a6ccfece6d50c8a Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 13 May 2026 11:15:48 +0530 Subject: [PATCH 820/864] feat: vary electron AppImage desktopName/productName per stage Adds patchElectronStageBranding helper invoked from all 4 electron build entry points after config-effective.json is written. Writes the kebab-case stage identifier into both src-electron/electron-builder.yml productName (becomes the .desktop StartupWMClass) and src-electron/package.json desktopName (Electron 41.5+ Wayland app_id) so they match per stage: dev -> phoenix-code-experimental-build stage -> phoenix-code-pre-release prod -> phoenix-code Without per-stage identifiers the AppImages collapse into one taskbar entry / icon slot when installed side-by-side. Co-Authored-By: Claude Opus 4.7 (1M context) --- package-lock.json | 4 ++-- src-build/ci-setupDistFolders.js | 4 +++- src-build/createDistRelease.js | 4 +++- src-build/createDistTestRelease.js | 4 +++- src-build/createSrcRelease.js | 4 +++- src-build/utils.js | 29 +++++++++++++++++++++++++++++ 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index a1412225..0a260352 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "5.1.5", + "version": "5.1.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "5.1.5", + "version": "5.1.8", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.3", diff --git a/src-build/ci-setupDistFolders.js b/src-build/ci-setupDistFolders.js index e9b5b543..f4bddf35 100644 --- a/src-build/ci-setupDistFolders.js +++ b/src-build/ci-setupDistFolders.js @@ -9,7 +9,7 @@ import { import { EOL } from "os"; import os from "os"; import fs from 'fs'; -import {patchTauriConfigWithMetricsHTML} from "./utils.js"; +import {patchTauriConfigWithMetricsHTML, patchElectronStageBranding} from "./utils.js"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -182,6 +182,8 @@ function createElectronReleaseAssets() { console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); console.log('version:', effectiveConfig.version); fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); + + patchElectronStageBranding(electronDir, effectiveConfig.productName); } ciCreateTauriDistReleaseConfig(); diff --git a/src-build/createDistRelease.js b/src-build/createDistRelease.js index a78db94c..5d68b896 100644 --- a/src-build/createDistRelease.js +++ b/src-build/createDistRelease.js @@ -4,7 +4,7 @@ import { dirname, join } from 'path'; import fs from 'fs'; import * as os from 'os'; import chalk from 'chalk'; -import { getPlatformDetails, patchTauriConfigWithMetricsHTML } from './utils.js'; +import { getPlatformDetails, patchTauriConfigWithMetricsHTML, patchElectronStageBranding } from './utils.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -164,6 +164,8 @@ function createElectronConfig() { console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); console.log('version:', effectiveConfig.version); fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); + + patchElectronStageBranding(electronDir, effectiveConfig.productName); } function buildElectron() { diff --git a/src-build/createDistTestRelease.js b/src-build/createDistTestRelease.js index da15019b..2977ab4f 100644 --- a/src-build/createDistTestRelease.js +++ b/src-build/createDistTestRelease.js @@ -4,7 +4,7 @@ import { dirname, join } from 'path'; import fs from 'fs'; import * as os from 'os'; import chalk from 'chalk'; -import { getPlatformDetails } from './utils.js'; +import { getPlatformDetails, patchElectronStageBranding } from './utils.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -160,6 +160,8 @@ function createElectronConfig() { console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); console.log('version:', effectiveConfig.version); fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); + + patchElectronStageBranding(electronDir, effectiveConfig.productName); } function buildElectron() { diff --git a/src-build/createSrcRelease.js b/src-build/createSrcRelease.js index 0d978fea..a8dfa8b3 100644 --- a/src-build/createSrcRelease.js +++ b/src-build/createSrcRelease.js @@ -4,7 +4,7 @@ import { dirname, join } from 'path'; import fs from 'fs'; import * as os from 'os'; import chalk from 'chalk'; -import { getPlatformDetails } from './utils.js'; +import { getPlatformDetails, patchElectronStageBranding } from './utils.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); @@ -136,6 +136,8 @@ function createElectronConfig() { console.log('gaMetricsURL:', effectiveConfig.gaMetricsURL); console.log('version:', effectiveConfig.version); fs.writeFileSync(configEffectivePath, JSON.stringify(effectiveConfig, null, 2)); + + patchElectronStageBranding(electronDir, effectiveConfig.productName); } function buildElectron() { diff --git a/src-build/utils.js b/src-build/utils.js index f13c4b3d..a36081dd 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -103,6 +103,35 @@ const METRIC_URL_FOR_STAGE = { "production": "https://phcode.dev/desktop-metrics.html" }; +/** + * Patches the electron build inputs so each stage has a unique app identity: + * - src-electron/package.json `desktopName` (Electron 41.5+ uses this as the Wayland app_id) + * - src-electron/electron-builder.yml `productName` (becomes the .desktop StartupWMClass + binary name) + * Both are set to the kebab-case form of `productName` so they match. Without matching values, + * the running window can't be paired to its .desktop entry and falls back to the generic Electron icon. + * + * @param {string} electronDir - absolute path to src-electron/ + * @param {string} productName - stage-specific display name from config-effective.json + * (e.g. "Phoenix Code", "Phoenix Code Pre-release", "Phoenix Code Experimental Build") + */ +export function patchElectronStageBranding(electronDir, productName) { + const appId = productName.toLowerCase().trim().replace(/\s+/g, '-'); + console.log(`Patching electron stage branding -> ${appId}`); + + const pkgPath = path.join(electronDir, 'package.json'); + const pkg = JSON.parse(fs.readFileSync(pkgPath)); + pkg.desktopName = appId; + fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2)); + + const builderPath = path.join(electronDir, 'electron-builder.yml'); + const builderYml = fs.readFileSync(builderPath, 'utf8'); + const patched = builderYml.replace(/^productName:.*$/m, `productName: ${appId}`); + if (patched === builderYml) { + throw new Error(`Could not find productName line in ${builderPath}`); + } + fs.writeFileSync(builderPath, patched); +} + export function patchTauriConfigWithMetricsHTML(tauriConf, useClonedPhoenix) { const platform = getPlatformDetails().platform; let phoenixConfigPath = (platform === "win") ? `${__dirname}\\..\\..\\phoenix\\dist\\config.json` From bbb340cf5df12a0345de66779aee754f85c1d182 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 13 May 2026 11:22:49 +0530 Subject: [PATCH 821/864] fix: make patchElectronStageBranding idempotent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous "did we change anything" check inferred regex match failure from `patched === builderYml`, which also fires when the productName line is already the target value — so a second run (or any prod build, since the committed default is already `phoenix-code`) threw "Could not find productName line". Test the regex directly instead. Co-Authored-By: Claude Opus 4.7 (1M context) --- src-build/utils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src-build/utils.js b/src-build/utils.js index a36081dd..0480541f 100644 --- a/src-build/utils.js +++ b/src-build/utils.js @@ -125,11 +125,11 @@ export function patchElectronStageBranding(electronDir, productName) { const builderPath = path.join(electronDir, 'electron-builder.yml'); const builderYml = fs.readFileSync(builderPath, 'utf8'); - const patched = builderYml.replace(/^productName:.*$/m, `productName: ${appId}`); - if (patched === builderYml) { + const productNameRegex = /^productName:.*$/m; + if (!productNameRegex.test(builderYml)) { throw new Error(`Could not find productName line in ${builderPath}`); } - fs.writeFileSync(builderPath, patched); + fs.writeFileSync(builderPath, builderYml.replace(productNameRegex, `productName: ${appId}`)); } export function patchTauriConfigWithMetricsHTML(tauriConf, useClonedPhoenix) { From 616d245dcd22f9394172e781411b1525a57e1007 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 13 May 2026 12:02:02 +0530 Subject: [PATCH 822/864] chore: set electron AppImage dev kebab as committed default src-electron/package.json desktopName and src-electron/electron-builder.yml productName were committed as the prod kebab (`phoenix-code`), but the matching display productName ("Phoenix Code Experimental Build") and config.json `stage: dev` are dev defaults. Align both to the dev kebab so a raw `npm run build:appimage` (no wrapper script) produces a coherent dev AppImage; CI wrappers continue to overwrite per stage via patchElectronStageBranding. Co-Authored-By: Claude Opus 4.7 (1M context) --- src-electron/electron-builder.yml | 2 +- src-electron/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src-electron/electron-builder.yml b/src-electron/electron-builder.yml index 8ba1d295..045d9701 100644 --- a/src-electron/electron-builder.yml +++ b/src-electron/electron-builder.yml @@ -1,5 +1,5 @@ appId: io.phcode.dev -productName: phoenix-code +productName: phoenix-code-experimental-build copyright: Copyright © 2024 phcode.dev asar: true diff --git a/src-electron/package.json b/src-electron/package.json index f54a70e7..d19588c4 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -8,7 +8,7 @@ ], "version": "5.1.8", "productName": "Phoenix Code Experimental Build", - "desktopName": "phoenix-code", + "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", "main": "main.js", "scripts": { From 7ad6dd7264470e42e75327a6d33ce62144f05f87 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 13 May 2026 12:41:54 +0530 Subject: [PATCH 823/864] fix: load BrowserWindow icon from resources/ in packaged AppImage The BrowserWindow icon path resolved correctly in dev (`__dirname` = src-electron/, so `../src-tauri/icons/icon.png` reached the source tree) but not in the packaged AppImage, where `__dirname` is inside the asar and src-tauri/ is not bundled. Electron silently dropped the icon and the taskbar fell back to the generic Electron icon. Copy icon.png into the AppImage's resources/ via extraResources, and load it from process.resourcesPath when app.isPackaged. Co-Authored-By: Claude Opus 4.7 (1M context) --- src-electron/electron-builder.yml | 2 ++ src-electron/main.js | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src-electron/electron-builder.yml b/src-electron/electron-builder.yml index 045d9701..8a621dff 100644 --- a/src-electron/electron-builder.yml +++ b/src-electron/electron-builder.yml @@ -27,6 +27,8 @@ extraResources: to: "bin" - from: "phoenix-dist" to: "phoenix-dist" + - from: "../src-tauri/icons/icon.png" + to: "icon.png" extraMetadata: main: main.js diff --git a/src-electron/main.js b/src-electron/main.js index b548c491..29a2da4f 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -118,7 +118,9 @@ async function createWindow() { contextIsolation: true, nodeIntegration: false }, - icon: path.join(__dirname, '..', 'src-tauri', 'icons', 'icon.png') + icon: app.isPackaged + ? path.join(process.resourcesPath, 'icon.png') + : path.join(__dirname, '..', 'src-tauri', 'icons', 'icon.png') }); // Track window state for persistence From c0f763f419539723098411f2fce8b9bc6187f3ff Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 13 May 2026 11:27:27 +0000 Subject: [PATCH 824/864] ci: update phcode version to 5.1.9 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 307a50cb..178cedcf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.8", + "version": "5.1.9", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "c0e3776e806c2c9d153b4b7bd8d35b153cc68361" + "commit": "a52688cc7c040ebef8df9283520dc7439252f021" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index d19588c4..10b884f4 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.8", + "version": "5.1.9", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ea6f4509..7c553667 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.8" +version = "5.1.9" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index c992ee97..8c636e94 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.8" + "version": "5.1.9" }, "tauri": { "allowlist": { From ef282556a548d40952b9aa13ee0c1c6e7a598376 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 13 May 2026 17:20:31 +0530 Subject: [PATCH 825/864] fix(electron): allow cross-origin XHR/fetch to asset:// scheme The asset:// scheme was registered with only supportFetchAPI+stream, which caused Chromium to block XHR/fetch from the phtauri://localhost app origin to asset://localhost/... with a CORS error. Extensions loaded from appLocalData/assets/ failed to load their requirejs-config, keymap, snippets, and HTML panels. Add standard+secure+corsEnabled to the scheme privileges (matching phtauri and Tauri's wry asset protocol) and set Access-Control-Allow-Origin:* on responses so cross-origin reads from the app are allowed. --- src-electron/main.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src-electron/main.js b/src-electron/main.js index 29a2da4f..3b537eb1 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -40,11 +40,17 @@ protocol.registerSchemesAsPrivileged([ } }, { - // asset:// is for serving static files only - minimal privileges to match Tauri's security posture - // No standard/secure/corsEnabled - just enough for fetch() to read local assets + // asset:// serves static files (extensions, themes, user assets) from appLocalData/assets/. + // Needs standard+secure+corsEnabled so the phtauri:// app origin can XHR/fetch these files + // (RequireJS text plugin, $.getJSON for requirejs-config.json/keymap.json/snippets.json, etc.). + // Without these privileges Chromium blocks cross-origin requests to asset:// with a CORS error. + // This matches Tauri's wry asset protocol, which is also CORS-enabled. scheme: 'asset', privileges: { + standard: true, + secure: true, supportFetchAPI: true, + corsEnabled: true, stream: true } } @@ -326,7 +332,7 @@ app.whenReady().then(async () => { const appDataDir = getAppDataDir(); const assetsDir = path.join(appDataDir, 'assets'); - protocol.handle('asset', (request) => { + protocol.handle('asset', async (request) => { try { const url = new URL(request.url); // Decode the path from URL encoding @@ -341,13 +347,17 @@ app.whenReady().then(async () => { // Security: Ensure path is under assets directory (prevent directory traversal) if (!normalizedRequested.startsWith(normalizedAssetsDir)) { console.error('Asset access denied - path not under assets dir:', requestedPath); - return new Response('Access denied', { status: 403 }); + return new Response('Access denied', { status: 403, headers: { 'Access-Control-Allow-Origin': '*' } }); } - return net.fetch(`file://${normalizedRequested}`); + const response = await net.fetch(`file://${normalizedRequested}`); + // Mirror Tauri's wry asset protocol: allow the phtauri:// app origin to XHR/fetch these files. + const headers = new Headers(response.headers); + headers.set('Access-Control-Allow-Origin', '*'); + return new Response(response.body, { status: response.status, statusText: response.statusText, headers }); } catch (err) { console.error('Asset protocol error:', err); - return new Response('Not found', { status: 404 }); + return new Response('Not found', { status: 404, headers: { 'Access-Control-Allow-Origin': '*' } }); } }); From 033b475736238515c055858083635857251867f1 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 13 May 2026 17:30:26 +0000 Subject: [PATCH 826/864] ci: update phcode version to 5.1.10 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 178cedcf..09a2527b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.9", + "version": "5.1.10", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "a52688cc7c040ebef8df9283520dc7439252f021" + "commit": "ddbcd4ca9406daa5d2a2ebe7f3d6ed699bae19d7" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 10b884f4..ea27ea0a 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.9", + "version": "5.1.10", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 7c553667..8ab20247 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.9" +version = "5.1.10" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 8c636e94..73d3d3c0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.9" + "version": "5.1.10" }, "tauri": { "allowlist": { From cd9b8357068e21597c3c26a796b5d7e836fc24e9 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 14 May 2026 05:23:35 +0000 Subject: [PATCH 827/864] ci: update phcode version to 5.1.11 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 09a2527b..312d255c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.10", + "version": "5.1.11", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "ddbcd4ca9406daa5d2a2ebe7f3d6ed699bae19d7" + "commit": "45cc670db96ed8c32f75336047f9c56425520572" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index ea27ea0a..666f8cf8 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.10", + "version": "5.1.11", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8ab20247..a1a99af4 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.10" +version = "5.1.11" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 73d3d3c0..f39fbff2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.10" + "version": "5.1.11" }, "tauri": { "allowlist": { From dc4679948deefca141409c5bafa1080beb5be71f Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 14 May 2026 10:57:27 +0000 Subject: [PATCH 828/864] ci: update phcode version to 5.1.12 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 312d255c..780b9d52 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.11", + "version": "5.1.12", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "45cc670db96ed8c32f75336047f9c56425520572" + "commit": "1d6395697a1b0bcf1f2fa4bf23278c263af27882" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 666f8cf8..033d5cd0 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.11", + "version": "5.1.12", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a1a99af4..36bf2a72 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.11" +version = "5.1.12" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f39fbff2..89241825 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.11" + "version": "5.1.12" }, "tauri": { "allowlist": { From 0de196cb0f8942e3ca96cc342697cb81209554e9 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 14 May 2026 11:21:43 +0000 Subject: [PATCH 829/864] ci: update phcode version to 5.1.13 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 780b9d52..1ac7b351 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.12", + "version": "5.1.13", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "1d6395697a1b0bcf1f2fa4bf23278c263af27882" + "commit": "09d0c46136f6f5f0226783bdd1dcaec23b990523" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 033d5cd0..861aeb51 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.12", + "version": "5.1.13", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 36bf2a72..055c694a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.12" +version = "5.1.13" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 89241825..13cad7eb 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.12" + "version": "5.1.13" }, "tauri": { "allowlist": { From c8fce122017ab8b2465fd1adca1dc274c282ffc7 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 14 May 2026 12:21:48 +0000 Subject: [PATCH 830/864] ci: update phcode version to 5.1.14 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 1ac7b351..7c1bb8f6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.13", + "version": "5.1.14", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "09d0c46136f6f5f0226783bdd1dcaec23b990523" + "commit": "29b71e9ed60b5d475c2976096fd7fff4fb22a9f0" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 861aeb51..1ccaa49f 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.13", + "version": "5.1.14", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 055c694a..8d0c53c1 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.13" +version = "5.1.14" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 13cad7eb..adeb81e0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.13" + "version": "5.1.14" }, "tauri": { "allowlist": { From c8a7835a2fc44ba7aea4ec036580be47f756b796 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 14 May 2026 12:52:23 +0000 Subject: [PATCH 831/864] ci: update phcode version to 5.1.15 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7c1bb8f6..829cd829 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.14", + "version": "5.1.15", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "29b71e9ed60b5d475c2976096fd7fff4fb22a9f0" + "commit": "4a8a063fd402c3dabddd72def3f68633bf14406b" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 1ccaa49f..3ff30820 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.14", + "version": "5.1.15", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 8d0c53c1..b05b69bd 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.14" +version = "5.1.15" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index adeb81e0..ce424022 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.14" + "version": "5.1.15" }, "tauri": { "allowlist": { From 27d8af2b67f30de89caddf27e52839328b2ea095 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 16 May 2026 11:19:51 +0000 Subject: [PATCH 832/864] ci: update phcode version to 5.1.16 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 829cd829..bb6ed5ae 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.15", + "version": "5.1.16", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "4a8a063fd402c3dabddd72def3f68633bf14406b" + "commit": "f2cd6487f482dc92bbc75c740965f833fd48b8cf" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 3ff30820..ac08e995 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.15", + "version": "5.1.16", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b05b69bd..1d25c7e2 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.15" +version = "5.1.16" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ce424022..04bbb207 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.15" + "version": "5.1.16" }, "tauri": { "allowlist": { From afee19f7b9b1b329444c7467c30f484c3a7bc64a Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 16 May 2026 19:41:21 +0530 Subject: [PATCH 833/864] chore: increase build timouts as builds timing out for prod build gen --- .github/workflows/tauri-build-dev.yml | 4 ++-- .github/workflows/tauri-build-prod.yml | 4 ++-- .github/workflows/tauri-build-staging.yml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tauri-build-dev.yml b/.github/workflows/tauri-build-dev.yml index 87c7d6ae..0210bafa 100644 --- a/.github/workflows/tauri-build-dev.yml +++ b/.github/workflows/tauri-build-dev.yml @@ -76,7 +76,7 @@ jobs: needs: [create-release, build-mac-m1-node-modules] permissions: contents: write - timeout-minutes: 60 + timeout-minutes: 100 strategy: fail-fast: false matrix: @@ -276,7 +276,7 @@ jobs: needs: [ create-release ] permissions: contents: write - timeout-minutes: 60 + timeout-minutes: 100 runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tauri-build-prod.yml b/.github/workflows/tauri-build-prod.yml index c028c1c0..aeefffb2 100644 --- a/.github/workflows/tauri-build-prod.yml +++ b/.github/workflows/tauri-build-prod.yml @@ -76,7 +76,7 @@ jobs: needs: [create-release, build-mac-m1-node-modules] permissions: contents: write - timeout-minutes: 60 + timeout-minutes: 100 strategy: fail-fast: false matrix: @@ -325,7 +325,7 @@ jobs: needs: [ create-release ] permissions: contents: write - timeout-minutes: 60 + timeout-minutes: 100 runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/tauri-build-staging.yml b/.github/workflows/tauri-build-staging.yml index 33d86303..e5914ee5 100644 --- a/.github/workflows/tauri-build-staging.yml +++ b/.github/workflows/tauri-build-staging.yml @@ -76,7 +76,7 @@ jobs: needs: [create-release, build-mac-m1-node-modules] permissions: contents: write - timeout-minutes: 60 + timeout-minutes: 100 strategy: fail-fast: false matrix: @@ -276,7 +276,7 @@ jobs: needs: [ create-release ] permissions: contents: write - timeout-minutes: 60 + timeout-minutes: 100 runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 From 2b0800441213d274da2466843a6a3fa0a7a01635 Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 17 May 2026 09:57:36 +0530 Subject: [PATCH 834/864] chore: add electron install location identifier apis for auto updater --- src-electron/main.js | 18 +++++++++++++++++- src-electron/preload.js | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src-electron/main.js b/src-electron/main.js index 3b537eb1..a8b497af 100644 --- a/src-electron/main.js +++ b/src-electron/main.js @@ -253,12 +253,28 @@ ipcMain.handle('is-packaged', (event) => { return app.isPackaged; }); -// Get executable path (path to the AppImage on Linux) +// Path to the running Electron binary. On Linux AppImages this is the +// FUSE-mounted binary (/tmp/.mount_*/...), not the .AppImage file — +// use 'get-installed-app-path' if you need the user-visible install path. ipcMain.handle('get-executable-path', (event) => { assertTrusted(event); return process.execPath; }); +// Path of the installed app, or null if not running from an installed build. +// - Linux AppImage: process.env.APPIMAGE (set by AppRun to the .AppImage path) +// - Other / dev / unpacked: null (auto-update not supported yet) +ipcMain.handle('get-installed-app-path', (event) => { + assertTrusted(event); + if (!app.isPackaged) { + return null; + } + if (process.platform === 'linux') { + return process.env.APPIMAGE || null; + } + return null; +}); + // Update scheduled state - shared across windows for multi-window update persistence ipcMain.handle('set-update-scheduled', (event, scheduled) => { assertTrusted(event); diff --git a/src-electron/preload.js b/src-electron/preload.js index 99467063..b818fa0f 100644 --- a/src-electron/preload.js +++ b/src-electron/preload.js @@ -173,6 +173,7 @@ contextBridge.exposeInMainWorld('electronAPI', { getAppVersion: () => ipcRenderer.invoke('get-app-version'), isPackaged: () => ipcRenderer.invoke('is-packaged'), getExecutablePath: () => ipcRenderer.invoke('get-executable-path'), + getInstalledAppPath: () => ipcRenderer.invoke('get-installed-app-path'), setUpdateScheduled: (scheduled) => ipcRenderer.invoke('set-update-scheduled', scheduled), getUpdateScheduled: () => ipcRenderer.invoke('get-update-scheduled') }); From f00b10d1d5598406d1c7683b569251e7eb4c6c4e Mon Sep 17 00:00:00 2001 From: abose Date: Sun, 17 May 2026 11:11:15 +0530 Subject: [PATCH 835/864] chore: copy prod linux installer script to dev stage --- .../installer-latest-experimental-build.sh | 967 ++++++++---------- 1 file changed, 408 insertions(+), 559 deletions(-) diff --git a/docs/linux/installer-latest-experimental-build.sh b/docs/linux/installer-latest-experimental-build.sh index 24327768..8c442ddc 100755 --- a/docs/linux/installer-latest-experimental-build.sh +++ b/docs/linux/installer-latest-experimental-build.sh @@ -1,42 +1,40 @@ #!/bin/bash -set -euo pipefail # Exit immediately if a command exits with a non-zero status. -# Check if jq is installed. This is only used in dev builds and not actual prod builds as jq -# is not a default in most systems -if ! command -v jq &> /dev/null -then - echo "jq is not installed. This check is only present in dev builds" - # Provide installation command based on the package manager. - # Adjust the command according to the target Linux distribution's package manager. - echo "To install jq, run one of the following commands based on your Linux distribution:" - - # Suggest installation commands for different package managers - echo "Ubuntu/Debian: sudo apt-get install jq" - echo "Fedora: sudo dnf install jq" - echo "CentOS/RHEL: sudo yum install jq" - echo "Arch Linux: sudo pacman -S jq" - - # Wait for the user to press any key - read -n 1 -s -r -p "Press any key to continue after installing jq" - echo -fi -# Continue with the rest of the script... -# Define common variables -DESKTOP_DIR=$HOME/.local/share/applications -GITHUB_REPO="phcode-dev/phoenix-desktop" -RELEASES_URL="https://api.github.com/repos/$GITHUB_REPO/releases" -# Fetch the list of releases, assuming the first prerelease in the list is the latest, get the prerelase api url -API_URL=$(wget -qO- "$RELEASES_URL" | jq -r '[.[] | select(.prerelease == true)][0].url') -echo "$API_URL" +set -euo pipefail +# Phoenix Code Linux installer. +# +# Downloads the latest Phoenix Code AppImage from the update JSON, then probes +# the downloaded AppImage with `--version` (early-exit handler at +# src-electron/main.js:23-26). If the probe succeeds, no apt/dnf/pacman install +# is attempted — the system already has every shared library Phoenix Code +# needs at startup, regardless of which package name provides it. +# +# Beyond the --version probe, the installer also checks for the gnome-keyring +# daemon binary — libsecret needs the daemon for keytar credential storage, +# and --version exits before keytar is require()d. Sudo is only requested if +# libs or the keyring daemon are actually missing. +# +# On Ubuntu 24.04+ / Debian 13+, Chromium's unprivileged userns sandbox can +# be blocked by the kernel sysctl. The app still launches because the wrapper +# script falls back to --no-sandbox; we no longer install an AppArmor profile +# to keep the kernel sandbox enabled (the renderer-RCE-to-syscall threat the +# kernel sandbox guards against is narrow, and Phoenix Code's actual attack +# surface flows through the IPC bridge which the kernel sandbox doesn't gate). +# +# Also wires up a desktop entry + `phcode` wrapper script that handles +# AppImage launch fallbacks. + +DESKTOP_DIR=$HOME/.local/share/applications +UPDATE_JSON_URL="https://updates.phcode.io/tauri/update-latest-experimental-build.json" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" -DESKTOP_DIR="$HOME/.local/share/applications" # Directory for desktop entries DESKTOP_ENTRY_NAME="PhoenixCode.desktop" -DESKTOP_APP_NAME="Phoenix Code Experimental Build" +DESKTOP_APP_NAME="Phoenix Code" DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" -SCRIPT_NAME="phcode" # Name of the script to invoke the binary +SCRIPT_NAME="phcode" BINARY_NAME="phoenix-code" +APPIMAGE_NAME="phoenix-code.AppImage" declare -a MIME_TYPES=( "text/html" @@ -65,328 +63,357 @@ declare -a MIME_TYPES=( "text/cjs" ) - -# Define color variables for easy reference GREEN="\e[32m" YELLOW="\e[33m" RED="\e[31m" RESET="\e[0m" -# Cleanup Function -# -# Purpose: -# The cleanup function is designed to ensure that the script cleans up any temporary -# resources it used during its execution. Specifically, it removes the temporary directory -# created at the beginning of the script, along with all its contents. This is crucial for -# maintaining a clean file system and avoiding the accumulation of unused files. -# -# Behavior: -# - The function targets a temporary directory specified by the `$TMP_DIR` variable. -# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. -# This includes any temporary files, downloaded assets, or other data generated during the script's execution. -# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes -# automatically when the script exits, regardless of the exit point. This includes normal completion, -# errors, or manual termination via signals like SIGINT (Ctrl+C). -# -# Considerations: -# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. -# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. -# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` -# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. -# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within -# `$TMP_DIR` is expendable and safe to delete. -# -# Usage: -# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` -# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` -# is correctly set to the temporary directory path before invoking the function. -# cleanup() { - rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. + rm -rf "$TMP_DIR" } +# Surface user interrupts (Ctrl+C / kill) with a clear message and exit 130, +# while still running cleanup. Without this, dpkg unpacks and sudo prompts can +# make the script look unresponsive to SIGINT for a beat. +on_interrupt() { + echo + echo -e "${RED}Interrupted by user. Cleaning up...${RESET}" + cleanup + exit 130 +} +trap cleanup EXIT +trap on_interrupt INT TERM -trap cleanup EXIT # Register the cleanup function to be called on script exit. +TMP_DIR=$(mktemp -d) +configure_wget_options() { + local wget_version + wget_version=$(wget --version | head -n1 | awk '{print $3}') + local major_version + major_version=$(echo "$wget_version" | cut -d. -f1) -TMP_DIR=$(mktemp -d) + if [[ "$major_version" -ge 2 ]]; then + echo "-c --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" + else + echo "-c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO" + fi +} -# Create Invocation Script Function -# -# Purpose: -# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. -# This script is intended to simplify the execution of Phoenix Code by providing a more accessible -# command interface. The generated script is placed in a user-accessible binary directory, making it -# possible to run Phoenix Code from anywhere in the system without needing to specify the full path -# to the binary. -# -# Parameters: -# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. -# - script_name: The name to be given to the invocation script. This name is used both for the -# script file itself and for the symlink created in the user's binary directory. -# - link_dir: The directory where a symlink to the invocation script will be placed, typically -# a location in the user's PATH, such as ~/.local/bin, for easy access. -# -# Behavior: -# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. -# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a -# command to execute the Phoenix Code binary with any passed arguments ("$@"). -# 3. Sets executable permissions on the newly created script. -# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. -# -# Considerations: -# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' -# does not conflict with existing files in these directories to prevent unintended overwrites. -# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes -# these directories are already created and accessible. -# - The generated script includes a warning comment advising against deletion, as it is -# essential for the proper functioning of Phoenix Code when invoked through this script. -# -# Usage: -# This function is intended to be called during the installation or upgrade process of Phoenix Code, -# after the binary has been placed in its final location. It should not be called arbitrarily, as it -# assumes a specific setup and context established by the installer script. -# +check_architecture() { + local arch + arch=$(uname -m) + if [ "$arch" != "x86_64" ]; then + echo -e "${RED}This installer only supports 64-bit x86 (x86_64). Detected: $arch.${RESET}" + exit 1 + fi +} + +# Runtime-library probe: ask the AppImage to print its version and exit. This +# is handled at src-electron/main.js:23-26, but `require('electron')` runs +# before that handler — which means Chromium initializes its sandbox bits even +# for --version. On Ubuntu 24.04+ / Debian 13+ where unprivileged user +# namespaces are restricted, that init can SIGTRAP. Pass --no-sandbox so the +# probe isolates to "are the system shared libraries present and loadable?" +# regardless of the kernel's userns policy. +# +# The `{ … } 2>/dev/null` wrapper suppresses bash's own "Trace/breakpoint trap +# (core dumped)" report when the subprocess dies on signal — those messages +# look alarming but are harmless: we already detect failure via the exit code. +verify_appimage_launches() { + { "$1" --no-sandbox --version >/dev/null 2>&1; } 2>/dev/null +} + +# Returns 0 if the gnome-keyring secret-service daemon binary is on PATH. +# `--version` can't test this because keytar is only require()d at first use, +# so we need an independent presence check. +gnome_keyring_present() { + command -v gnome-keyring-daemon >/dev/null 2>&1 +} + +downloadLatestReleaseInfo() { + local release_info_file="$TMP_DIR/latest_release.json" + if [ ! -f "$release_info_file" ]; then + >&2 echo -e "${GREEN}Fetching the latest release information...${RESET}" + wget -qO "$release_info_file" "$UPDATE_JSON_URL" || { + >&2 echo -e "${RED}Failed to fetch release info from $UPDATE_JSON_URL. Check your internet connection.${RESET}" + exit 1 + } + fi + grep -Po '"version"\s*:\s*"\K[^"]+' "$release_info_file" | head -n1 +} + +# Parses the linux-x86_64 download URL out of the update JSON without needing jq. +getLinuxAppImageUrl() { + awk ' + /"linux-x86_64"[[:space:]]*:/ { in_linux=1 } + in_linux && /"url"[[:space:]]*:/ { + if (match($0, /"url"[[:space:]]*:[[:space:]]*"[^"]+"/)) { + s = substr($0, RSTART, RLENGTH) + sub(/^"url"[[:space:]]*:[[:space:]]*"/, "", s) + sub(/"$/, "", s) + print s + exit + } + } + ' "$TMP_DIR/latest_release.json" +} + +# Generates the `phcode` wrapper script. The wrapper runs the AppImage directly, +# falling back to --appimage-extract-and-run on FUSE failure or to --no-sandbox +# on userns/AppArmor failure (Ubuntu 24.04+ / Debian 13+ blocks Chromium's +# unprivileged user namespace sandbox unless our AppArmor profile is loaded). create_invocation_script() { - local binary_path="$1" + local install_dir="$1" local script_name="$2" local link_dir="$3" - echo "Creating an invocation script for the binary..." - # Start of the generated script - echo "#!/bin/bash" > "$binary_path/$script_name.sh" - # Add a warning comment about the script being auto-generated - echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" - echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" - chmod +x "$binary_path/$script_name" - - echo "Copying the invocation script to $link_dir..." - mkdir -p "$link_dir" # Ensure the directory exists - cp "$binary_path/$script_name" "$link_dir/$script_name" + echo "Creating an invocation script for the AppImage..." + cat > "$install_dir/$script_name" <"\$ERR"; then + if grep -qiE 'fuse|libfuse|fusermount|/dev/fuse' "\$ERR"; then + rm -f "\$ERR" + exec "\$APPIMAGE" --appimage-extract-and-run "\$@" + fi + if grep -qiE 'userns|apparmor|sandbox|setuid|namespace|Check failed' "\$ERR"; then + rm -f "\$ERR" + exec "\$APPIMAGE" --no-sandbox "\$@" + fi + cat "\$ERR" >&2 + rm -f "\$ERR" + exit 1 +fi +rm -f "\$ERR" +EOF + chmod +x "$install_dir/$script_name" + mkdir -p "$link_dir" + cp "$install_dir/$script_name" "$link_dir/$script_name" echo -e "Invocation script created at: $link_dir/$script_name" } -# Install Dependencies Function -# -# Purpose: -# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. -# This function identifies the user's Linux distribution and installs the appropriate packages -# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and -# Arch Linux distributions. -# -# Behavior: -# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. -# If the command fails, it prompts the user to enter their password for `sudo` access. -# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. -# 3. Based on the identified distribution, executes the appropriate package manager command -# with the required packages. Supported package managers are `apt` for Debian-based systems, -# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. -# 4. Updates the package index (if applicable) and installs the packages. -# -# Considerations: -# - The function requires internet access to fetch package information and install packages. -# - It assumes that the user has `sudo` privileges to install packages system-wide. -# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, -# this function must be updated accordingly. -# - Unsupported distributions will result in an error message and termination of the script, -# as the required dependencies cannot be installed automatically. -# - This function does not handle potential errors from package installation commands. It's -# recommended to monitor the output for any issues that may require manual intervention. -# -# Usage: -# This function is intended to be called during the Phoenix Code installation process, typically -# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites -# are met for a successful Phoenix Code execution. -# -install_dependencies() { - echo "Attempting to install required dependencies..." - - # Inform the user that the next steps require administrative access - echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." - # Check if the script can execute sudo commands without interaction - if ! sudo -n true 2>/dev/null; then - echo "Please enter your password to proceed with the installation of dependencies." +# Returns "gnome-keyring" unless the current session is KDE. +# On KDE, kwallet implements the Secret Service interface (KF 5.97+ / ksecretd +# in 2026), and installing gnome-keyring causes a D-Bus activation race for +# org.freedesktop.secrets — see VSCode issue #189672. +gnome_keyring_pkg_if_needed() { + if [[ "${XDG_CURRENT_DESKTOP:-}" =~ KDE ]]; then + echo "" + else + echo "gnome-keyring" fi +} - # Attempt to identify the Linux distribution - if [ -f /etc/os-release ]; then - . /etc/os-release - DISTRO=$ID +# Picks the libfuse2 package name for whatever Ubuntu/Debian release we're on. +# Ubuntu 24.04 Noble+ / Debian 13 Trixie+ / Kali rolling / Mint 22+ / Neon 24+ +# ship libfuse2t64 (the post-y2038 rename); older releases (Ubuntu 20.04 Focal +# / 22.04 Jammy, Debian 11/12, Mint 20/21, Neon 22) ship the pre-rename +# libfuse2. Both provide the same libfuse.so.2 SONAME, so picking by repo +# availability is correct. +choose_fuse_package_apt() { + if apt-cache show libfuse2t64 >/dev/null 2>&1; then + echo libfuse2t64 else - echo "Unable to identify the operating system." - exit 1 + echo libfuse2 fi +} - # Install dependencies based on the distribution - case "$DISTRO" in - ubuntu|debian|linuxmint) - echo "Detected an Ubuntu/Debian based distribution." - sudo apt update - sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ - gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ - gstreamer1.0-tools +# Per-distro package install. Only called when verify_appimage_launches failed +# OR the keyring daemon is missing — i.e., we've already decided we need sudo. +install_packages_for_distro() { + local distro="$1" keyring="$2" + # RHEL 10 does not ship libXScrnSaver in any default channel — left off the + # dnf list intentionally; Electron's XScreenSaver calls no-op on Wayland. + # libxss + libnotify are listed for Arch because gtk3 does NOT pull them in + # transitively but Electron dlopen's them at runtime. + local -a pkgs=() + case "$distro" in + ubuntu|debian|linuxmint|kali|neon) pkgs=("$(choose_fuse_package_apt)" libsecret-1-0) ;; + fedora|rhel|centos) pkgs=(fuse-libs fuse3-libs libsecret) ;; + arch|manjaro|cachyos) pkgs=(fuse2 libsecret libxss libnotify) ;; + esac + [ -n "$keyring" ] && pkgs+=("$keyring") + + case "$distro" in + ubuntu|debian|linuxmint|kali|neon) + # No `yes |` pipeline: under `set -o pipefail`, `yes` dies of SIGPIPE + # after apt exits and the pipeline returns 141, silently aborting the + # installer. Use apt-get -y, and keep user /etc config files via the + # force-conf* options so an unrelated pending upgrade can't prompt. + echo "Detected an Ubuntu/Debian-based distribution." + sudo apt-get update + # shellcheck disable=SC2068 + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ + -o Dpkg::Options::="--force-confdef" \ + -o Dpkg::Options::="--force-confold" \ + ${pkgs[@]} ;; fedora|rhel|centos) - echo "Detected a Fedora/Red Hat based distribution." - sudo dnf install webkit2gtk3 gtk3 \ - gstreamer1-plugins-base gstreamer1-plugins-good - ;; - arch|manjaro) - echo "Detected an Arch Linux based distribution." - sudo pacman -Syu - sudo pacman -S webkit2gtk gtk3 - ;; - *) - echo "Unsupported distribution. Please manually install the required dependencies." - exit 1 - ;; + echo "Detected a Fedora/Red Hat-based distribution." + # shellcheck disable=SC2068 + sudo dnf install -y ${pkgs[@]} + ;; + arch|manjaro|cachyos) + echo "Detected an Arch-based distribution." + sudo pacman -Sy + # shellcheck disable=SC2068 + sudo pacman -S --noconfirm --needed ${pkgs[@]} + ;; esac } -# Verify and Install Dependencies Function -# -# Purpose: -# This function is responsible for verifying if the Phoenix Code application can be successfully -# launched with the current set of installed dependencies. If the initial verification fails, it -# attempts to install the necessary dependencies and then re-verifies the application launch. -# -# Behavior: -# 1. Changes the current directory to the temporary directory where Phoenix Code is located. -# 2. Sets the executable permission for the Phoenix Code binary and attempts to run it with a -# verification-specific command (e.g., `--runVerify`). This step is intended to check if the -# application can start without installing additional dependencies. -# 3. If the initial verification succeeds, the function exits with a success status (0), indicating -# no further action is needed. -# 4. If the initial verification fails, the function proceeds to invoke `install_dependencies` to -# install any missing dependencies specific to the user's Linux distribution. -# 5. After installing dependencies, it attempts to verify the application launch again. If this -# second attempt succeeds, the function exits with a success status (0). -# 6. If the verification fails even after installing dependencies, the function prints an error -# message advising the user to check the application requirements or contact support, and -# exits with an error status (1). -# 7. Finally, the function ensures to change back to the original directory where the script was -# invoked, preserving the user's shell environment. -# -# Considerations: -# - The function assumes that the Phoenix Code binary is located in a temporary directory and -# that this directory is correctly set in the `$TMP_DIR` variable. -# - It relies on the Phoenix Code binary supporting a `--runVerify` command or equivalent for -# verification purposes. If such a command is not available, this part of the function needs -# adjustment. -# - Dependency installation requires administrative privileges; hence, the user might be prompted -# for a password to allow `sudo` operations. -# - The function does not handle all possible error scenarios during dependency installation. -# Users should monitor the output for potential issues that might need manual intervention. + +# Decides what (if anything) the user's system is missing for Phoenix Code to +# run, then installs only the missing piece(s). Three independent probes: # -# Usage: -# This function is intended to be called during the installation or upgrade process of Phoenix Code, -# before finalizing the installation, to ensure that all system requirements are met for the -# application to run properly. +# 1. System shared libraries — probed by running the downloaded AppImage +# with `--version`. main.js exits immediately on this flag, AFTER libfuse +# mounts the AppImage and AFTER the Electron binary loads its NEEDED libs. +# 2. gnome-keyring daemon — binary-presence check; `--version` doesn't +# exercise keytar so it can't verify libsecret/Secret Service end-to-end. # -verify_and_install_dependencies() { - cd "$TMP_DIR/phoenix-code" - # Ensure the binary is executable - chmod +x "./phoenix-code" - # First attempt to verify the application launch - if ./phoenix-code --runVerify; then - echo "Application launch verification successful." - return 0 # Exit the function successfully if verification succeeds - else - echo "Initial verification failed. Attempting to install dependencies..." - install_dependencies # Function to install required dependencies +# Sudo is requested ONLY if at least one of the probes fails. +ensure_runtime_dependencies() { + local appimage="$1" + if [ ! -f /etc/os-release ]; then + echo -e "${RED}Unable to identify the operating system (no /etc/os-release).${RESET}" + exit 1 fi + . /etc/os-release + local distro="${ID:-}" + case "$distro" in + ubuntu|debian|linuxmint|kali|neon|fedora|rhel|centos|arch|manjaro|cachyos) ;; + *) + echo -e "${RED}Unsupported distribution: $distro. Please install libfuse2/fuse2, libsecret, and (on non-KDE) gnome-keyring manually.${RESET}" + exit 1 + ;; + esac + local keyring; keyring=$(gnome_keyring_pkg_if_needed) - # Second attempt to verify the application launch after installing dependencies - if ./phoenix-code --runVerify; then - echo "Application launch verification successful after installing dependencies." - cd - - return 0 # Exit the function successfully if verification succeeds + local libs_ok=1 keyring_ok=1 + verify_appimage_launches "$appimage" || libs_ok=0 + if [ -n "$keyring" ] && ! gnome_keyring_present; then keyring_ok=0; fi + + if [ "$libs_ok" = 1 ] && [ "$keyring_ok" = 1 ]; then + echo -e "${GREEN}All runtime dependencies already present.${RESET}" + return 0 + fi + + if [ "$libs_ok" = 0 ]; then + echo "Installing missing runtime libraries..." else - echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." - cd - - return 1 # Return an error code to indicate failure + echo "Installing system keychain daemon..." + fi + echo "This step requires administrative access." + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed." + fi + + install_packages_for_distro "$distro" "$keyring" + # Re-probe libraries; if still failing, surface a clear warning but don't + # abort — the AppImage may have a runtime-specific issue we can't fix here. + if [ "$libs_ok" = 0 ] && ! verify_appimage_launches "$appimage"; then + echo -e "${YELLOW}WARN: AppImage still fails --version after dep install.${RESET}" fi } -# Set Phoenix Code as the default application for specified MIME types -set_default_application() { - local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file - for mime_type in "${MIME_TYPES[@]}"; do - # Skip setting default application for text/html - if [ "$mime_type" = "text/html" ]; then - continue # Skip to the next iteration +# Returns 0 if any of the common display managers is configured to autologin +# the current user. All probed files are world-readable; no sudo, no prompts. +# Used only to enrich the post-install keyring hint with a probable cause. +autologin_detected() { + local user="${USER:-$(id -un)}" + local f + for f in /etc/gdm3/custom.conf /etc/gdm3/daemon.conf /etc/gdm/custom.conf; do + [ -r "$f" ] && grep -qE '^[[:space:]]*AutomaticLoginEnable[[:space:]]*=[[:space:]]*[Tt]rue' "$f" && return 0 + done + for f in /etc/lightdm/lightdm.conf /etc/lightdm/lightdm.conf.d/*.conf; do + [ -r "$f" ] && grep -qE "^[[:space:]]*autologin-user[[:space:]]*=[[:space:]]*${user}([[:space:]]|$)" "$f" && return 0 + done + for f in /etc/sddm.conf /etc/sddm.conf.d/*.conf; do + [ -r "$f" ] && grep -qE "^[[:space:]]*User[[:space:]]*=[[:space:]]*${user}([[:space:]]|$)" "$f" && return 0 + done + return 1 +} + +# If the user's login keyring is currently locked, print a one-time hint so +# the first-launch unlock dialog isn't a surprise. Uses the side-effect-free +# Locked property on org.freedesktop.Secret.Collection — querying it does NOT +# trigger a prompt. Silently no-ops when busctl is missing, when no Secret +# Service is on the bus (e.g., kwallet-only setups where this message would be +# wrong), or when the keyring is already unlocked. +print_keyring_hint_if_locked() { + command -v busctl >/dev/null 2>&1 || return 0 + local locked + locked=$(busctl --user --no-pager call org.freedesktop.secrets \ + /org/freedesktop/secrets/collection/login \ + org.freedesktop.DBus.Properties Get \ + ss org.freedesktop.Secret.Collection Locked 2>/dev/null \ + | awk '/^b /{print $NF}') + [ "$locked" = "true" ] || return 0 + + echo + echo -e "${YELLOW}Note: your system keychain is currently locked.${RESET}" + echo -e "${YELLOW}The first time Phoenix Code stores or reads a credential, gnome-keyring${RESET}" + echo -e "${YELLOW}will ask once for your login password to unlock it. This is a one-time${RESET}" + echo -e "${YELLOW}per-session Linux behavior — not a Phoenix Code prompt.${RESET}" + if autologin_detected; then + echo -e "${YELLOW}(Autologin is enabled on this machine, which is why PAM did not${RESET}" + echo -e "${YELLOW} auto-unlock the keyring at session start.)${RESET}" + fi +} + +set_default_application() { + local desktop_file="$DESKTOP_ENTRY_NAME" + + if [ "${KDE_SESSION_VERSION:-0}" -gt 0 ] && ! command -v qtpaths &> /dev/null; then + local qtpaths_locations=( + "/usr/lib/qt6/bin" + "/usr/lib/qt5/bin" + "/usr/lib64/qt6/bin" + "/usr/lib64/qt5/bin" + "/opt/qt6/bin" + "/opt/qt5/bin" + ) + for qtpath_dir in "${qtpaths_locations[@]}"; do + if [ -x "$qtpath_dir/qtpaths" ] || [ -x "$qtpath_dir/qtpaths6" ]; then + export PATH="$qtpath_dir:$PATH" + break fi + done + fi - xdg-mime default "$desktop_file" "$mime_type" + for mime_type in "${MIME_TYPES[@]}"; do + if [ "$mime_type" = "text/html" ]; then + continue + fi + xdg-mime default "$desktop_file" "$mime_type" done echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" } -# Copy Files to Destination Function -# -# Purpose: -# This function is responsible for setting up the final installation directory for Phoenix Code, -# moving the necessary files into place, creating the invocation script, and setting up the desktop -# entry for the application. It ensures that all components of Phoenix Code are correctly installed -# and configured in the user's environment. -# -# Behavior: -# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files -# will reside. -# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. -# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from -# the temporary directory (`$TMP_DIR`) to the installation directory. -# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. -# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. -# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. -# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and -# launchers, and places this file in the desktop entry directory. -# 8. Updates the system's desktop database to ensure the new application entry is recognized and available -# in application menus and launchers. This step might involve commands like `update-desktop-database` -# or `kbuildsycoca5`, depending on the desktop environment. -# -# Considerations: -# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and -# that this directory is correctly set. -# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and -# accessible. If these variables are unset or incorrect, the function may not perform as intended. -# - Administrative privileges may be required for certain operations, such as updating the desktop database -# or setting permissions, depending on the system's configuration. -# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function -# does perform significant file system operations that could potentially conflict with existing user data -# or system settings. -# -# Usage: -# This function is intended to be called as part of the Phoenix Code installation process, after the -# application's binary and other necessary files have been prepared in a temporary location. It finalizes -# the installation by placing all components in their appropriate locations within the user's system. -# -copyFilesToDestination(){ +copyFilesToDestination() { echo "Setting up the installation directory at $INSTALL_DIR..." mkdir -p "$INSTALL_DIR" mkdir -p "$DESKTOP_DIR" - echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" - echo "Moving the necessary files to the installation directory..." - echo -e "Phoenix Code files moved to: $INSTALL_DIR" - mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { - echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" + mv "$TMP_DIR/$APPIMAGE_NAME" "$INSTALL_DIR/$APPIMAGE_NAME" || { + echo -e "${RED}Failed to move the AppImage to the installation directory. Please check the permissions and try again.${RESET}" exit 1 } - # Move the icon to the installation directory mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" - echo "Setting the correct permissions for the executable..." - chmod +x "$INSTALL_DIR/phoenix-code" || { - echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" + chmod +x "$INSTALL_DIR/$APPIMAGE_NAME" || { + echo -e "${RED}Failed to set executable permissions on the AppImage.${RESET}" exit 1 } - echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" + echo -e "AppImage installed at: $INSTALL_DIR/$APPIMAGE_NAME" - mkdir -p "$LINK_DIR" # Ensure the directory exists - # Call the function to create and copy the invocation script + mkdir -p "$LINK_DIR" create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" - # Convert MIME types array to semicolon-separated string for the desktop entry - MIME_TYPES_STRING=$(IFS=";"; echo "${MIME_TYPES[*]}") + + local mime_types_string + mime_types_string=$(IFS=";"; echo "${MIME_TYPES[*]}") echo "Creating desktop entry..." cat > "$DESKTOP_ENTRY" < /dev/null; then - update-desktop-database "$DESKTOP_DIR" - echo -e "Desktop database updated in: $DESKTOP_DIR" + update-desktop-database "$DESKTOP_DIR" fi - - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if [ "${XDG_CURRENT_DESKTOP:-}" = "KDE" ]; then if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 + kbuildsycoca5 fi fi - # Set Phoenix Code as the default application for the MIME types - set_default_application - echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" - -} -downloadLatestReleaseInfo() { - local release_info_file="$TMP_DIR/latest_release.json" - - if [ -f "$release_info_file" ]; then - # Only extract and echo the version number, without any additional messages - grep -Po '"tag_name": "dev-app-v\K[\d.]+(?=")' "$release_info_file" - return + if [[ "${XDG_CURRENT_DESKTOP:-}" =~ LXQt ]]; then + if command -v xdg-desktop-menu &> /dev/null; then + xdg-desktop-menu forceupdate + echo -e "${YELLOW}Please log out and log back in to see Phoenix Code in the panel.${RESET}" + else + echo -e "${RED}Failed to update LXQt menu. Please log out and log back in to see Phoenix Code in the panel.${RESET}" + fi fi - # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly - >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET} " - wget -qO "$release_info_file" "$API_URL" || { - >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" - exit 1 - } - - # Only extract and echo the version number after successful download - grep -Po '"tag_name": "dev-app-v\K[\d.]+(?=")' "$release_info_file" + set_default_application + echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" + print_keyring_hint_if_locked } -# Download Latest Release Information Function -# -# Purpose: -# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function -# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to -# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. -# -# Behavior: -# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary -# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already -# been fetched and proceeds to extract the version number from this file without re-downloading. -# 2. If the release information file does not exist, the function uses `wget` to download the JSON data -# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint -# of the Phoenix Code GitHub repository. -# 3. The JSON data is saved to `latest_release.json` in the temporary directory. -# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular -# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version -# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number -# portion. -# 5. Echoes the extracted version number for use by the calling context. -# -# Considerations: -# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available -# in the execution environment. -# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code -# repository for this function to work as intended. -# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, -# the `grep` pattern used to extract the version number may need to be updated. -# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an -# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the -# latest release information. -# - The function does not perform error handling for the `wget` command. If the download fails, the script may -# exit or behave unexpectedly depending on the `set -e` setting. -# -# Usage: -# This function is intended to be called during the installation or upgrade process to determine the latest -# version of Phoenix Code. The extracted version number can be used to compare with the currently installed -# version and decide whether an upgrade is necessary. -# -downloadAndInstall(){ +downloadAndInstall() { echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null - CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') - echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" - - BEST_MATCH_URL="" - BEST_MATCH_VERSION=0 - echo "Searching for a compatible binary..." - - while read -r BINARY_URL; do - BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') - if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then - BEST_MATCH_URL="$BINARY_URL" - BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" - echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" - fi - done < <(grep -oP '"browser_download_url": "\K(.*_linux_bin-GLIBC-[\d\.]+\.tar\.gz)(?=")' "$TMP_DIR/latest_release.json") + check_architecture - if [ -z "$BEST_MATCH_URL" ]; then - echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" + local appimage_url + appimage_url=$(getLinuxAppImageUrl) + if [ -z "$appimage_url" ]; then + echo -e "${RED}Could not find a linux-x86_64 AppImage URL in the release info.${RESET}" exit 1 fi - echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { - echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" + echo -e "${YELLOW}Downloading the AppImage from $appimage_url...${RESET}" + local wget_opts + wget_opts=$(configure_wget_options) + # shellcheck disable=SC2086 + wget $wget_opts "$TMP_DIR/$APPIMAGE_NAME" "$appimage_url" || { + echo -e "${RED}Failed to download the AppImage. Please check your internet connection and try again.${RESET}" exit 1 } - echo -e "Downloading the icon..." - wget -c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO "$TMP_DIR/icon.png" "$ICON_URL" || { - echo -e "${RED}Failed to download Icon${RESET}"; - exit 1; - } - echo "Extracting the binary to $TMP_DIR..." - tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { - echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" + + echo "Downloading the icon..." + # shellcheck disable=SC2086 + wget $wget_opts "$TMP_DIR/icon.png" "$ICON_URL" || { + echo -e "${RED}Failed to download the icon.${RESET}" exit 1 } - if [ -f "$TMP_DIR/phoenix-code/phoenix-code-experimental-build" ]; then - echo "The file $TMP_DIR/phoenix-code/phoenix-code-experimental-build exist. Dev build detected." - mv "$TMP_DIR/phoenix-code/phoenix-code-experimental-build" "$TMP_DIR/phoenix-code/phoenix-code" - fi + chmod +x "$TMP_DIR/$APPIMAGE_NAME" - # Verify binary execution and install dependencies if necessary - if ! verify_and_install_dependencies; then - echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" - exit 1 - fi + ensure_runtime_dependencies "$TMP_DIR/$APPIMAGE_NAME" } -# Install Function -# -# Purpose: -# Facilitates the entire installation process of Phoenix Code on the user's system. This includes -# checking for previous installations, downloading and installing the latest version, setting up -# necessary directories, and ensuring that all dependencies are met. It also handles user prompts -# for repair or reinstallation options if Phoenix Code is already installed. -# -# Behavior: -# 1. Checks if Phoenix Code is already installed by looking for specific files or directories -# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main -# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). -# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and -# then reinstalls the application, ensuring the user ends up with the latest version. -# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest -# release and install it. This step involves downloading the binary, setting permissions, and -# moving files to their correct locations. -# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, -# create an invocation script, and perform other necessary post-installation configurations. -# -# Considerations: -# - The function assumes that the user has sufficient permissions to write to the target directories -# and install Phoenix Code. Administrative privileges may be required for certain operations. -# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation -# directory will be replaced. Users should ensure that any custom configurations or data are backed up -# before proceeding. -# - Network connectivity is required to download the latest version of Phoenix Code from the repository. -# - The function does not explicitly handle all potential error scenarios, such as download failures or -# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. -# -# Usage: -# This function is intended to be invoked when the script is run without specific options (e.g., not an -# uninstall or upgrade). It can be directly called from the command line when the user wishes to install -# Phoenix Code, or it may be triggered by default when the script is executed without arguments. -# + +# Temporary cleanup for files from older installer versions. +uninstallBetaAppImage() { + rm -f "$LINK_DIR"/phoenix_icon.png +} + install() { - # Check if the application is already installed if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" - - # Simplified prompt for reinstall without detailed explanation - read -r -p "Would you like to reinstall it? (y/N): " response - case "$response" in - [Yy]* ) + if [ ! -t 0 ]; then + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + uninstall + downloadAndInstall + copyFilesToDestination + else + read -r -p "Would you like to reinstall it? (y/N): " response + case "$response" in + [Yy]* ) echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" uninstall downloadAndInstall copyFilesToDestination ;; - * ) + * ) echo -e "${RED}Reinstall aborted by the user.${RESET}" exit 0 ;; - esac + esac + fi else downloadAndInstall copyFilesToDestination fi } -# Temporary code to clean up earlier beta installations -function uninstallBetaAppImage() { - rm -f "$LINK_DIR"/phoenix_icon.png -} -# Upgrade Function -# -# Purpose: -# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated -# to the latest version available. This function checks the currently installed version against -# the latest version available in the GitHub repository. If a newer version is found, it proceeds -# to download and install the update, effectively replacing the old version with the new one. -# -# Behavior: -# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation -# directory and the invocation script. If not found, it exits with an error message indicating that -# Phoenix Code must be installed before it can be upgraded. -# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version -# check command (e.g., `phoenix-code --version`) and captures the output. -# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` -# function, which retrieves the version number of the latest release. -# 4. Compares the currently installed version with the latest version. If the installed version is older, -# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and -# installation of the new version. -# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. -# -# Considerations: -# - The function relies on the correct implementation of version checking in the Phoenix Code binary. -# The binary must support a command-line option to output its version, and the output format must be -# consistent for correct parsing and comparison. -# - Network connectivity is required to fetch the latest release information from the GitHub repository. -# The upgrade process will fail if the script cannot connect to GitHub. -# - The user must have sufficient permissions to overwrite the existing installation files and to -# execute network requests (e.g., downloading the latest release). -# - The upgrade process replaces the existing installation files. Users should ensure that any -# necessary backups or custom configurations are saved before proceeding with the upgrade. -# -# Usage: -# This function is intended to be called when the user explicitly wants to upgrade their installation -# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the -# script, as defined in the script's main case statement handling command-line arguments. -# upgrade() { echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" - # Ensure Phoenix Code is installed if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" exit 1 fi - # Get the current installed version - CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) - echo "Current installed version: $CURRENT_VERSION" - LATEST_VERSION=$(downloadLatestReleaseInfo) - # Now LATEST_VERSION should only contain the version number without extra messages - echo "Latest available version: $LATEST_VERSION" + local current_version + current_version=$("$INSTALL_DIR/$APPIMAGE_NAME" --version 2>/dev/null || true) + echo "Current installed version: ${current_version:-unknown}" + + local latest_version + latest_version=$(downloadLatestReleaseInfo) + echo "Latest available version: $latest_version" - # Compare versions and upgrade if the latest version is greater - if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then + if [ -n "$latest_version" ] && [ "$(printf '%s\n' "$latest_version" "$current_version" | sort -V | tail -n1)" = "$latest_version" ] && [ "$latest_version" != "$current_version" ]; then echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" downloadAndInstall uninstall @@ -659,48 +547,12 @@ upgrade() { else echo "Your Phoenix Code installation is up-to-date." fi - } -# Uninstall Function -# -# Purpose: -# Handles the removal of Phoenix Code from the user's system. This function is responsible for -# cleaning up all files, directories, and links created during the installation process, effectively -# reverting any changes made by the installer script. It ensures that Phoenix Code and its components -# are uninstalled cleanly, leaving no residual files or configurations. -# -# Behavior: -# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). -# This step prevents the Phoenix Code command from being accessible after uninstallation. -# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus -# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. -# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. -# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. -# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including -# the main binary, configuration files, and any other related files placed during installation. -# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. -# -# Considerations: -# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately -# reflect the locations used during the installation. If these variables are incorrect, the uninstallation -# process may not remove all components. -# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed -# in system-wide directories. -# - Users should be advised to back up any important data or configurations related to Phoenix Code before -# initiating the uninstallation process, as this function will remove all associated files without recovery options. -# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot -# be reversed through this script. -# -# Usage: -# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. -# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement -# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this -# function is executed to prevent accidental data loss. -# + uninstall() { echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" uninstallBetaAppImage - # Remove the invocation script from ~/.local/bin + if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" rm "$LINK_DIR/$SCRIPT_NAME" @@ -708,34 +560,33 @@ uninstall() { echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" fi - # Delete the desktop entry if [ -f "$DESKTOP_ENTRY" ]; then echo -e "${YELLOW}Removing desktop entry...${RESET}" rm "$DESKTOP_ENTRY" - - # Update the desktop database for GNOME, Unity, XFCE, etc. - echo -e "${YELLOW}Updating desktop database...${RESET}" if command -v update-desktop-database &> /dev/null; then - update-desktop-database "$DESKTOP_DIR" + update-desktop-database "$DESKTOP_DIR" fi - - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 - fi + if [ "${XDG_CURRENT_DESKTOP:-}" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi + fi + if [[ "${XDG_CURRENT_DESKTOP:-}" =~ LXQt ]]; then + if command -v xdg-desktop-menu &> /dev/null; then + xdg-desktop-menu forceupdate + fi fi else - echo -e "${RED}Desktop entry not found. Skipping...${RESET}" + echo -e "${RED}Desktop entry not found. Skipping...${RESET}" fi - # Remove the installation directory and its contents if [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" rm -rf "$INSTALL_DIR" else echo -e "${RED}Installation directory not found. Skipping...${RESET}" fi + echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" } @@ -750,7 +601,7 @@ show_help() { echo echo "Without any options, the script will install Phoenix Code." } -# Check for GUI session by looking for DISPLAY or WAYLAND_DISPLAY variables + if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then echo "This script should only be run from terminals in GUI sessions." exit 1 @@ -758,22 +609,20 @@ fi case "${1-}" in -h|--help) - show_help # Function to show help + show_help ;; --uninstall) - uninstall # Function to uninstall + uninstall ;; --upgrade) - upgrade # Function to upgrade + upgrade ;; "") - # This case handles when $1 is unset (acts as a default action) - install # Function to install + install ;; *) - # This case handles unexpected arguments echo "Invalid option: $1" >&2 - show_help # Assuming you have a function to show usage information + show_help exit 1 ;; esac From 6c6063f11d752bde98646749ccf0c820e080410f Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 18 May 2026 09:53:32 +0530 Subject: [PATCH 836/864] revert installer for testing in deployed builds --- docs/linux/installer.sh | 1132 +++++++++++------ .../update-latest-experimental-build.json | 2 +- 2 files changed, 772 insertions(+), 362 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 8c442ddc..87f8b54e 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,40 +1,25 @@ #!/bin/bash -set -euo pipefail - -# Phoenix Code Linux installer. -# -# Downloads the latest Phoenix Code AppImage from the update JSON, then probes -# the downloaded AppImage with `--version` (early-exit handler at -# src-electron/main.js:23-26). If the probe succeeds, no apt/dnf/pacman install -# is attempted — the system already has every shared library Phoenix Code -# needs at startup, regardless of which package name provides it. -# -# Beyond the --version probe, the installer also checks for the gnome-keyring -# daemon binary — libsecret needs the daemon for keytar credential storage, -# and --version exits before keytar is require()d. Sudo is only requested if -# libs or the keyring daemon are actually missing. -# -# On Ubuntu 24.04+ / Debian 13+, Chromium's unprivileged userns sandbox can -# be blocked by the kernel sysctl. The app still launches because the wrapper -# script falls back to --no-sandbox; we no longer install an AppArmor profile -# to keep the kernel sandbox enabled (the renderer-RCE-to-syscall threat the -# kernel sandbox guards against is narrow, and Phoenix Code's actual attack -# surface flows through the IPC bridge which the kernel sandbox doesn't gate). -# -# Also wires up a desktop entry + `phcode` wrapper script that handles -# AppImage launch fallbacks. - -DESKTOP_DIR=$HOME/.local/share/applications -UPDATE_JSON_URL="https://updates.phcode.io/tauri/update-latest-experimental-build.json" +set -euo pipefail # Exit immediately if a command exits with a non-zero status. +# Define common variables +DESKTOP_DIR=$HOME/.local/share/applications # Directory for desktop entries +GITHUB_REPO="phcode-dev/phoenix-desktop" +API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" +GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/gtk.tar.xz" +WEBKIT2GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/webkit2gtk-4.0.tar.xz" INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" DESKTOP_ENTRY_NAME="PhoenixCode.desktop" DESKTOP_APP_NAME="Phoenix Code" DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" -SCRIPT_NAME="phcode" +SCRIPT_NAME="phcode" # Name of the script to invoke the binary BINARY_NAME="phoenix-code" -APPIMAGE_NAME="phoenix-code.AppImage" +# STARTUP_WM_CLASS is set to the binary name and used as the application's class name in the desktop file. +# This class name helps the desktop environment manage application windows. If native libraries are missing +# and the application needs to be launched via a script instead of directly, this variable is updated +# accordingly before the desktop file is created. +STARTUP_WM_CLASS=$BINARY_NAME + declare -a MIME_TYPES=( "text/html" @@ -63,310 +48,460 @@ declare -a MIME_TYPES=( "text/cjs" ) + +# Define color variables for easy reference GREEN="\e[32m" YELLOW="\e[33m" RED="\e[31m" RESET="\e[0m" +# Cleanup Function +# +# Purpose: +# The cleanup function is designed to ensure that the script cleans up any temporary +# resources it used during its execution. Specifically, it removes the temporary directory +# created at the beginning of the script, along with all its contents. This is crucial for +# maintaining a clean file system and avoiding the accumulation of unused files. +# +# Behavior: +# - The function targets a temporary directory specified by the `$TMP_DIR` variable. +# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. +# This includes any temporary files, downloaded assets, or other data generated during the script's execution. +# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes +# automatically when the script exits, regardless of the exit point. This includes normal completion, +# errors, or manual termination via signals like SIGINT (Ctrl+C). +# +# Considerations: +# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. +# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. +# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` +# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. +# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within +# `$TMP_DIR` is expendable and safe to delete. +# +# Usage: +# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` +# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` +# is correctly set to the temporary directory path before invoking the function. +# cleanup() { - rm -rf "$TMP_DIR" -} -# Surface user interrupts (Ctrl+C / kill) with a clear message and exit 130, -# while still running cleanup. Without this, dpkg unpacks and sudo prompts can -# make the script look unresponsive to SIGINT for a beat. -on_interrupt() { - echo - echo -e "${RED}Interrupted by user. Cleaning up...${RESET}" - cleanup - exit 130 -} -trap cleanup EXIT -trap on_interrupt INT TERM - -TMP_DIR=$(mktemp -d) - -configure_wget_options() { - local wget_version - wget_version=$(wget --version | head -n1 | awk '{print $3}') - local major_version - major_version=$(echo "$wget_version" | cut -d. -f1) - - if [[ "$major_version" -ge 2 ]]; then - echo "-c --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" - else - echo "-c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO" - fi + rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. } -check_architecture() { - local arch - arch=$(uname -m) - if [ "$arch" != "x86_64" ]; then - echo -e "${RED}This installer only supports 64-bit x86 (x86_64). Detected: $arch.${RESET}" - exit 1 - fi -} +trap cleanup EXIT # Register the cleanup function to be called on script exit. -# Runtime-library probe: ask the AppImage to print its version and exit. This -# is handled at src-electron/main.js:23-26, but `require('electron')` runs -# before that handler — which means Chromium initializes its sandbox bits even -# for --version. On Ubuntu 24.04+ / Debian 13+ where unprivileged user -# namespaces are restricted, that init can SIGTRAP. Pass --no-sandbox so the -# probe isolates to "are the system shared libraries present and loadable?" -# regardless of the kernel's userns policy. -# -# The `{ … } 2>/dev/null` wrapper suppresses bash's own "Trace/breakpoint trap -# (core dumped)" report when the subprocess dies on signal — those messages -# look alarming but are harmless: we already detect failure via the exit code. -verify_appimage_launches() { - { "$1" --no-sandbox --version >/dev/null 2>&1; } 2>/dev/null -} -# Returns 0 if the gnome-keyring secret-service daemon binary is on PATH. -# `--version` can't test this because keytar is only require()d at first use, -# so we need an independent presence check. -gnome_keyring_present() { - command -v gnome-keyring-daemon >/dev/null 2>&1 -} +TMP_DIR=$(mktemp -d) -downloadLatestReleaseInfo() { - local release_info_file="$TMP_DIR/latest_release.json" - if [ ! -f "$release_info_file" ]; then - >&2 echo -e "${GREEN}Fetching the latest release information...${RESET}" - wget -qO "$release_info_file" "$UPDATE_JSON_URL" || { - >&2 echo -e "${RED}Failed to fetch release info from $UPDATE_JSON_URL. Check your internet connection.${RESET}" - exit 1 - } - fi - grep -Po '"version"\s*:\s*"\K[^"]+' "$release_info_file" | head -n1 -} +# Check OS Version Function +# +# Purpose: +# This function checks if the current operating system is Ubuntu 24.04, Linux Mint 22, or Kali Linux 2024.2 or newer. +# It reads the /etc/os-release file, which contains identification data for the operating system. +# +# Behavior: +# 1. The function first checks if the /etc/os-release file exists. +# 2. If the file exists, it sources the file to load the OS identification variables. +# 3. It then checks if: +# - The ID variable is set to "ubuntu" and the VERSION_ID variable is "24.04", +# - The ID variable is "linuxmint" and the VERSION_ID is "22", +# - The ID variable is "kali" and the VERSION_ID is "2024.2" or newer. +# 4. If any of these conditions are met, the function returns 0 (indicating success). +# 5. If none of these conditions are met, the function returns 1 (indicating failure). +# +# Usage: +# This function can be called to determine if special handling is needed for these specific versions of +# Ubuntu, Linux Mint, or Kali Linux, such as installing additional libraries or making compatibility adjustments. +# +# Example: +# if check_os_version; then +# echo "Supported OS version detected." +# else +# echo "Unsupported OS version." +# fi +# +# Notes: +# - This function assumes that the /etc/os-release file follows the standard format for Linux OS +# identification and that the distribution's identifiers are consistent with those specified in the script. -# Parses the linux-x86_64 download URL out of the update JSON without needing jq. -getLinuxAppImageUrl() { - awk ' - /"linux-x86_64"[[:space:]]*:/ { in_linux=1 } - in_linux && /"url"[[:space:]]*:/ { - if (match($0, /"url"[[:space:]]*:[[:space:]]*"[^"]+"/)) { - s = substr($0, RSTART, RLENGTH) - sub(/^"url"[[:space:]]*:[[:space:]]*"/, "", s) - sub(/"$/, "", s) - print s - exit - } - } - ' "$TMP_DIR/latest_release.json" +check_os_version() { + if [ -f /etc/os-release ]; then + . /etc/os-release + # Set VERSION_ID to empty string if not defined (for rolling releases) + VERSION_ID="${VERSION_ID:-}" + # Define supported OS and version combinations + case "$ID:${VERSION_ID%%.*}" in # Extract major version number + ubuntu:24) # Ubuntu 24.x + return 0 + ;; + ubuntu:25) # Ubuntu 25.x + return 0 + ;; + linuxmint:22) # Linux Mint 22.x + return 0 + ;; + neon:24) # KDE Neon 24.x + return 0 + ;; + debian:13) # Debian 13.x (Trixie) + return 0 + ;; + kali:2024|kali:20[2-9][0-9]) # Kali 2024.x or newer + return 0 + ;; + esac + fi + return 1 } -# Generates the `phcode` wrapper script. The wrapper runs the AppImage directly, -# falling back to --appimage-extract-and-run on FUSE failure or to --no-sandbox -# on userns/AppArmor failure (Ubuntu 24.04+ / Debian 13+ blocks Chromium's -# unprivileged user namespace sandbox unless our AppArmor profile is loaded). +# Create Invocation Script Function +# +# Purpose: +# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. +# This script is intended to simplify the execution of Phoenix Code by providing a more accessible +# command interface. The generated script is placed in a user-accessible binary directory, making it +# possible to run Phoenix Code from anywhere in the system without needing to specify the full path +# to the binary. +# +# Parameters: +# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. +# - script_name: The name to be given to the invocation script. This name is used both for the +# script file itself and for the symlink created in the user's binary directory. +# - link_dir: The directory where a symlink to the invocation script will be placed, typically +# a location in the user's PATH, such as ~/.local/bin, for easy access. +# +# Behavior: +# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. +# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a +# command to execute the Phoenix Code binary with any passed arguments ("$@"). +# 3. Sets executable permissions on the newly created script. +# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. +# +# Considerations: +# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' +# does not conflict with existing files in these directories to prevent unintended overwrites. +# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes +# these directories are already created and accessible. +# - The generated script includes a warning comment advising against deletion, as it is +# essential for the proper functioning of Phoenix Code when invoked through this script. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# after the binary has been placed in its final location. It should not be called arbitrarily, as it +# assumes a specific setup and context established by the installer script. +# create_invocation_script() { - local install_dir="$1" + local binary_path="$1" local script_name="$2" local link_dir="$3" - echo "Creating an invocation script for the AppImage..." - cat > "$install_dir/$script_name" <"\$ERR"; then - if grep -qiE 'fuse|libfuse|fusermount|/dev/fuse' "\$ERR"; then - rm -f "\$ERR" - exec "\$APPIMAGE" --appimage-extract-and-run "\$@" - fi - if grep -qiE 'userns|apparmor|sandbox|setuid|namespace|Check failed' "\$ERR"; then - rm -f "\$ERR" - exec "\$APPIMAGE" --no-sandbox "\$@" - fi - cat "\$ERR" >&2 - rm -f "\$ERR" - exit 1 -fi -rm -f "\$ERR" -EOF - chmod +x "$install_dir/$script_name" + echo "Creating an invocation script for the binary..." + # Start of the generated script + echo "#!/bin/bash" > "$binary_path/$script_name.sh" + # Add a warning comment about the script being auto-generated + echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" + echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" + chmod +x "$binary_path/$script_name" + + echo "Copying the invocation script to $link_dir..." + mkdir -p "$link_dir" # Ensure the directory exists + cp "$binary_path/$script_name" "$link_dir/$script_name" - mkdir -p "$link_dir" - cp "$install_dir/$script_name" "$link_dir/$script_name" echo -e "Invocation script created at: $link_dir/$script_name" } +# Install Dependencies Function +# +# Purpose: +# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. +# This function identifies the user's Linux distribution and installs the appropriate packages +# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and +# Arch Linux distributions. +# +# Behavior: +# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. +# If the command fails, it prompts the user to enter their password for `sudo` access. +# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. +# 3. Based on the identified distribution, executes the appropriate package manager command +# with the required packages. Supported package managers are `apt` for Debian-based systems, +# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. +# 4. Updates the package index (if applicable) and installs the packages. +# +# Considerations: +# - The function requires internet access to fetch package information and install packages. +# - It assumes that the user has `sudo` privileges to install packages system-wide. +# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, +# this function must be updated accordingly. +# - Unsupported distributions will result in an error message and termination of the script, +# as the required dependencies cannot be installed automatically. +# - This function does not handle potential errors from package installation commands. It's +# recommended to monitor the output for any issues that may require manual intervention. +# +# Usage: +# This function is intended to be called during the Phoenix Code installation process, typically +# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites +# are met for a successful Phoenix Code execution. +# +install_dependencies() { + echo "Attempting to install required dependencies..." -# Returns "gnome-keyring" unless the current session is KDE. -# On KDE, kwallet implements the Secret Service interface (KF 5.97+ / ksecretd -# in 2026), and installing gnome-keyring causes a D-Bus activation race for -# org.freedesktop.secrets — see VSCode issue #189672. -gnome_keyring_pkg_if_needed() { - if [[ "${XDG_CURRENT_DESKTOP:-}" =~ KDE ]]; then - echo "" - else - echo "gnome-keyring" + # Inform the user that the next steps require administrative access + echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." + + # Check if the script can execute sudo commands without interaction + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed with the installation of dependencies." fi -} -# Picks the libfuse2 package name for whatever Ubuntu/Debian release we're on. -# Ubuntu 24.04 Noble+ / Debian 13 Trixie+ / Kali rolling / Mint 22+ / Neon 24+ -# ship libfuse2t64 (the post-y2038 rename); older releases (Ubuntu 20.04 Focal -# / 22.04 Jammy, Debian 11/12, Mint 20/21, Neon 22) ship the pre-rename -# libfuse2. Both provide the same libfuse.so.2 SONAME, so picking by repo -# availability is correct. -choose_fuse_package_apt() { - if apt-cache show libfuse2t64 >/dev/null 2>&1; then - echo libfuse2t64 + # Attempt to identify the Linux distribution + if [ -f /etc/os-release ]; then + . /etc/os-release + DISTRO=$ID else - echo libfuse2 + echo "Unable to identify the operating system." + exit 1 fi -} -# Per-distro package install. Only called when verify_appimage_launches failed -# OR the keyring daemon is missing — i.e., we've already decided we need sudo. -install_packages_for_distro() { - local distro="$1" keyring="$2" - # RHEL 10 does not ship libXScrnSaver in any default channel — left off the - # dnf list intentionally; Electron's XScreenSaver calls no-op on Wayland. - # libxss + libnotify are listed for Arch because gtk3 does NOT pull them in - # transitively but Electron dlopen's them at runtime. - local -a pkgs=() - case "$distro" in - ubuntu|debian|linuxmint|kali|neon) pkgs=("$(choose_fuse_package_apt)" libsecret-1-0) ;; - fedora|rhel|centos) pkgs=(fuse-libs fuse3-libs libsecret) ;; - arch|manjaro|cachyos) pkgs=(fuse2 libsecret libxss libnotify) ;; - esac - [ -n "$keyring" ] && pkgs+=("$keyring") - - case "$distro" in - ubuntu|debian|linuxmint|kali|neon) - # No `yes |` pipeline: under `set -o pipefail`, `yes` dies of SIGPIPE - # after apt exits and the pipeline returns 141, silently aborting the - # installer. Use apt-get -y, and keep user /etc config files via the - # force-conf* options so an unrelated pending upgrade can't prompt. - echo "Detected an Ubuntu/Debian-based distribution." - sudo apt-get update - # shellcheck disable=SC2068 - sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ - -o Dpkg::Options::="--force-confdef" \ - -o Dpkg::Options::="--force-confold" \ - ${pkgs[@]} + # Install dependencies based on the distribution + case "$DISTRO" in + ubuntu|debian|linuxmint|kali) + echo "Detected an Ubuntu/Debian based distribution." + sudo apt update + yes | sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + gstreamer1.0-tools ;; fedora|rhel|centos) - echo "Detected a Fedora/Red Hat-based distribution." - # shellcheck disable=SC2068 - sudo dnf install -y ${pkgs[@]} + echo "Detected a Fedora/Red Hat based distribution." + yes | sudo dnf install webkit2gtk3 gtk3 \ + gstreamer1-plugins-base gstreamer1-plugins-good + yes | sudo dnf upgrade webkit2gtk3 gtk3 \ + gstreamer1 gstreamer1-plugins-base gstreamer1-plugins-good ;; arch|manjaro|cachyos) - echo "Detected an Arch-based distribution." + echo "Detected an Arch Linux based distribution." + echo "Updating package database..." sudo pacman -Sy - # shellcheck disable=SC2068 - sudo pacman -S --noconfirm --needed ${pkgs[@]} + yes | sudo pacman -S webkit2gtk gtk3 libxml2 + ;; + *) + echo "Unsupported distribution. Please manually install the required dependencies." + exit 1 ;; esac } +download_and_install_gtk() { + # Function: create_launch_script_with_gtk + # + # Purpose: + # This function creates a launch script for the Phoenix Code application that sets the required + # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that + # the Phoenix Code application uses the correct GTK libraries, which are included in the + # application's installation directory. + # + # Parameters: + # - binary_path: The path to the directory containing the Phoenix Code binary. + # - binary_name: The name of the Phoenix Code binary file. + # + # Behavior: + # 1. The function renames the original Phoenix Code binary to append ".real" to its name. + # 2. It then creates a new launch script with the original binary name in the same directory. + # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the + # GTK libraries located in the same directory as the binary. + # 4. The launch script executes the original Phoenix Code binary (now renamed) with any + # arguments passed to the script. + # 5. The function sets the appropriate executable permissions on the launch script. + # + # Usage: + # This function should be called after the Phoenix Code binary and its required GTK libraries + # have been installed. It ensures that the application uses the correct libraries when launched. + # + # Example: + # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" + # + # Notes: + # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within + # the same directory as the Phoenix Code binary. + # - The function requires the mv, chmod, and cat commands to be available in the environment. + # - This piece of code should only be executed if the package manager does not distribute + # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. -# Decides what (if anything) the user's system is missing for Phoenix Code to -# run, then installs only the missing piece(s). Three independent probes: -# -# 1. System shared libraries — probed by running the downloaded AppImage -# with `--version`. main.js exits immediately on this flag, AFTER libfuse -# mounts the AppImage and AFTER the Electron binary loads its NEEDED libs. -# 2. gnome-keyring daemon — binary-presence check; `--version` doesn't -# exercise keytar so it can't verify libsecret/Secret Service end-to-end. -# -# Sudo is requested ONLY if at least one of the probes fails. -ensure_runtime_dependencies() { - local appimage="$1" - if [ ! -f /etc/os-release ]; then - echo -e "${RED}Unable to identify the operating system (no /etc/os-release).${RESET}" + local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.5/" + local GTK_FILE="gtk.tar.xz" + local WEBKIT2GTK_FILE="webkit2gtk-4.0.tar.xz" + + local GTK_URL="${URL_PREFIX}${GTK_FILE}" + local WEBKIT2GTK_URL="${URL_PREFIX}${WEBKIT2GTK_FILE}" + + echo -e "${YELLOW}Downloading GTK from $GTK_URL...${RESET}" + local destination="$TMP_DIR/$BINARY_NAME" + WGET_OPTS=$(configure_wget_options) + + wget $WGET_OPTS "$TMP_DIR/gtk.tar.xz" "$GTK_URL" || { + echo -e "${RED}Failed to download GTK. Please check your internet connection and try again.${RESET}" exit 1 - fi - . /etc/os-release - local distro="${ID:-}" - case "$distro" in - ubuntu|debian|linuxmint|kali|neon|fedora|rhel|centos|arch|manjaro|cachyos) ;; - *) - echo -e "${RED}Unsupported distribution: $distro. Please install libfuse2/fuse2, libsecret, and (on non-KDE) gnome-keyring manually.${RESET}" + } + echo "Extracting GTK..." + tar -xJf "$TMP_DIR/$GTK_FILE" -C "$destination" || { + echo -e "${RED}Failed to extract GTK. The downloaded file might be corrupt.${RESET}" + exit 1 + } + + if [ ! -d "/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0" ]; then + echo -e "${YELLOW}Downloading WebKit2GTK from $WEBKIT2GTK_URL...${RESET}" + wget $WGET_OPTS "$TMP_DIR/$WEBKIT2GTK_FILE" "$WEBKIT2GTK_URL" || { + echo -e "${RED}Failed to download WebKit2GTK. Please check your internet connection and try again.${RESET}" exit 1 - ;; - esac - local keyring; keyring=$(gnome_keyring_pkg_if_needed) + } + echo "Extracting WebKit2GTK..." + tar -xJf "$TMP_DIR/$WEBKIT2GTK_FILE" -C "$TMP_DIR" || { + echo -e "${RED}Failed to extract WebKit2GTK. The downloaded file might be corrupt.${RESET}" + exit 1 + } - local libs_ok=1 keyring_ok=1 - verify_appimage_launches "$appimage" || libs_ok=0 - if [ -n "$keyring" ] && ! gnome_keyring_present; then keyring_ok=0; fi + # Inform the user that the next steps require administrative access + echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." - if [ "$libs_ok" = 1 ] && [ "$keyring_ok" = 1 ]; then - echo -e "${GREEN}All runtime dependencies already present.${RESET}" - return 0 - fi + # Check if the script can execute sudo commands without interaction + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed with the installation of dependencies." + fi - if [ "$libs_ok" = 0 ]; then - echo "Installing missing runtime libraries..." + echo "Installing WebKit2GTK..." + sudo cp -r "$TMP_DIR/webkit2gtk-4.0" /usr/lib/x86_64-linux-gnu/ || { + echo -e "${RED}Failed to install WebKit2GTK. Please check the permissions and try again.${RESET}" + exit 1 + } + echo -e "${GREEN}WebKit2GTK installed successfully.${RESET}" else - echo "Installing system keychain daemon..." - fi - echo "This step requires administrative access." - if ! sudo -n true 2>/dev/null; then - echo "Please enter your password to proceed." - fi - - install_packages_for_distro "$distro" "$keyring" - # Re-probe libraries; if still failing, surface a clear warning but don't - # abort — the AppImage may have a runtime-specific issue we can't fix here. - if [ "$libs_ok" = 0 ] && ! verify_appimage_launches "$appimage"; then - echo -e "${YELLOW}WARN: AppImage still fails --version after dep install.${RESET}" + echo -e "${GREEN}WebKit2GTK already installed.${RESET}" fi } -# Returns 0 if any of the common display managers is configured to autologin -# the current user. All probed files are world-readable; no sudo, no prompts. -# Used only to enrich the post-install keyring hint with a probable cause. -autologin_detected() { - local user="${USER:-$(id -un)}" - local f - for f in /etc/gdm3/custom.conf /etc/gdm3/daemon.conf /etc/gdm/custom.conf; do - [ -r "$f" ] && grep -qE '^[[:space:]]*AutomaticLoginEnable[[:space:]]*=[[:space:]]*[Tt]rue' "$f" && return 0 - done - for f in /etc/lightdm/lightdm.conf /etc/lightdm/lightdm.conf.d/*.conf; do - [ -r "$f" ] && grep -qE "^[[:space:]]*autologin-user[[:space:]]*=[[:space:]]*${user}([[:space:]]|$)" "$f" && return 0 - done - for f in /etc/sddm.conf /etc/sddm.conf.d/*.conf; do - [ -r "$f" ] && grep -qE "^[[:space:]]*User[[:space:]]*=[[:space:]]*${user}([[:space:]]|$)" "$f" && return 0 - done - return 1 + +create_launch_script_with_gtk() { + # Function: create_launch_script_with_gtk + # + # Purpose: + # This function creates a launch script for the Phoenix Code application that sets the required + # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that + # the Phoenix Code application uses the correct GTK libraries, which are included in the + # application's installation directory. + # + # Parameters: + # - binary_path: The path to the directory containing the Phoenix Code binary. + # - binary_name: The name of the Phoenix Code binary file. + # + # Behavior: + # 1. The function renames the original Phoenix Code binary to append ".real" to its name. + # 2. It then creates a new launch script with the original binary name in the same directory. + # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the + # GTK libraries located in the same directory as the binary. + # 4. The launch script executes the original Phoenix Code binary (now renamed) with any + # arguments passed to the script. + # 5. The function sets the appropriate executable permissions on the launch script. + # + # Usage: + # This function should be called after the Phoenix Code binary and its required GTK libraries + # have been installed. It ensures that the application uses the correct libraries when launched. + # + # Example: + # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" + # + # Notes: + # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within + # the same directory as the Phoenix Code binary. + # - The function requires the mv, chmod, and cat commands to be available in the environment. + # - This piece of code should only be executed if the package manager does not distribute + # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. + + local binary_path="$1" + local binary_name="$BINARY_NAME" + local original_bin=$binary_name.app + local realBin="$binary_path/$original_bin" + mv "$binary_path/$binary_name" "$realBin" + echo "Creating a launch script for Phoenix Code with GTK libraries..." + cat > "$binary_path/$binary_name" </dev/null 2>&1 || return 0 - local locked - locked=$(busctl --user --no-pager call org.freedesktop.secrets \ - /org/freedesktop/secrets/collection/login \ - org.freedesktop.DBus.Properties Get \ - ss org.freedesktop.Secret.Collection Locked 2>/dev/null \ - | awk '/^b /{print $NF}') - [ "$locked" = "true" ] || return 0 +# Verify and Install Dependencies Function +# +# Purpose: +# This function is responsible for verifying if the Phoenix Code application can be successfully +# launched with the current set of installed dependencies. If the initial verification fails, it +# attempts to install the necessary dependencies and then re-verifies the application launch. +# +# Behavior: +# 1. Changes the current directory to the temporary directory where Phoenix Code is located. +# 2. Sets the executable permission for the Phoenix Code binary and attempts to run it with a +# verification-specific command (e.g., `--runVerify`). This step is intended to check if the +# application can start without installing additional dependencies. +# 3. If the initial verification succeeds, the function exits with a success status (0), indicating +# no further action is needed. +# 4. If the initial verification fails, the function proceeds to invoke `install_dependencies` to +# install any missing dependencies specific to the user's Linux distribution. +# 5. After installing dependencies, it attempts to verify the application launch again. If this +# second attempt succeeds, the function exits with a success status (0). +# 6. If the verification fails even after installing dependencies, the function prints an error +# message advising the user to check the application requirements or contact support, and +# exits with an error status (1). +# 7. Finally, the function ensures to change back to the original directory where the script was +# invoked, preserving the user's shell environment. +# +# Considerations: +# - The function assumes that the Phoenix Code binary is located in a temporary directory and +# that this directory is correctly set in the `$TMP_DIR` variable. +# - It relies on the Phoenix Code binary supporting a `--runVerify` command or equivalent for +# verification purposes. If such a command is not available, this part of the function needs +# adjustment. +# - Dependency installation requires administrative privileges; hence, the user might be prompted +# for a password to allow `sudo` operations. +# - The function does not handle all possible error scenarios during dependency installation. +# Users should monitor the output for potential issues that might need manual intervention. +# +# Usage: +# This function is intended to be called during the installation or upgrade process of Phoenix Code, +# before finalizing the installation, to ensure that all system requirements are met for the +# application to run properly. +# +verify_and_install_dependencies() { + if "$TMP_DIR/phoenix-code/phoenix-code" --runVerify; then + echo "Application launch verification successful." + return 0 + else + if check_os_version; then + echo -e "${YELLOW}Ubuntu 24.04 detected. Attempting to download and install GTK and WebKit2GTK...${RESET}" + download_and_install_gtk + create_launch_script_with_gtk "$TMP_DIR/phoenix-code" + else + echo "Initial verification failed. Attempting to install dependencies..." + install_dependencies + fi + fi - echo - echo -e "${YELLOW}Note: your system keychain is currently locked.${RESET}" - echo -e "${YELLOW}The first time Phoenix Code stores or reads a credential, gnome-keyring${RESET}" - echo -e "${YELLOW}will ask once for your login password to unlock it. This is a one-time${RESET}" - echo -e "${YELLOW}per-session Linux behavior — not a Phoenix Code prompt.${RESET}" - if autologin_detected; then - echo -e "${YELLOW}(Autologin is enabled on this machine, which is why PAM did not${RESET}" - echo -e "${YELLOW} auto-unlock the keyring at session start.)${RESET}" + if "$TMP_DIR/phoenix-code/phoenix-code" --runVerify; then + echo "Application launch verification successful after installing dependencies." + return 0 + else + echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." + return 1 fi } - +# Set Phoenix Code as the default application for specified MIME types set_default_application() { - local desktop_file="$DESKTOP_ENTRY_NAME" + local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file + # Dynamically detect qtpaths if KDE is running and qtpaths is not in PATH if [ "${KDE_SESSION_VERSION:-0}" -gt 0 ] && ! command -v qtpaths &> /dev/null; then + # Common locations where qtpaths might be installed local qtpaths_locations=( "/usr/lib/qt6/bin" "/usr/lib/qt5/bin" @@ -375,6 +510,7 @@ set_default_application() { "/opt/qt6/bin" "/opt/qt5/bin" ) + for qtpath_dir in "${qtpaths_locations[@]}"; do if [ -x "$qtpath_dir/qtpaths" ] || [ -x "$qtpath_dir/qtpaths6" ]; then export PATH="$qtpath_dir:$PATH" @@ -384,36 +520,82 @@ set_default_application() { fi for mime_type in "${MIME_TYPES[@]}"; do - if [ "$mime_type" = "text/html" ]; then - continue - fi - xdg-mime default "$desktop_file" "$mime_type" + # Skip setting default application for text/html + if [ "$mime_type" = "text/html" ]; then + continue # Skip to the next iteration + fi + + xdg-mime default "$desktop_file" "$mime_type" done echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" } -copyFilesToDestination() { +# Copy Files to Destination Function +# +# Purpose: +# This function is responsible for setting up the final installation directory for Phoenix Code, +# moving the necessary files into place, creating the invocation script, and setting up the desktop +# entry for the application. It ensures that all components of Phoenix Code are correctly installed +# and configured in the user's environment. +# +# Behavior: +# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files +# will reside. +# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. +# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from +# the temporary directory (`$TMP_DIR`) to the installation directory. +# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. +# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. +# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. +# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and +# launchers, and places this file in the desktop entry directory. +# 8. Updates the system's desktop database to ensure the new application entry is recognized and available +# in application menus and launchers. This step might involve commands like `update-desktop-database` +# or `kbuildsycoca5`, depending on the desktop environment. +# +# Considerations: +# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and +# that this directory is correctly set. +# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and +# accessible. If these variables are unset or incorrect, the function may not perform as intended. +# - Administrative privileges may be required for certain operations, such as updating the desktop database +# or setting permissions, depending on the system's configuration. +# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function +# does perform significant file system operations that could potentially conflict with existing user data +# or system settings. +# +# Usage: +# This function is intended to be called as part of the Phoenix Code installation process, after the +# application's binary and other necessary files have been prepared in a temporary location. It finalizes +# the installation by placing all components in their appropriate locations within the user's system. +# +copyFilesToDestination(){ echo "Setting up the installation directory at $INSTALL_DIR..." mkdir -p "$INSTALL_DIR" mkdir -p "$DESKTOP_DIR" + echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" - mv "$TMP_DIR/$APPIMAGE_NAME" "$INSTALL_DIR/$APPIMAGE_NAME" || { - echo -e "${RED}Failed to move the AppImage to the installation directory. Please check the permissions and try again.${RESET}" + echo "Moving the necessary files to the installation directory..." + echo -e "Phoenix Code files moved to: $INSTALL_DIR" + mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { + echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" exit 1 } + # Move the icon to the installation directory mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" - chmod +x "$INSTALL_DIR/$APPIMAGE_NAME" || { - echo -e "${RED}Failed to set executable permissions on the AppImage.${RESET}" + echo "Setting the correct permissions for the executable..." + chmod +x "$INSTALL_DIR/phoenix-code" || { + echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" exit 1 } - echo -e "AppImage installed at: $INSTALL_DIR/$APPIMAGE_NAME" + echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" - mkdir -p "$LINK_DIR" + mkdir -p "$LINK_DIR" # Ensure the directory exists + # Call the function to create and copy the invocation script create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" - - local mime_types_string - mime_types_string=$(IFS=";"; echo "${MIME_TYPES[*]}") + # Convert MIME types array to semicolon-separated string for the desktop entry + MIME_TYPES_STRING=$(IFS=";"; echo "${MIME_TYPES[*]}") echo "Creating desktop entry..." cat > "$DESKTOP_ENTRY" < /dev/null; then - update-desktop-database "$DESKTOP_DIR" + update-desktop-database "$DESKTOP_DIR" + echo -e "Desktop database updated in: $DESKTOP_DIR" fi - if [ "${XDG_CURRENT_DESKTOP:-}" = "KDE" ]; then + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 + kbuildsycoca5 fi fi - if [[ "${XDG_CURRENT_DESKTOP:-}" =~ LXQt ]]; then + + if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then if command -v xdg-desktop-menu &> /dev/null; then - xdg-desktop-menu forceupdate - echo -e "${YELLOW}Please log out and log back in to see Phoenix Code in the panel.${RESET}" + xdg-desktop-menu forceupdate + echo -e "${YELLOW}Please log out and log back in to see Phoenix Code in the panel.${RESET}" else - echo -e "${RED}Failed to update LXQt menu. Please log out and log back in to see Phoenix Code in the panel.${RESET}" + echo -e "${RED}Failed to update LXQt menu. Please log out and log back in to see Phoenix Code in the panel.${RESET}" fi fi - + # Set Phoenix Code as the default application for the MIME types set_default_application echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" - print_keyring_hint_if_locked + +} + +downloadLatestReleaseInfo() { + local release_info_file="$TMP_DIR/latest_release.json" + + if [ -f "$release_info_file" ]; then + # Only extract and echo the version number, without any additional messages + grep -Po '"tag_name":\s*"prod-app-v\K[\d.]+(?=")' "$release_info_file" + return + fi + + # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly + >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" + wget -qO "$release_info_file" "$API_URL" || { + >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" + exit 1 + } + + # Only extract and echo the version number after successful download + grep -Po '"tag_name":\s*"prod-app-v\K[\d.]+(?=")' "$release_info_file" } -downloadAndInstall() { +# Function to check if the architecture is 64-bit x86 +check_architecture() { + ARCHITECTURE=$(uname -m) + if [ "$ARCHITECTURE" != "x86_64" ]; then + local latestFileUrl + latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") + WGET_OPTS=$(configure_wget_options) + wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { + echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" + } + echo -e "${RED}This script can only be run on 64-bit x86 architecture.${RESET}" + exit 1 + fi +} +# Download Latest Release Information Function +# +# Purpose: +# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function +# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to +# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. +# +# Behavior: +# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary +# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already +# been fetched and proceeds to extract the version number from this file without re-downloading. +# 2. If the release information file does not exist, the function uses `wget` to download the JSON data +# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint +# of the Phoenix Code GitHub repository. +# 3. The JSON data is saved to `latest_release.json` in the temporary directory. +# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular +# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version +# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number +# portion. +# 5. Echoes the extracted version number for use by the calling context. +# +# Considerations: +# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available +# in the execution environment. +# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code +# repository for this function to work as intended. +# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, +# the `grep` pattern used to extract the version number may need to be updated. +# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an +# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the +# latest release information. +# - The function does not perform error handling for the `wget` command. If the download fails, the script may +# exit or behave unexpectedly depending on the `set -e` setting. +# +# Usage: +# This function is intended to be called during the installation or upgrade process to determine the latest +# version of Phoenix Code. The extracted version number can be used to compare with the currently installed +# version and decide whether an upgrade is necessary. +# +downloadAndInstall(){ echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null check_architecture + CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') + echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" + + BEST_MATCH_URL="" + BEST_MATCH_VERSION=0 + echo "Searching for a compatible binary..." + + while read -r BINARY_URL; do + BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') + if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then + BEST_MATCH_URL="$BINARY_URL" + BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" + echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" + fi + done < <(grep -oP '"browser_download_url"\s*:\s*"\K[^"]*_linux_bin-GLIBC-[\d\.]+\.tar\.gz(?=")' "$TMP_DIR/latest_release.json") - local appimage_url - appimage_url=$(getLinuxAppImageUrl) - if [ -z "$appimage_url" ]; then - echo -e "${RED}Could not find a linux-x86_64 AppImage URL in the release info.${RESET}" + if [ -z "$BEST_MATCH_URL" ]; then + echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" exit 1 fi - echo -e "${YELLOW}Downloading the AppImage from $appimage_url...${RESET}" - local wget_opts - wget_opts=$(configure_wget_options) - # shellcheck disable=SC2086 - wget $wget_opts "$TMP_DIR/$APPIMAGE_NAME" "$appimage_url" || { - echo -e "${RED}Failed to download the AppImage. Please check your internet connection and try again.${RESET}" + echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" + # Set options based on wget version + WGET_OPTS=$(configure_wget_options) + + wget $WGET_OPTS "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { + echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" exit 1 } - echo "Downloading the icon..." - # shellcheck disable=SC2086 - wget $wget_opts "$TMP_DIR/icon.png" "$ICON_URL" || { - echo -e "${RED}Failed to download the icon.${RESET}" + # Download the icon + echo -e "Downloading the icon..." + wget $WGET_OPTS "$TMP_DIR/icon.png" "$ICON_URL" || { + echo -e "${RED}Failed to download the icon${RESET}" + exit 1 + } + echo "Extracting the binary to $TMP_DIR..." + tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { + echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" exit 1 } - chmod +x "$TMP_DIR/$APPIMAGE_NAME" - - ensure_runtime_dependencies "$TMP_DIR/$APPIMAGE_NAME" + # Verify binary execution and install dependencies if necessary + if ! verify_and_install_dependencies; then + echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" + exit 1 + fi } +# Function to check wget version and configure options +configure_wget_options() { + local wget_version=$(wget --version | head -n1 | awk '{print $3}') + local major_version=$(echo "$wget_version" | cut -d. -f1) -# Temporary cleanup for files from older installer versions. -uninstallBetaAppImage() { - rm -f "$LINK_DIR"/phoenix_icon.png + if [[ "$major_version" -ge 2 ]]; then + echo "-c --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" + else + echo "-c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO" + fi } - +# Install Function +# +# Purpose: +# Facilitates the entire installation process of Phoenix Code on the user's system. This includes +# checking for previous installations, downloading and installing the latest version, setting up +# necessary directories, and ensuring that all dependencies are met. It also handles user prompts +# for repair or reinstallation options if Phoenix Code is already installed. +# +# Behavior: +# 1. Checks if Phoenix Code is already installed by looking for specific files or directories +# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main +# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). +# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and +# then reinstalls the application, ensuring the user ends up with the latest version. +# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest +# release and install it. This step involves downloading the binary, setting permissions, and +# moving files to their correct locations. +# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, +# create an invocation script, and perform other necessary post-installation configurations. +# +# Considerations: +# - The function assumes that the user has sufficient permissions to write to the target directories +# and install Phoenix Code. Administrative privileges may be required for certain operations. +# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation +# directory will be replaced. Users should ensure that any custom configurations or data are backed up +# before proceeding. +# - Network connectivity is required to download the latest version of Phoenix Code from the repository. +# - The function does not explicitly handle all potential error scenarios, such as download failures or +# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. +# +# Usage: +# This function is intended to be invoked when the script is run without specific options (e.g., not an +# uninstall or upgrade). It can be directly called from the command line when the user wishes to install +# Phoenix Code, or it may be triggered by default when the script is executed without arguments. +# install() { + # Check if the application is already installed if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" + # Checking if the shell has a controlling terminal if its non interactive reinstall phoenix with latest version if [ ! -t 0 ]; then echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" uninstall downloadAndInstall copyFilesToDestination else + # Simplified prompt for reinstall without detailed explanation read -r -p "Would you like to reinstall it? (y/N): " response case "$response" in [Yy]* ) - echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" - uninstall - downloadAndInstall - copyFilesToDestination - ;; + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + uninstall + downloadAndInstall + copyFilesToDestination + ;; * ) - echo -e "${RED}Reinstall aborted by the user.${RESET}" - exit 0 - ;; + echo -e "${RED}Reinstall aborted by the user.${RESET}" + exit 0 + ;; esac fi else @@ -522,23 +844,65 @@ install() { fi } +# Temporary code to clean up earlier beta installations +function uninstallBetaAppImage() { + rm -f "$LINK_DIR"/phoenix_icon.png +} +# Upgrade Function +# +# Purpose: +# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated +# to the latest version available. This function checks the currently installed version against +# the latest version available in the GitHub repository. If a newer version is found, it proceeds +# to download and install the update, effectively replacing the old version with the new one. +# +# Behavior: +# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation +# directory and the invocation script. If not found, it exits with an error message indicating that +# Phoenix Code must be installed before it can be upgraded. +# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version +# check command (e.g., `phoenix-code --version`) and captures the output. +# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` +# function, which retrieves the version number of the latest release. +# 4. Compares the currently installed version with the latest version. If the installed version is older, +# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and +# installation of the new version. +# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. +# +# Considerations: +# - The function relies on the correct implementation of version checking in the Phoenix Code binary. +# The binary must support a command-line option to output its version, and the output format must be +# consistent for correct parsing and comparison. +# - Network connectivity is required to fetch the latest release information from the GitHub repository. +# The upgrade process will fail if the script cannot connect to GitHub. +# - The user must have sufficient permissions to overwrite the existing installation files and to +# execute network requests (e.g., downloading the latest release). +# - The upgrade process replaces the existing installation files. Users should ensure that any +# necessary backups or custom configurations are saved before proceeding with the upgrade. +# +# Usage: +# This function is intended to be called when the user explicitly wants to upgrade their installation +# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the +# script, as defined in the script's main case statement handling command-line arguments. +# upgrade() { echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" + # Ensure Phoenix Code is installed if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" exit 1 fi + # Get the current installed version + CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) + echo "Current installed version: $CURRENT_VERSION" - local current_version - current_version=$("$INSTALL_DIR/$APPIMAGE_NAME" --version 2>/dev/null || true) - echo "Current installed version: ${current_version:-unknown}" + LATEST_VERSION=$(downloadLatestReleaseInfo) + # Now LATEST_VERSION should only contain the version number without extra messages + echo "Latest available version: $LATEST_VERSION" - local latest_version - latest_version=$(downloadLatestReleaseInfo) - echo "Latest available version: $latest_version" - - if [ -n "$latest_version" ] && [ "$(printf '%s\n' "$latest_version" "$current_version" | sort -V | tail -n1)" = "$latest_version" ] && [ "$latest_version" != "$current_version" ]; then + # Compare versions and upgrade if the latest version is greater + if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" downloadAndInstall uninstall @@ -547,12 +911,48 @@ upgrade() { else echo "Your Phoenix Code installation is up-to-date." fi -} +} +# Uninstall Function +# +# Purpose: +# Handles the removal of Phoenix Code from the user's system. This function is responsible for +# cleaning up all files, directories, and links created during the installation process, effectively +# reverting any changes made by the installer script. It ensures that Phoenix Code and its components +# are uninstalled cleanly, leaving no residual files or configurations. +# +# Behavior: +# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). +# This step prevents the Phoenix Code command from being accessible after uninstallation. +# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus +# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. +# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. +# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. +# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including +# the main binary, configuration files, and any other related files placed during installation. +# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. +# +# Considerations: +# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately +# reflect the locations used during the installation. If these variables are incorrect, the uninstallation +# process may not remove all components. +# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed +# in system-wide directories. +# - Users should be advised to back up any important data or configurations related to Phoenix Code before +# initiating the uninstallation process, as this function will remove all associated files without recovery options. +# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot +# be reversed through this script. +# +# Usage: +# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. +# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement +# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this +# function is executed to prevent accidental data loss. +# uninstall() { echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" uninstallBetaAppImage - + # Remove the invocation script from ~/.local/bin if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" rm "$LINK_DIR/$SCRIPT_NAME" @@ -560,33 +960,40 @@ uninstall() { echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" fi + # Delete the desktop entry if [ -f "$DESKTOP_ENTRY" ]; then echo -e "${YELLOW}Removing desktop entry...${RESET}" rm "$DESKTOP_ENTRY" + + # Update the desktop database for GNOME, Unity, XFCE, etc. + echo -e "${YELLOW}Updating desktop database...${RESET}" if command -v update-desktop-database &> /dev/null; then - update-desktop-database "$DESKTOP_DIR" + update-desktop-database "$DESKTOP_DIR" fi - if [ "${XDG_CURRENT_DESKTOP:-}" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 - fi + + # Update the KDE desktop database if KDE is in use + if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi fi - if [[ "${XDG_CURRENT_DESKTOP:-}" =~ LXQt ]]; then + + if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then if command -v xdg-desktop-menu &> /dev/null; then - xdg-desktop-menu forceupdate + xdg-desktop-menu forceupdate fi fi else - echo -e "${RED}Desktop entry not found. Skipping...${RESET}" + echo -e "${RED}Desktop entry not found. Skipping...${RESET}" fi + # Remove the installation directory and its contents if [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" rm -rf "$INSTALL_DIR" else echo -e "${RED}Installation directory not found. Skipping...${RESET}" fi - echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" } @@ -602,6 +1009,7 @@ show_help() { echo "Without any options, the script will install Phoenix Code." } +# Check for GUI session by looking for DISPLAY or WAYLAND_DISPLAY variables if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then echo "This script should only be run from terminals in GUI sessions." exit 1 @@ -609,20 +1017,22 @@ fi case "${1-}" in -h|--help) - show_help + show_help # Function to show help ;; --uninstall) - uninstall + uninstall # Function to uninstall ;; --upgrade) - upgrade + upgrade # Function to upgrade ;; "") - install + # This case handles when $1 is unset (acts as a default action) + install # Function to install ;; *) + # This case handles unexpected arguments echo "Invalid option: $1" >&2 - show_help + show_help # Assuming you have a function to show usage information exit 1 ;; esac diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index c1c67770..d02b893d 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -29,7 +29,7 @@ }, "linux-x86_64": { "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIG1pbmlzaWduIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1LT0Rla1BIK1l2akRaclI3TFhGMHZYTEVSbWxmSGt1UFRCeGRPY1BjVkJ3Nk9DMlgvYjZWSXlWSVhjVGR2S1dYa2RsYVF2SnZLY2lra2lObXZ3cWdRPQp0cnVzdGVkIGNvbW1lbnQ6IDE3Njk5Mzc4MDYJZmlsZTpwaG9lbml4LWNvZGUtZXhwZXJpbWVudGFsLWJ1aWxkXzUuMC41LkFwcEltYWdlCjhVR3BVVkFSV010dXZjZkExeDFnOTcrbjRWMW4wVlhmOFYzbmhWMGxUd1VaR0lhc2tmMTRpNTRHYzkyeVNNNnAydG9YSkZvQTJ1U3F1RU96akVsaEN3PT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.3/phoenix-code_5.1.3.AppImage" + "url": "https://github.com/abose/phoenix-desktop/releases/download/cc/phoenix-code_5.1.16.AppImage" } } } From 3d2c1431a169b2478d045933c6903f45a8e66a67 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 18 May 2026 12:25:37 +0000 Subject: [PATCH 837/864] ci: update phcode version to 5.1.17 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index bb6ed5ae..34771051 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.16", + "version": "5.1.17", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "f2cd6487f482dc92bbc75c740965f833fd48b8cf" + "commit": "280ad019bb9cdeb0f82ee9ebf17f5cc3480f55f4" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index ac08e995..6ec723db 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.16", + "version": "5.1.17", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1d25c7e2..faf2b78f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.16" +version = "5.1.17" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 04bbb207..a7165abe 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.16" + "version": "5.1.17" }, "tauri": { "allowlist": { From 28b8139686ee4ce86d63476ee07c3f2ee29a7827 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 20 May 2026 13:58:00 +0000 Subject: [PATCH 838/864] ci: update phcode version to 5.1.18 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 34771051..65d85207 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.17", + "version": "5.1.18", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "280ad019bb9cdeb0f82ee9ebf17f5cc3480f55f4" + "commit": "54fefa3fc34c811c6079ee7174f7133aaf10fdd6" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 6ec723db..accc67be 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.17", + "version": "5.1.18", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index faf2b78f..fe3c723a 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.17" +version = "5.1.18" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a7165abe..a44cbd1e 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.17" + "version": "5.1.18" }, "tauri": { "allowlist": { From 27bd133cd7e844d4871ea81b037e176a164e8746 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 20 May 2026 21:29:04 +0530 Subject: [PATCH 839/864] chore: update linux appimage dev installer location for testing --- docs/tauri/update-latest-experimental-build.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tauri/update-latest-experimental-build.json b/docs/tauri/update-latest-experimental-build.json index d02b893d..7ff48cee 100644 --- a/docs/tauri/update-latest-experimental-build.json +++ b/docs/tauri/update-latest-experimental-build.json @@ -29,7 +29,7 @@ }, "linux-x86_64": { "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIG1pbmlzaWduIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm1LT0Rla1BIK1l2akRaclI3TFhGMHZYTEVSbWxmSGt1UFRCeGRPY1BjVkJ3Nk9DMlgvYjZWSXlWSVhjVGR2S1dYa2RsYVF2SnZLY2lra2lObXZ3cWdRPQp0cnVzdGVkIGNvbW1lbnQ6IDE3Njk5Mzc4MDYJZmlsZTpwaG9lbml4LWNvZGUtZXhwZXJpbWVudGFsLWJ1aWxkXzUuMC41LkFwcEltYWdlCjhVR3BVVkFSV010dXZjZkExeDFnOTcrbjRWMW4wVlhmOFYzbmhWMGxUd1VaR0lhc2tmMTRpNTRHYzkyeVNNNnAydG9YSkZvQTJ1U3F1RU96akVsaEN3PT0K", - "url": "https://github.com/abose/phoenix-desktop/releases/download/cc/phoenix-code_5.1.16.AppImage" + "url": "https://github.com/abose/phoenix-desktop/releases/download/cc/phoenix-code_5.1.18.AppImage" } } } From da3139526842382ca53873929f1389791c0e8dbc Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 23 May 2026 06:29:33 +0000 Subject: [PATCH 840/864] ci: update phcode version to 5.1.19 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 65d85207..3ef68154 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.18", + "version": "5.1.19", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "54fefa3fc34c811c6079ee7174f7133aaf10fdd6" + "commit": "0da2c61e0b407b3697889b9853b57604a2a92619" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index accc67be..e2f519fe 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.18", + "version": "5.1.19", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index fe3c723a..dd8d02c9 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.18" +version = "5.1.19" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a44cbd1e..6f5fd836 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.18" + "version": "5.1.19" }, "tauri": { "allowlist": { From 43ca9bdbcd957055572b674f95075465e6e0c4b5 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 25 May 2026 04:57:17 +0000 Subject: [PATCH 841/864] ci: update phcode version to 5.1.20 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3ef68154..7bccd983 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.19", + "version": "5.1.20", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "0da2c61e0b407b3697889b9853b57604a2a92619" + "commit": "c66c9ce7c54bb73d2785be089dddd96f4c8f1963" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index e2f519fe..c1487de2 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.19", + "version": "5.1.20", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index dd8d02c9..5c687d58 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.19" +version = "5.1.20" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6f5fd836..cd6af7cf 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.19" + "version": "5.1.20" }, "tauri": { "allowlist": { From 34806589a5c3509a9c59bf76cc8586e5b0a5909c Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Wed, 27 May 2026 15:08:22 +0530 Subject: [PATCH 842/864] feat: gate linux installer on GLIBC version and disable auto-update for old systems The new AppImage is built on ubuntu-22.04 (GLIBC 2.35) and cannot run on older systems like Ubuntu 20.04 (GLIBC 2.31). When the installer detects an incompatible GLIBC, it sets "autoUpdate": false in phcode.json to prevent the old version from repeatedly attempting an upgrade that will never succeed. Tested on ubuntu20 (2.31, refused), ubuntu26 (2.43, passed), fedora-44 (2.43, passed). --- .../installer-latest-experimental-build.sh | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/docs/linux/installer-latest-experimental-build.sh b/docs/linux/installer-latest-experimental-build.sh index 8c442ddc..e71f3ef9 100755 --- a/docs/linux/installer-latest-experimental-build.sh +++ b/docs/linux/installer-latest-experimental-build.sh @@ -35,6 +35,7 @@ DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" SCRIPT_NAME="phcode" BINARY_NAME="phoenix-code" APPIMAGE_NAME="phoenix-code.AppImage" +MIN_GLIBC_VERSION="2.35" declare -a MIME_TYPES=( "text/html" @@ -488,12 +489,62 @@ downloadAndInstall() { ensure_runtime_dependencies "$TMP_DIR/$APPIMAGE_NAME" } +# Returns 0 if the system GLIBC is >= MIN_GLIBC_VERSION, 1 otherwise. +# Uses the same ldd + awk pattern the old GLIBC-matched installer used. +glibc_compatible() { + local cur_ver + cur_ver=$(ldd --version | grep "ldd" | awk '{print $NF}') + echo "Current GLIBC version: $cur_ver" + awk -v min="$MIN_GLIBC_VERSION" -v cur="$cur_ver" \ + 'BEGIN { min += 0; cur += 0; exit !(min <= cur) }' +} + +# On systems whose GLIBC is too old for the new AppImage, disable auto-update +# in the old installation's config so it stops trying to upgrade to a binary +# that cannot run here. +disable_auto_update_old_version() { + local config_path="" + local primary="$HOME/.local/share/io.phcode/phcode.json" + local xdg="${XDG_DATA_HOME:-$HOME/.local/share}/io.phcode/phcode.json" + + if [ -f "$primary" ]; then + config_path="$primary" + elif [ "$xdg" != "$primary" ] && [ -f "$xdg" ]; then + config_path="$xdg" + fi + + if [ -z "$config_path" ]; then + config_path="$primary" + echo "Creating $config_path..." + mkdir -p "$(dirname "$config_path")" + echo '{"autoUpdate": false}' > "$config_path" + echo -e "${GREEN}Auto-update disabled in $config_path${RESET}" + return 0 + fi + + echo "Disabling auto-update in $config_path..." + if grep -q '"autoUpdate"' "$config_path"; then + sed -i 's/"autoUpdate"[[:space:]]*:[[:space:]]*[^,}]*/"autoUpdate": false/' "$config_path" + elif grep -q '"' "$config_path"; then + sed -i '0,/{/ s/{/{\n "autoUpdate": false,/' "$config_path" + else + echo '{"autoUpdate": false}' > "$config_path" + fi + echo -e "${GREEN}Auto-update disabled in $config_path${RESET}" +} + # Temporary cleanup for files from older installer versions. uninstallBetaAppImage() { rm -f "$LINK_DIR"/phoenix_icon.png } install() { + if ! glibc_compatible; then + echo -e "${RED}This system's GLIBC is older than $MIN_GLIBC_VERSION. The new AppImage cannot run here.${RESET}" + disable_auto_update_old_version + exit 1 + fi + if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" if [ ! -t 0 ]; then @@ -525,6 +576,12 @@ install() { upgrade() { echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" + if ! glibc_compatible; then + echo -e "${RED}This system's GLIBC is older than $MIN_GLIBC_VERSION. The new AppImage cannot run here.${RESET}" + disable_auto_update_old_version + exit 1 + fi + if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" exit 1 From 189f927f1764b172e516a43d53654cc10af3b32a Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 May 2026 19:49:42 +0530 Subject: [PATCH 843/864] feat: promote electron installer to prod stage --- docs/linux/installer.sh | 1187 ++++++++++++++------------------------- 1 file changed, 417 insertions(+), 770 deletions(-) diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 87f8b54e..e71f3ef9 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -1,25 +1,41 @@ #!/bin/bash -set -euo pipefail # Exit immediately if a command exits with a non-zero status. -# Define common variables -DESKTOP_DIR=$HOME/.local/share/applications # Directory for desktop entries -GITHUB_REPO="phcode-dev/phoenix-desktop" -API_URL="https://api.github.com/repos/$GITHUB_REPO/releases/latest" +set -euo pipefail + +# Phoenix Code Linux installer. +# +# Downloads the latest Phoenix Code AppImage from the update JSON, then probes +# the downloaded AppImage with `--version` (early-exit handler at +# src-electron/main.js:23-26). If the probe succeeds, no apt/dnf/pacman install +# is attempted — the system already has every shared library Phoenix Code +# needs at startup, regardless of which package name provides it. +# +# Beyond the --version probe, the installer also checks for the gnome-keyring +# daemon binary — libsecret needs the daemon for keytar credential storage, +# and --version exits before keytar is require()d. Sudo is only requested if +# libs or the keyring daemon are actually missing. +# +# On Ubuntu 24.04+ / Debian 13+, Chromium's unprivileged userns sandbox can +# be blocked by the kernel sysctl. The app still launches because the wrapper +# script falls back to --no-sandbox; we no longer install an AppArmor profile +# to keep the kernel sandbox enabled (the renderer-RCE-to-syscall threat the +# kernel sandbox guards against is narrow, and Phoenix Code's actual attack +# surface flows through the IPC bridge which the kernel sandbox doesn't gate). +# +# Also wires up a desktop entry + `phcode` wrapper script that handles +# AppImage launch fallbacks. + +DESKTOP_DIR=$HOME/.local/share/applications +UPDATE_JSON_URL="https://updates.phcode.io/tauri/update-latest-experimental-build.json" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" -GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/gtk.tar.xz" -WEBKIT2GTK_URL="https://github.com/phcode-dev/dependencies/releases/download/v1.0.0/webkit2gtk-4.0.tar.xz" INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" DESKTOP_ENTRY_NAME="PhoenixCode.desktop" DESKTOP_APP_NAME="Phoenix Code" DESKTOP_ENTRY="$DESKTOP_DIR/$DESKTOP_ENTRY_NAME" -SCRIPT_NAME="phcode" # Name of the script to invoke the binary +SCRIPT_NAME="phcode" BINARY_NAME="phoenix-code" -# STARTUP_WM_CLASS is set to the binary name and used as the application's class name in the desktop file. -# This class name helps the desktop environment manage application windows. If native libraries are missing -# and the application needs to be launched via a script instead of directly, this variable is updated -# accordingly before the desktop file is created. -STARTUP_WM_CLASS=$BINARY_NAME - +APPIMAGE_NAME="phoenix-code.AppImage" +MIN_GLIBC_VERSION="2.35" declare -a MIME_TYPES=( "text/html" @@ -48,460 +64,310 @@ declare -a MIME_TYPES=( "text/cjs" ) - -# Define color variables for easy reference GREEN="\e[32m" YELLOW="\e[33m" RED="\e[31m" RESET="\e[0m" -# Cleanup Function -# -# Purpose: -# The cleanup function is designed to ensure that the script cleans up any temporary -# resources it used during its execution. Specifically, it removes the temporary directory -# created at the beginning of the script, along with all its contents. This is crucial for -# maintaining a clean file system and avoiding the accumulation of unused files. -# -# Behavior: -# - The function targets a temporary directory specified by the `$TMP_DIR` variable. -# - It uses `rm -rf` to recursively and forcefully remove this directory and all its contents. -# This includes any temporary files, downloaded assets, or other data generated during the script's execution. -# - The cleanup is registered with a `trap` command on the `EXIT` signal, ensuring it executes -# automatically when the script exits, regardless of the exit point. This includes normal completion, -# errors, or manual termination via signals like SIGINT (Ctrl+C). -# -# Considerations: -# - The function assumes that `$TMP_DIR` is correctly set to the path of the temporary directory. -# If `$TMP_DIR` is unset or incorrectly set, the function may not perform as intended. -# - Using `rm -rf` carries the risk of deleting significant data if misused. It's crucial that `$TMP_DIR` -# is always a temporary directory intended for deletion and does not overlap with any critical system or user directories. -# - The function does not provide a confirmation prompt before deletion, so it's assumed that any data within -# `$TMP_DIR` is expendable and safe to delete. -# -# Usage: -# This function is not intended to be called directly by the user. It's automatically triggered by the `trap` -# command set up at the beginning of the script. However, if manual cleanup is necessary, ensure that `$TMP_DIR` -# is correctly set to the temporary directory path before invoking the function. -# cleanup() { - rm -rf "$TMP_DIR" # Command to remove the temporary directory and its contents. + rm -rf "$TMP_DIR" } +# Surface user interrupts (Ctrl+C / kill) with a clear message and exit 130, +# while still running cleanup. Without this, dpkg unpacks and sudo prompts can +# make the script look unresponsive to SIGINT for a beat. +on_interrupt() { + echo + echo -e "${RED}Interrupted by user. Cleaning up...${RESET}" + cleanup + exit 130 +} +trap cleanup EXIT +trap on_interrupt INT TERM -trap cleanup EXIT # Register the cleanup function to be called on script exit. +TMP_DIR=$(mktemp -d) +configure_wget_options() { + local wget_version + wget_version=$(wget --version | head -n1 | awk '{print $3}') + local major_version + major_version=$(echo "$wget_version" | cut -d. -f1) -TMP_DIR=$(mktemp -d) + if [[ "$major_version" -ge 2 ]]; then + echo "-c --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" + else + echo "-c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO" + fi +} -# Check OS Version Function -# -# Purpose: -# This function checks if the current operating system is Ubuntu 24.04, Linux Mint 22, or Kali Linux 2024.2 or newer. -# It reads the /etc/os-release file, which contains identification data for the operating system. -# -# Behavior: -# 1. The function first checks if the /etc/os-release file exists. -# 2. If the file exists, it sources the file to load the OS identification variables. -# 3. It then checks if: -# - The ID variable is set to "ubuntu" and the VERSION_ID variable is "24.04", -# - The ID variable is "linuxmint" and the VERSION_ID is "22", -# - The ID variable is "kali" and the VERSION_ID is "2024.2" or newer. -# 4. If any of these conditions are met, the function returns 0 (indicating success). -# 5. If none of these conditions are met, the function returns 1 (indicating failure). -# -# Usage: -# This function can be called to determine if special handling is needed for these specific versions of -# Ubuntu, Linux Mint, or Kali Linux, such as installing additional libraries or making compatibility adjustments. -# -# Example: -# if check_os_version; then -# echo "Supported OS version detected." -# else -# echo "Unsupported OS version." -# fi -# -# Notes: -# - This function assumes that the /etc/os-release file follows the standard format for Linux OS -# identification and that the distribution's identifiers are consistent with those specified in the script. - -check_os_version() { - if [ -f /etc/os-release ]; then - . /etc/os-release - # Set VERSION_ID to empty string if not defined (for rolling releases) - VERSION_ID="${VERSION_ID:-}" - # Define supported OS and version combinations - case "$ID:${VERSION_ID%%.*}" in # Extract major version number - ubuntu:24) # Ubuntu 24.x - return 0 - ;; - ubuntu:25) # Ubuntu 25.x - return 0 - ;; - linuxmint:22) # Linux Mint 22.x - return 0 - ;; - neon:24) # KDE Neon 24.x - return 0 - ;; - debian:13) # Debian 13.x (Trixie) - return 0 - ;; - kali:2024|kali:20[2-9][0-9]) # Kali 2024.x or newer - return 0 - ;; - esac +check_architecture() { + local arch + arch=$(uname -m) + if [ "$arch" != "x86_64" ]; then + echo -e "${RED}This installer only supports 64-bit x86 (x86_64). Detected: $arch.${RESET}" + exit 1 fi - return 1 } -# Create Invocation Script Function -# -# Purpose: -# Generates a Bash script that serves as a wrapper for invoking the installed binary of Phoenix Code. -# This script is intended to simplify the execution of Phoenix Code by providing a more accessible -# command interface. The generated script is placed in a user-accessible binary directory, making it -# possible to run Phoenix Code from anywhere in the system without needing to specify the full path -# to the binary. -# -# Parameters: -# - binary_path: The absolute path to the directory where the Phoenix Code binary is located. -# - script_name: The name to be given to the invocation script. This name is used both for the -# script file itself and for the symlink created in the user's binary directory. -# - link_dir: The directory where a symlink to the invocation script will be placed, typically -# a location in the user's PATH, such as ~/.local/bin, for easy access. -# -# Behavior: -# 1. Creates a new Bash script in the specified 'binary_path' with the 'script_name'. -# 2. Writes a shebang line, a warning comment indicating the script is auto-generated, and a -# command to execute the Phoenix Code binary with any passed arguments ("$@"). -# 3. Sets executable permissions on the newly created script. -# 4. Copies the script to the specified 'link_dir', creating a symlink in a user-accessible location. -# -# Considerations: -# - It's crucial that 'binary_path' and 'link_dir' are valid directories and that 'script_name' -# does not conflict with existing files in these directories to prevent unintended overwrites. -# - The function does not check for the existence of 'binary_path' or 'link_dir'; it assumes -# these directories are already created and accessible. -# - The generated script includes a warning comment advising against deletion, as it is -# essential for the proper functioning of Phoenix Code when invoked through this script. -# -# Usage: -# This function is intended to be called during the installation or upgrade process of Phoenix Code, -# after the binary has been placed in its final location. It should not be called arbitrarily, as it -# assumes a specific setup and context established by the installer script. -# +# Runtime-library probe: ask the AppImage to print its version and exit. This +# is handled at src-electron/main.js:23-26, but `require('electron')` runs +# before that handler — which means Chromium initializes its sandbox bits even +# for --version. On Ubuntu 24.04+ / Debian 13+ where unprivileged user +# namespaces are restricted, that init can SIGTRAP. Pass --no-sandbox so the +# probe isolates to "are the system shared libraries present and loadable?" +# regardless of the kernel's userns policy. +# +# The `{ … } 2>/dev/null` wrapper suppresses bash's own "Trace/breakpoint trap +# (core dumped)" report when the subprocess dies on signal — those messages +# look alarming but are harmless: we already detect failure via the exit code. +verify_appimage_launches() { + { "$1" --no-sandbox --version >/dev/null 2>&1; } 2>/dev/null +} + +# Returns 0 if the gnome-keyring secret-service daemon binary is on PATH. +# `--version` can't test this because keytar is only require()d at first use, +# so we need an independent presence check. +gnome_keyring_present() { + command -v gnome-keyring-daemon >/dev/null 2>&1 +} + +downloadLatestReleaseInfo() { + local release_info_file="$TMP_DIR/latest_release.json" + if [ ! -f "$release_info_file" ]; then + >&2 echo -e "${GREEN}Fetching the latest release information...${RESET}" + wget -qO "$release_info_file" "$UPDATE_JSON_URL" || { + >&2 echo -e "${RED}Failed to fetch release info from $UPDATE_JSON_URL. Check your internet connection.${RESET}" + exit 1 + } + fi + grep -Po '"version"\s*:\s*"\K[^"]+' "$release_info_file" | head -n1 +} + +# Parses the linux-x86_64 download URL out of the update JSON without needing jq. +getLinuxAppImageUrl() { + awk ' + /"linux-x86_64"[[:space:]]*:/ { in_linux=1 } + in_linux && /"url"[[:space:]]*:/ { + if (match($0, /"url"[[:space:]]*:[[:space:]]*"[^"]+"/)) { + s = substr($0, RSTART, RLENGTH) + sub(/^"url"[[:space:]]*:[[:space:]]*"/, "", s) + sub(/"$/, "", s) + print s + exit + } + } + ' "$TMP_DIR/latest_release.json" +} + +# Generates the `phcode` wrapper script. The wrapper runs the AppImage directly, +# falling back to --appimage-extract-and-run on FUSE failure or to --no-sandbox +# on userns/AppArmor failure (Ubuntu 24.04+ / Debian 13+ blocks Chromium's +# unprivileged user namespace sandbox unless our AppArmor profile is loaded). create_invocation_script() { - local binary_path="$1" + local install_dir="$1" local script_name="$2" local link_dir="$3" - echo "Creating an invocation script for the binary..." - # Start of the generated script - echo "#!/bin/bash" > "$binary_path/$script_name.sh" - # Add a warning comment about the script being auto-generated - echo "# DO NOT DELETE: This script is generated by the Phoenix Code installer." >> "$binary_path/$script_name" - echo "$binary_path/$BINARY_NAME \"\$@\"" >> "$binary_path/$script_name" - chmod +x "$binary_path/$script_name" - - echo "Copying the invocation script to $link_dir..." - mkdir -p "$link_dir" # Ensure the directory exists - cp "$binary_path/$script_name" "$link_dir/$script_name" + echo "Creating an invocation script for the AppImage..." + cat > "$install_dir/$script_name" <"\$ERR"; then + if grep -qiE 'fuse|libfuse|fusermount|/dev/fuse' "\$ERR"; then + rm -f "\$ERR" + exec "\$APPIMAGE" --appimage-extract-and-run "\$@" + fi + if grep -qiE 'userns|apparmor|sandbox|setuid|namespace|Check failed' "\$ERR"; then + rm -f "\$ERR" + exec "\$APPIMAGE" --no-sandbox "\$@" + fi + cat "\$ERR" >&2 + rm -f "\$ERR" + exit 1 +fi +rm -f "\$ERR" +EOF + chmod +x "$install_dir/$script_name" + mkdir -p "$link_dir" + cp "$install_dir/$script_name" "$link_dir/$script_name" echo -e "Invocation script created at: $link_dir/$script_name" } -# Install Dependencies Function -# -# Purpose: -# Installs the necessary dependencies for Phoenix Code to run properly on the user's system. -# This function identifies the user's Linux distribution and installs the appropriate packages -# using the distribution's package manager. It supports Ubuntu/Debian, Fedora/RHEL/CentOS, and -# Arch Linux distributions. -# -# Behavior: -# 1. Checks for administrative privileges by attempting a non-interactive `sudo` command. -# If the command fails, it prompts the user to enter their password for `sudo` access. -# 2. Determines the Linux distribution by examining the contents of `/etc/os-release`. -# 3. Based on the identified distribution, executes the appropriate package manager command -# with the required packages. Supported package managers are `apt` for Debian-based systems, -# `dnf` for Fedora/RHEL/CentOS, and `pacman` for Arch Linux. -# 4. Updates the package index (if applicable) and installs the packages. -# -# Considerations: -# - The function requires internet access to fetch package information and install packages. -# - It assumes that the user has `sudo` privileges to install packages system-wide. -# - The list of dependencies is hardcoded within the function. If Phoenix Code's dependencies change, -# this function must be updated accordingly. -# - Unsupported distributions will result in an error message and termination of the script, -# as the required dependencies cannot be installed automatically. -# - This function does not handle potential errors from package installation commands. It's -# recommended to monitor the output for any issues that may require manual intervention. -# -# Usage: -# This function is intended to be called during the Phoenix Code installation process, typically -# before attempting to run or configure the Phoenix Code binary. It ensures that all prerequisites -# are met for a successful Phoenix Code execution. -# -install_dependencies() { - echo "Attempting to install required dependencies..." - - # Inform the user that the next steps require administrative access - echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." - # Check if the script can execute sudo commands without interaction - if ! sudo -n true 2>/dev/null; then - echo "Please enter your password to proceed with the installation of dependencies." +# Returns "gnome-keyring" unless the current session is KDE. +# On KDE, kwallet implements the Secret Service interface (KF 5.97+ / ksecretd +# in 2026), and installing gnome-keyring causes a D-Bus activation race for +# org.freedesktop.secrets — see VSCode issue #189672. +gnome_keyring_pkg_if_needed() { + if [[ "${XDG_CURRENT_DESKTOP:-}" =~ KDE ]]; then + echo "" + else + echo "gnome-keyring" fi +} - # Attempt to identify the Linux distribution - if [ -f /etc/os-release ]; then - . /etc/os-release - DISTRO=$ID +# Picks the libfuse2 package name for whatever Ubuntu/Debian release we're on. +# Ubuntu 24.04 Noble+ / Debian 13 Trixie+ / Kali rolling / Mint 22+ / Neon 24+ +# ship libfuse2t64 (the post-y2038 rename); older releases (Ubuntu 20.04 Focal +# / 22.04 Jammy, Debian 11/12, Mint 20/21, Neon 22) ship the pre-rename +# libfuse2. Both provide the same libfuse.so.2 SONAME, so picking by repo +# availability is correct. +choose_fuse_package_apt() { + if apt-cache show libfuse2t64 >/dev/null 2>&1; then + echo libfuse2t64 else - echo "Unable to identify the operating system." - exit 1 + echo libfuse2 fi +} - # Install dependencies based on the distribution - case "$DISTRO" in - ubuntu|debian|linuxmint|kali) - echo "Detected an Ubuntu/Debian based distribution." - sudo apt update - yes | sudo apt install libgtk-3-0 libwebkit2gtk-4.0-37 \ - gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ - gstreamer1.0-tools +# Per-distro package install. Only called when verify_appimage_launches failed +# OR the keyring daemon is missing — i.e., we've already decided we need sudo. +install_packages_for_distro() { + local distro="$1" keyring="$2" + # RHEL 10 does not ship libXScrnSaver in any default channel — left off the + # dnf list intentionally; Electron's XScreenSaver calls no-op on Wayland. + # libxss + libnotify are listed for Arch because gtk3 does NOT pull them in + # transitively but Electron dlopen's them at runtime. + local -a pkgs=() + case "$distro" in + ubuntu|debian|linuxmint|kali|neon) pkgs=("$(choose_fuse_package_apt)" libsecret-1-0) ;; + fedora|rhel|centos) pkgs=(fuse-libs fuse3-libs libsecret) ;; + arch|manjaro|cachyos) pkgs=(fuse2 libsecret libxss libnotify) ;; + esac + [ -n "$keyring" ] && pkgs+=("$keyring") + + case "$distro" in + ubuntu|debian|linuxmint|kali|neon) + # No `yes |` pipeline: under `set -o pipefail`, `yes` dies of SIGPIPE + # after apt exits and the pipeline returns 141, silently aborting the + # installer. Use apt-get -y, and keep user /etc config files via the + # force-conf* options so an unrelated pending upgrade can't prompt. + echo "Detected an Ubuntu/Debian-based distribution." + sudo apt-get update + # shellcheck disable=SC2068 + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \ + -o Dpkg::Options::="--force-confdef" \ + -o Dpkg::Options::="--force-confold" \ + ${pkgs[@]} ;; fedora|rhel|centos) - echo "Detected a Fedora/Red Hat based distribution." - yes | sudo dnf install webkit2gtk3 gtk3 \ - gstreamer1-plugins-base gstreamer1-plugins-good - yes | sudo dnf upgrade webkit2gtk3 gtk3 \ - gstreamer1 gstreamer1-plugins-base gstreamer1-plugins-good + echo "Detected a Fedora/Red Hat-based distribution." + # shellcheck disable=SC2068 + sudo dnf install -y ${pkgs[@]} ;; arch|manjaro|cachyos) - echo "Detected an Arch Linux based distribution." - echo "Updating package database..." + echo "Detected an Arch-based distribution." sudo pacman -Sy - yes | sudo pacman -S webkit2gtk gtk3 libxml2 - ;; - *) - echo "Unsupported distribution. Please manually install the required dependencies." - exit 1 + # shellcheck disable=SC2068 + sudo pacman -S --noconfirm --needed ${pkgs[@]} ;; esac } -download_and_install_gtk() { - # Function: create_launch_script_with_gtk - # - # Purpose: - # This function creates a launch script for the Phoenix Code application that sets the required - # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that - # the Phoenix Code application uses the correct GTK libraries, which are included in the - # application's installation directory. - # - # Parameters: - # - binary_path: The path to the directory containing the Phoenix Code binary. - # - binary_name: The name of the Phoenix Code binary file. - # - # Behavior: - # 1. The function renames the original Phoenix Code binary to append ".real" to its name. - # 2. It then creates a new launch script with the original binary name in the same directory. - # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the - # GTK libraries located in the same directory as the binary. - # 4. The launch script executes the original Phoenix Code binary (now renamed) with any - # arguments passed to the script. - # 5. The function sets the appropriate executable permissions on the launch script. - # - # Usage: - # This function should be called after the Phoenix Code binary and its required GTK libraries - # have been installed. It ensures that the application uses the correct libraries when launched. - # - # Example: - # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" - # - # Notes: - # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within - # the same directory as the Phoenix Code binary. - # - The function requires the mv, chmod, and cat commands to be available in the environment. - # - This piece of code should only be executed if the package manager does not distribute - # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. - - local URL_PREFIX="https://github.com/phcode-dev/dependencies/releases/download/v1.0.5/" - local GTK_FILE="gtk.tar.xz" - local WEBKIT2GTK_FILE="webkit2gtk-4.0.tar.xz" - - local GTK_URL="${URL_PREFIX}${GTK_FILE}" - local WEBKIT2GTK_URL="${URL_PREFIX}${WEBKIT2GTK_FILE}" - - echo -e "${YELLOW}Downloading GTK from $GTK_URL...${RESET}" - local destination="$TMP_DIR/$BINARY_NAME" - WGET_OPTS=$(configure_wget_options) - - wget $WGET_OPTS "$TMP_DIR/gtk.tar.xz" "$GTK_URL" || { - echo -e "${RED}Failed to download GTK. Please check your internet connection and try again.${RESET}" - exit 1 - } - echo "Extracting GTK..." - tar -xJf "$TMP_DIR/$GTK_FILE" -C "$destination" || { - echo -e "${RED}Failed to extract GTK. The downloaded file might be corrupt.${RESET}" - exit 1 - } - if [ ! -d "/usr/lib/x86_64-linux-gnu/webkit2gtk-4.0" ]; then - echo -e "${YELLOW}Downloading WebKit2GTK from $WEBKIT2GTK_URL...${RESET}" - wget $WGET_OPTS "$TMP_DIR/$WEBKIT2GTK_FILE" "$WEBKIT2GTK_URL" || { - echo -e "${RED}Failed to download WebKit2GTK. Please check your internet connection and try again.${RESET}" - exit 1 - } - echo "Extracting WebKit2GTK..." - tar -xJf "$TMP_DIR/$WEBKIT2GTK_FILE" -C "$TMP_DIR" || { - echo -e "${RED}Failed to extract WebKit2GTK. The downloaded file might be corrupt.${RESET}" +# Decides what (if anything) the user's system is missing for Phoenix Code to +# run, then installs only the missing piece(s). Three independent probes: +# +# 1. System shared libraries — probed by running the downloaded AppImage +# with `--version`. main.js exits immediately on this flag, AFTER libfuse +# mounts the AppImage and AFTER the Electron binary loads its NEEDED libs. +# 2. gnome-keyring daemon — binary-presence check; `--version` doesn't +# exercise keytar so it can't verify libsecret/Secret Service end-to-end. +# +# Sudo is requested ONLY if at least one of the probes fails. +ensure_runtime_dependencies() { + local appimage="$1" + if [ ! -f /etc/os-release ]; then + echo -e "${RED}Unable to identify the operating system (no /etc/os-release).${RESET}" + exit 1 + fi + . /etc/os-release + local distro="${ID:-}" + case "$distro" in + ubuntu|debian|linuxmint|kali|neon|fedora|rhel|centos|arch|manjaro|cachyos) ;; + *) + echo -e "${RED}Unsupported distribution: $distro. Please install libfuse2/fuse2, libsecret, and (on non-KDE) gnome-keyring manually.${RESET}" exit 1 - } + ;; + esac + local keyring; keyring=$(gnome_keyring_pkg_if_needed) - # Inform the user that the next steps require administrative access - echo "The installation of dependencies requires administrative access. You may be prompted to enter your password." + local libs_ok=1 keyring_ok=1 + verify_appimage_launches "$appimage" || libs_ok=0 + if [ -n "$keyring" ] && ! gnome_keyring_present; then keyring_ok=0; fi - # Check if the script can execute sudo commands without interaction - if ! sudo -n true 2>/dev/null; then - echo "Please enter your password to proceed with the installation of dependencies." - fi + if [ "$libs_ok" = 1 ] && [ "$keyring_ok" = 1 ]; then + echo -e "${GREEN}All runtime dependencies already present.${RESET}" + return 0 + fi - echo "Installing WebKit2GTK..." - sudo cp -r "$TMP_DIR/webkit2gtk-4.0" /usr/lib/x86_64-linux-gnu/ || { - echo -e "${RED}Failed to install WebKit2GTK. Please check the permissions and try again.${RESET}" - exit 1 - } - echo -e "${GREEN}WebKit2GTK installed successfully.${RESET}" + if [ "$libs_ok" = 0 ]; then + echo "Installing missing runtime libraries..." else - echo -e "${GREEN}WebKit2GTK already installed.${RESET}" + echo "Installing system keychain daemon..." + fi + echo "This step requires administrative access." + if ! sudo -n true 2>/dev/null; then + echo "Please enter your password to proceed." fi -} - -create_launch_script_with_gtk() { - # Function: create_launch_script_with_gtk - # - # Purpose: - # This function creates a launch script for the Phoenix Code application that sets the required - # GTK library paths in the LD_LIBRARY_PATH environment variable. The launch script ensures that - # the Phoenix Code application uses the correct GTK libraries, which are included in the - # application's installation directory. - # - # Parameters: - # - binary_path: The path to the directory containing the Phoenix Code binary. - # - binary_name: The name of the Phoenix Code binary file. - # - # Behavior: - # 1. The function renames the original Phoenix Code binary to append ".real" to its name. - # 2. It then creates a new launch script with the original binary name in the same directory. - # 3. The launch script sets the LD_LIBRARY_PATH environment variable to include the path to the - # GTK libraries located in the same directory as the binary. - # 4. The launch script executes the original Phoenix Code binary (now renamed) with any - # arguments passed to the script. - # 5. The function sets the appropriate executable permissions on the launch script. - # - # Usage: - # This function should be called after the Phoenix Code binary and its required GTK libraries - # have been installed. It ensures that the application uses the correct libraries when launched. - # - # Example: - # create_launch_script_with_gtk "/path/to/phoenix-code" "phoenix-code" - # - # Notes: - # - This function assumes that the GTK libraries are located in a subdirectory named "gtk" within - # the same directory as the Phoenix Code binary. - # - The function requires the mv, chmod, and cat commands to be available in the environment. - # - This piece of code should only be executed if the package manager does not distribute - # libgtk or if the version provided by the package manager is not compatible with Phoenix Code. - - local binary_path="$1" - local binary_name="$BINARY_NAME" - local original_bin=$binary_name.app - local realBin="$binary_path/$original_bin" - mv "$binary_path/$binary_name" "$realBin" - echo "Creating a launch script for Phoenix Code with GTK libraries..." - cat > "$binary_path/$binary_name" </dev/null 2>&1 || return 0 + local locked + locked=$(busctl --user --no-pager call org.freedesktop.secrets \ + /org/freedesktop/secrets/collection/login \ + org.freedesktop.DBus.Properties Get \ + ss org.freedesktop.Secret.Collection Locked 2>/dev/null \ + | awk '/^b /{print $NF}') + [ "$locked" = "true" ] || return 0 - if "$TMP_DIR/phoenix-code/phoenix-code" --runVerify; then - echo "Application launch verification successful after installing dependencies." - return 0 - else - echo "Verification failed even after installing dependencies. Please check the application requirements or contact support." - return 1 + echo + echo -e "${YELLOW}Note: your system keychain is currently locked.${RESET}" + echo -e "${YELLOW}The first time Phoenix Code stores or reads a credential, gnome-keyring${RESET}" + echo -e "${YELLOW}will ask once for your login password to unlock it. This is a one-time${RESET}" + echo -e "${YELLOW}per-session Linux behavior — not a Phoenix Code prompt.${RESET}" + if autologin_detected; then + echo -e "${YELLOW}(Autologin is enabled on this machine, which is why PAM did not${RESET}" + echo -e "${YELLOW} auto-unlock the keyring at session start.)${RESET}" fi } -# Set Phoenix Code as the default application for specified MIME types + set_default_application() { - local desktop_file="$DESKTOP_ENTRY_NAME" # Name of the Phoenix Code desktop entry file + local desktop_file="$DESKTOP_ENTRY_NAME" - # Dynamically detect qtpaths if KDE is running and qtpaths is not in PATH if [ "${KDE_SESSION_VERSION:-0}" -gt 0 ] && ! command -v qtpaths &> /dev/null; then - # Common locations where qtpaths might be installed local qtpaths_locations=( "/usr/lib/qt6/bin" "/usr/lib/qt5/bin" @@ -510,7 +376,6 @@ set_default_application() { "/opt/qt6/bin" "/opt/qt5/bin" ) - for qtpath_dir in "${qtpaths_locations[@]}"; do if [ -x "$qtpath_dir/qtpaths" ] || [ -x "$qtpath_dir/qtpaths6" ]; then export PATH="$qtpath_dir:$PATH" @@ -520,82 +385,36 @@ set_default_application() { fi for mime_type in "${MIME_TYPES[@]}"; do - # Skip setting default application for text/html - if [ "$mime_type" = "text/html" ]; then - continue # Skip to the next iteration - fi - - xdg-mime default "$desktop_file" "$mime_type" + if [ "$mime_type" = "text/html" ]; then + continue + fi + xdg-mime default "$desktop_file" "$mime_type" done echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" } -# Copy Files to Destination Function -# -# Purpose: -# This function is responsible for setting up the final installation directory for Phoenix Code, -# moving the necessary files into place, creating the invocation script, and setting up the desktop -# entry for the application. It ensures that all components of Phoenix Code are correctly installed -# and configured in the user's environment. -# -# Behavior: -# 1. Creates the installation directory at `$INSTALL_DIR`, where Phoenix Code and its related files -# will reside. -# 2. Similarly, ensures the desktop entry directory `$DESKTOP_DIR` exists for application launchers. -# 3. Moves the downloaded and possibly compiled Phoenix Code binary and other necessary files from -# the temporary directory (`$TMP_DIR`) to the installation directory. -# 4. Downloads and moves the application icon to the installation directory for use in the desktop entry. -# 5. Sets the correct executable permissions for the Phoenix Code binary to ensure it can be run by the user. -# 6. Calls `create_invocation_script` to generate a wrapper script for easier execution of Phoenix Code. -# 7. Constructs a `.desktop` file for Phoenix Code, defining how it should appear in application menus and -# launchers, and places this file in the desktop entry directory. -# 8. Updates the system's desktop database to ensure the new application entry is recognized and available -# in application menus and launchers. This step might involve commands like `update-desktop-database` -# or `kbuildsycoca5`, depending on the desktop environment. -# -# Considerations: -# - The function assumes that the necessary files for Phoenix Code are already present in `$TMP_DIR` and -# that this directory is correctly set. -# - It relies on specific directory paths (`$INSTALL_DIR`, `$DESKTOP_DIR`, `$LINK_DIR`) being set and -# accessible. If these variables are unset or incorrect, the function may not perform as intended. -# - Administrative privileges may be required for certain operations, such as updating the desktop database -# or setting permissions, depending on the system's configuration. -# - Care is taken to avoid overwriting existing files or directories without confirmation, but this function -# does perform significant file system operations that could potentially conflict with existing user data -# or system settings. -# -# Usage: -# This function is intended to be called as part of the Phoenix Code installation process, after the -# application's binary and other necessary files have been prepared in a temporary location. It finalizes -# the installation by placing all components in their appropriate locations within the user's system. -# -copyFilesToDestination(){ +copyFilesToDestination() { echo "Setting up the installation directory at $INSTALL_DIR..." mkdir -p "$INSTALL_DIR" mkdir -p "$DESKTOP_DIR" - echo -e "${YELLOW}Installation directory set up at: $INSTALL_DIR${RESET}" - echo "Moving the necessary files to the installation directory..." - echo -e "Phoenix Code files moved to: $INSTALL_DIR" - mv "$TMP_DIR"/phoenix-code/* "$INSTALL_DIR/" || { - echo -e "${RED}Failed to move the files to the installation directory. Please check the permissions and try again.${RESET}" + mv "$TMP_DIR/$APPIMAGE_NAME" "$INSTALL_DIR/$APPIMAGE_NAME" || { + echo -e "${RED}Failed to move the AppImage to the installation directory. Please check the permissions and try again.${RESET}" exit 1 } - # Move the icon to the installation directory mv "$TMP_DIR/icon.png" "$INSTALL_DIR/" - echo "Setting the correct permissions for the executable..." - chmod +x "$INSTALL_DIR/phoenix-code" || { - echo -e "${RED}Failed to set executable permissions. Please check the file path and permissions.${RESET}" + chmod +x "$INSTALL_DIR/$APPIMAGE_NAME" || { + echo -e "${RED}Failed to set executable permissions on the AppImage.${RESET}" exit 1 } - echo -e "Executable permissions set for: $INSTALL_DIR/$BINARY_NAME" + echo -e "AppImage installed at: $INSTALL_DIR/$APPIMAGE_NAME" - mkdir -p "$LINK_DIR" # Ensure the directory exists - # Call the function to create and copy the invocation script + mkdir -p "$LINK_DIR" create_invocation_script "$INSTALL_DIR" "$SCRIPT_NAME" "$LINK_DIR" - # Convert MIME types array to semicolon-separated string for the desktop entry - MIME_TYPES_STRING=$(IFS=";"; echo "${MIME_TYPES[*]}") + + local mime_types_string + mime_types_string=$(IFS=";"; echo "${MIME_TYPES[*]}") echo "Creating desktop entry..." cat > "$DESKTOP_ENTRY" < /dev/null; then - update-desktop-database "$DESKTOP_DIR" - echo -e "Desktop database updated in: $DESKTOP_DIR" + update-desktop-database "$DESKTOP_DIR" fi - - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then + if [ "${XDG_CURRENT_DESKTOP:-}" = "KDE" ]; then if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 + kbuildsycoca5 fi fi - - if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then + if [[ "${XDG_CURRENT_DESKTOP:-}" =~ LXQt ]]; then if command -v xdg-desktop-menu &> /dev/null; then - xdg-desktop-menu forceupdate - echo -e "${YELLOW}Please log out and log back in to see Phoenix Code in the panel.${RESET}" + xdg-desktop-menu forceupdate + echo -e "${YELLOW}Please log out and log back in to see Phoenix Code in the panel.${RESET}" else - echo -e "${RED}Failed to update LXQt menu. Please log out and log back in to see Phoenix Code in the panel.${RESET}" + echo -e "${RED}Failed to update LXQt menu. Please log out and log back in to see Phoenix Code in the panel.${RESET}" fi fi - # Set Phoenix Code as the default application for the MIME types + set_default_application echo -e "${GREEN}Installation completed successfully. Phoenix Code is now installed.${RESET}" - -} - -downloadLatestReleaseInfo() { - local release_info_file="$TMP_DIR/latest_release.json" - - if [ -f "$release_info_file" ]; then - # Only extract and echo the version number, without any additional messages - grep -Po '"tag_name":\s*"prod-app-v\K[\d.]+(?=")' "$release_info_file" - return - fi - - # Direct informational messages to stderr to avoid them being captured or displayed unexpectedly - >&2 echo -e "${GREEN}Fetching the latest release information from $GITHUB_REPO...${RESET}" - wget -qO "$release_info_file" "$API_URL" || { - >&2 echo -e "${RED}Failed to fetch the latest release information. Please check your internet connection and try again.${RESET}" - exit 1 - } - - # Only extract and echo the version number after successful download - grep -Po '"tag_name":\s*"prod-app-v\K[\d.]+(?=")' "$release_info_file" + print_keyring_hint_if_locked } -# Function to check if the architecture is 64-bit x86 -check_architecture() { - ARCHITECTURE=$(uname -m) - if [ "$ARCHITECTURE" != "x86_64" ]; then - local latestFileUrl - latestFileUrl=$(grep -oP 'https://[^"]*latest\.json' "$TMP_DIR/latest_release.json") - WGET_OPTS=$(configure_wget_options) - wget $WGET_OPTS "$TMP_DIR/latest.json" "$latestFileUrl" || { - echo -e "${RED}Failed to download the latestFile. Please check your internet connection and try again.${RESET}" - } - echo -e "${RED}This script can only be run on 64-bit x86 architecture.${RESET}" - exit 1 - fi -} -# Download Latest Release Information Function -# -# Purpose: -# Retrieves the latest release information for Phoenix Code from its GitHub repository. This function -# is designed to fetch the JSON data of the latest release using GitHub's API, allowing the script to -# determine the most recent version of Phoenix Code and any associated assets like binaries or icons. -# -# Behavior: -# 1. Checks if the release information file (`latest_release.json`) already exists in the temporary -# directory (`$TMP_DIR`). If it does, the function assumes the latest release information has already -# been fetched and proceeds to extract the version number from this file without re-downloading. -# 2. If the release information file does not exist, the function uses `wget` to download the JSON data -# from the GitHub API URL specified by `$API_URL`, which should point to the latest release endpoint -# of the Phoenix Code GitHub repository. -# 3. The JSON data is saved to `latest_release.json` in the temporary directory. -# 4. Extracts the version number from the downloaded JSON data using `grep` with a Perl-compatible regular -# expression (PCRE) that looks for the `tag_name` field. This field is expected to contain the version -# number prefixed by `prod-app-v` (e.g., `prod-app-v1.2.3`), and the function extracts the version number -# portion. -# 5. Echoes the extracted version number for use by the calling context. -# -# Considerations: -# - This function relies on external utilities `wget` and `grep` with PCRE support, which must be available -# in the execution environment. -# - The GitHub API URL (`$API_URL`) must be correctly set to the latest release endpoint of the Phoenix Code -# repository for this function to work as intended. -# - The function assumes a specific version naming convention (`prod-app-vX.Y.Z`). If this convention changes, -# the `grep` pattern used to extract the version number may need to be updated. -# - Network connectivity is required to fetch the release information from GitHub. If the script is run in an -# environment without internet access, or if GitHub is unreachable, this function will fail to retrieve the -# latest release information. -# - The function does not perform error handling for the `wget` command. If the download fails, the script may -# exit or behave unexpectedly depending on the `set -e` setting. -# -# Usage: -# This function is intended to be called during the installation or upgrade process to determine the latest -# version of Phoenix Code. The extracted version number can be used to compare with the currently installed -# version and decide whether an upgrade is necessary. -# -downloadAndInstall(){ +downloadAndInstall() { echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null check_architecture - CURRENT_GLIBC_VERSION=$(ldd --version | grep "ldd" | awk '{print $NF}') - echo "Current GLIBC version: $CURRENT_GLIBC_VERSION" - - BEST_MATCH_URL="" - BEST_MATCH_VERSION=0 - echo "Searching for a compatible binary..." - - while read -r BINARY_URL; do - BINARY_GLIBC_VERSION=$(echo "$BINARY_URL" | grep -oP 'GLIBC-\K[\d\.]+(?=\.tar\.gz)') - if awk -v bin_ver="$BINARY_GLIBC_VERSION" -v cur_ver="$CURRENT_GLIBC_VERSION" -v best_ver="$BEST_MATCH_VERSION" 'BEGIN { bin_ver += 0; cur_ver += 0; best_ver += 0; exit !(bin_ver <= cur_ver && bin_ver > best_ver) }'; then - BEST_MATCH_URL="$BINARY_URL" - BEST_MATCH_VERSION="$BINARY_GLIBC_VERSION" - echo "Found a new best match: $BEST_MATCH_URL with GLIBC version $BEST_MATCH_VERSION" - fi - done < <(grep -oP '"browser_download_url"\s*:\s*"\K[^"]*_linux_bin-GLIBC-[\d\.]+\.tar\.gz(?=")' "$TMP_DIR/latest_release.json") - if [ -z "$BEST_MATCH_URL" ]; then - echo -e "${RED}No compatible binary found for the current GLIBC version ($CURRENT_GLIBC_VERSION). Exiting installation.${RESET}" + local appimage_url + appimage_url=$(getLinuxAppImageUrl) + if [ -z "$appimage_url" ]; then + echo -e "${RED}Could not find a linux-x86_64 AppImage URL in the release info.${RESET}" exit 1 fi - echo -e "${YELLOW}Downloading the compatible binary from $BEST_MATCH_URL...${RESET}" - # Set options based on wget version - WGET_OPTS=$(configure_wget_options) - - wget $WGET_OPTS "$TMP_DIR/phoenix-code.tar.gz" "$BEST_MATCH_URL" || { - echo -e "${RED}Failed to download the binary. Please check your internet connection and try again.${RESET}" + echo -e "${YELLOW}Downloading the AppImage from $appimage_url...${RESET}" + local wget_opts + wget_opts=$(configure_wget_options) + # shellcheck disable=SC2086 + wget $wget_opts "$TMP_DIR/$APPIMAGE_NAME" "$appimage_url" || { + echo -e "${RED}Failed to download the AppImage. Please check your internet connection and try again.${RESET}" exit 1 } - # Download the icon - echo -e "Downloading the icon..." - wget $WGET_OPTS "$TMP_DIR/icon.png" "$ICON_URL" || { - echo -e "${RED}Failed to download the icon${RESET}" - exit 1 - } - echo "Extracting the binary to $TMP_DIR..." - tar -xzf "$TMP_DIR/phoenix-code.tar.gz" -C "$TMP_DIR" || { - echo -e "${RED}Failed to extract the binary. The downloaded file might be corrupt.${RESET}" + echo "Downloading the icon..." + # shellcheck disable=SC2086 + wget $wget_opts "$TMP_DIR/icon.png" "$ICON_URL" || { + echo -e "${RED}Failed to download the icon.${RESET}" exit 1 } - # Verify binary execution and install dependencies if necessary - if ! verify_and_install_dependencies; then - echo -e "${RED}Unable to successfully verify application launch. Exiting installation.${RESET}" - exit 1 - fi + chmod +x "$TMP_DIR/$APPIMAGE_NAME" + + ensure_runtime_dependencies "$TMP_DIR/$APPIMAGE_NAME" } -# Function to check wget version and configure options -configure_wget_options() { - local wget_version=$(wget --version | head -n1 | awk '{print $3}') - local major_version=$(echo "$wget_version" | cut -d. -f1) - if [[ "$major_version" -ge 2 ]]; then - echo "-c --tries=10 --timeout=30 --waitretry=5 --progress=bar --retry-connrefused -O" +# Returns 0 if the system GLIBC is >= MIN_GLIBC_VERSION, 1 otherwise. +# Uses the same ldd + awk pattern the old GLIBC-matched installer used. +glibc_compatible() { + local cur_ver + cur_ver=$(ldd --version | grep "ldd" | awk '{print $NF}') + echo "Current GLIBC version: $cur_ver" + awk -v min="$MIN_GLIBC_VERSION" -v cur="$cur_ver" \ + 'BEGIN { min += 0; cur += 0; exit !(min <= cur) }' +} + +# On systems whose GLIBC is too old for the new AppImage, disable auto-update +# in the old installation's config so it stops trying to upgrade to a binary +# that cannot run here. +disable_auto_update_old_version() { + local config_path="" + local primary="$HOME/.local/share/io.phcode/phcode.json" + local xdg="${XDG_DATA_HOME:-$HOME/.local/share}/io.phcode/phcode.json" + + if [ -f "$primary" ]; then + config_path="$primary" + elif [ "$xdg" != "$primary" ] && [ -f "$xdg" ]; then + config_path="$xdg" + fi + + if [ -z "$config_path" ]; then + config_path="$primary" + echo "Creating $config_path..." + mkdir -p "$(dirname "$config_path")" + echo '{"autoUpdate": false}' > "$config_path" + echo -e "${GREEN}Auto-update disabled in $config_path${RESET}" + return 0 + fi + + echo "Disabling auto-update in $config_path..." + if grep -q '"autoUpdate"' "$config_path"; then + sed -i 's/"autoUpdate"[[:space:]]*:[[:space:]]*[^,}]*/"autoUpdate": false/' "$config_path" + elif grep -q '"' "$config_path"; then + sed -i '0,/{/ s/{/{\n "autoUpdate": false,/' "$config_path" else - echo "-c -N --tries=10 --timeout=30 --waitretry=5 --retry-connrefused --show-progress -qO" + echo '{"autoUpdate": false}' > "$config_path" fi + echo -e "${GREEN}Auto-update disabled in $config_path${RESET}" } -# Install Function -# -# Purpose: -# Facilitates the entire installation process of Phoenix Code on the user's system. This includes -# checking for previous installations, downloading and installing the latest version, setting up -# necessary directories, and ensuring that all dependencies are met. It also handles user prompts -# for repair or reinstallation options if Phoenix Code is already installed. -# -# Behavior: -# 1. Checks if Phoenix Code is already installed by looking for specific files or directories -# associated with the installation (e.g., the invocation script in `$LINK_DIR` or the main -# directory in `$INSTALL_DIR`). If found, prompts the user with an option to repair (reinstall). -# 2. If the user opts for repair, the function proceeds to uninstall the existing installation and -# then reinstalls the application, ensuring the user ends up with the latest version. -# 3. For a fresh installation or repair, the function calls `downloadAndInstall` to fetch the latest -# release and install it. This step involves downloading the binary, setting permissions, and -# moving files to their correct locations. -# 4. After installing the binary, `copyFilesToDestination` is invoked to set up the desktop entry, -# create an invocation script, and perform other necessary post-installation configurations. -# -# Considerations: -# - The function assumes that the user has sufficient permissions to write to the target directories -# and install Phoenix Code. Administrative privileges may be required for certain operations. -# - If the repair option is chosen, all existing Phoenix Code files and configurations in the installation -# directory will be replaced. Users should ensure that any custom configurations or data are backed up -# before proceeding. -# - Network connectivity is required to download the latest version of Phoenix Code from the repository. -# - The function does not explicitly handle all potential error scenarios, such as download failures or -# permission issues. It relies on the `set -e` option to halt execution on any unhandled errors. -# -# Usage: -# This function is intended to be invoked when the script is run without specific options (e.g., not an -# uninstall or upgrade). It can be directly called from the command line when the user wishes to install -# Phoenix Code, or it may be triggered by default when the script is executed without arguments. -# + +# Temporary cleanup for files from older installer versions. +uninstallBetaAppImage() { + rm -f "$LINK_DIR"/phoenix_icon.png +} + install() { - # Check if the application is already installed + if ! glibc_compatible; then + echo -e "${RED}This system's GLIBC is older than $MIN_GLIBC_VERSION. The new AppImage cannot run here.${RESET}" + disable_auto_update_old_version + exit 1 + fi + if [ -f "$LINK_DIR/$SCRIPT_NAME" ] || [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" - # Checking if the shell has a controlling terminal if its non interactive reinstall phoenix with latest version if [ ! -t 0 ]; then echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" uninstall downloadAndInstall copyFilesToDestination else - # Simplified prompt for reinstall without detailed explanation read -r -p "Would you like to reinstall it? (y/N): " response case "$response" in [Yy]* ) - echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" - uninstall - downloadAndInstall - copyFilesToDestination - ;; + echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + uninstall + downloadAndInstall + copyFilesToDestination + ;; * ) - echo -e "${RED}Reinstall aborted by the user.${RESET}" - exit 0 - ;; + echo -e "${RED}Reinstall aborted by the user.${RESET}" + exit 0 + ;; esac fi else @@ -844,65 +573,29 @@ install() { fi } -# Temporary code to clean up earlier beta installations -function uninstallBetaAppImage() { - rm -f "$LINK_DIR"/phoenix_icon.png -} -# Upgrade Function -# -# Purpose: -# Manages the upgrade process for Phoenix Code, ensuring that the user's installation is updated -# to the latest version available. This function checks the currently installed version against -# the latest version available in the GitHub repository. If a newer version is found, it proceeds -# to download and install the update, effectively replacing the old version with the new one. -# -# Behavior: -# 1. Verifies that Phoenix Code is already installed by checking for the existence of the installation -# directory and the invocation script. If not found, it exits with an error message indicating that -# Phoenix Code must be installed before it can be upgraded. -# 2. Determines the currently installed version of Phoenix Code by invoking the binary with a version -# check command (e.g., `phoenix-code --version`) and captures the output. -# 3. Fetches the latest release information from the GitHub repository using the `downloadLatestReleaseInfo` -# function, which retrieves the version number of the latest release. -# 4. Compares the currently installed version with the latest version. If the installed version is older, -# it initiates the upgrade process by calling `downloadAndInstall`, which handles the download and -# installation of the new version. -# 5. If the currently installed version is already up to date, it informs the user that no upgrade is necessary. -# -# Considerations: -# - The function relies on the correct implementation of version checking in the Phoenix Code binary. -# The binary must support a command-line option to output its version, and the output format must be -# consistent for correct parsing and comparison. -# - Network connectivity is required to fetch the latest release information from the GitHub repository. -# The upgrade process will fail if the script cannot connect to GitHub. -# - The user must have sufficient permissions to overwrite the existing installation files and to -# execute network requests (e.g., downloading the latest release). -# - The upgrade process replaces the existing installation files. Users should ensure that any -# necessary backups or custom configurations are saved before proceeding with the upgrade. -# -# Usage: -# This function is intended to be called when the user explicitly wants to upgrade their installation -# of Phoenix Code to the latest version. It can be triggered by passing an `--upgrade` option to the -# script, as defined in the script's main case statement handling command-line arguments. -# upgrade() { echo -e "${YELLOW}Checking for upgrades to Phoenix Code...${RESET}" - # Ensure Phoenix Code is installed + if ! glibc_compatible; then + echo -e "${RED}This system's GLIBC is older than $MIN_GLIBC_VERSION. The new AppImage cannot run here.${RESET}" + disable_auto_update_old_version + exit 1 + fi + if [ ! -f "$LINK_DIR/$SCRIPT_NAME" ] && [ ! -d "$INSTALL_DIR" ]; then echo -e "${RED}Phoenix Code is not installed. Please install it first.${RESET}" exit 1 fi - # Get the current installed version - CURRENT_VERSION=$("$INSTALL_DIR/phoenix-code" --version) - echo "Current installed version: $CURRENT_VERSION" - LATEST_VERSION=$(downloadLatestReleaseInfo) - # Now LATEST_VERSION should only contain the version number without extra messages - echo "Latest available version: $LATEST_VERSION" + local current_version + current_version=$("$INSTALL_DIR/$APPIMAGE_NAME" --version 2>/dev/null || true) + echo "Current installed version: ${current_version:-unknown}" + + local latest_version + latest_version=$(downloadLatestReleaseInfo) + echo "Latest available version: $latest_version" - # Compare versions and upgrade if the latest version is greater - if [ "$(printf '%s\n' "$LATEST_VERSION" "$CURRENT_VERSION" | sort -V | tail -n1)" = "$LATEST_VERSION" ] && [ "$LATEST_VERSION" != "$CURRENT_VERSION" ]; then + if [ -n "$latest_version" ] && [ "$(printf '%s\n' "$latest_version" "$current_version" | sort -V | tail -n1)" = "$latest_version" ] && [ "$latest_version" != "$current_version" ]; then echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" downloadAndInstall uninstall @@ -911,48 +604,12 @@ upgrade() { else echo "Your Phoenix Code installation is up-to-date." fi - } -# Uninstall Function -# -# Purpose: -# Handles the removal of Phoenix Code from the user's system. This function is responsible for -# cleaning up all files, directories, and links created during the installation process, effectively -# reverting any changes made by the installer script. It ensures that Phoenix Code and its components -# are uninstalled cleanly, leaving no residual files or configurations. -# -# Behavior: -# 1. Checks for and removes the invocation script located in the user's binary directory (`$LINK_DIR`). -# This step prevents the Phoenix Code command from being accessible after uninstallation. -# 2. Deletes the desktop entry file (`$DESKTOP_ENTRY`) to remove Phoenix Code from application menus -# and launchers. This step is crucial for desktop environments to recognize that the application has been uninstalled. -# 3. Updates the desktop database, if necessary, to reflect the removal of the Phoenix Code desktop entry. -# This may involve commands like `update-desktop-database` or `kbuildsycoca5`, depending on the desktop environment. -# 4. Removes the Phoenix Code installation directory (`$INSTALL_DIR`) and all its contents, including -# the main binary, configuration files, and any other related files placed during installation. -# 5. Prints a confirmation message indicating that the uninstallation process has been completed successfully. -# -# Considerations: -# - The function assumes that the paths stored in `$LINK_DIR`, `$DESKTOP_ENTRY`, and `$INSTALL_DIR` accurately -# reflect the locations used during the installation. If these variables are incorrect, the uninstallation -# process may not remove all components. -# - Administrative privileges may be required for some operations, especially if Phoenix Code was installed -# in system-wide directories. -# - Users should be advised to back up any important data or configurations related to Phoenix Code before -# initiating the uninstallation process, as this function will remove all associated files without recovery options. -# - The function does not provide a rollback mechanism. Once the uninstallation is initiated, the process cannot -# be reversed through this script. -# -# Usage: -# This function is intended to be invoked when the user wishes to completely remove Phoenix Code from their system. -# It can be triggered by passing an `--uninstall` option to the script, as defined in the script's main case statement -# handling command-line arguments. Users should be prompted to confirm their intention to uninstall before this -# function is executed to prevent accidental data loss. -# + uninstall() { echo -e "${YELLOW}Starting uninstallation of Phoenix Code...${RESET}" uninstallBetaAppImage - # Remove the invocation script from ~/.local/bin + if [ -f "$LINK_DIR/$SCRIPT_NAME" ]; then echo -e "${YELLOW}Removing invocation script from $LINK_DIR...${RESET}" rm "$LINK_DIR/$SCRIPT_NAME" @@ -960,40 +617,33 @@ uninstall() { echo -e "${RED}Invocation script not found in $LINK_DIR. Skipping...${RESET}" fi - # Delete the desktop entry if [ -f "$DESKTOP_ENTRY" ]; then echo -e "${YELLOW}Removing desktop entry...${RESET}" rm "$DESKTOP_ENTRY" - - # Update the desktop database for GNOME, Unity, XFCE, etc. - echo -e "${YELLOW}Updating desktop database...${RESET}" if command -v update-desktop-database &> /dev/null; then - update-desktop-database "$DESKTOP_DIR" + update-desktop-database "$DESKTOP_DIR" fi - - # Update the KDE desktop database if KDE is in use - if [ "$XDG_CURRENT_DESKTOP" = "KDE" ]; then - if command -v kbuildsycoca5 &> /dev/null; then - kbuildsycoca5 - fi + if [ "${XDG_CURRENT_DESKTOP:-}" = "KDE" ]; then + if command -v kbuildsycoca5 &> /dev/null; then + kbuildsycoca5 + fi fi - - if [[ "$XDG_CURRENT_DESKTOP" =~ LXQt ]]; then + if [[ "${XDG_CURRENT_DESKTOP:-}" =~ LXQt ]]; then if command -v xdg-desktop-menu &> /dev/null; then - xdg-desktop-menu forceupdate + xdg-desktop-menu forceupdate fi fi else - echo -e "${RED}Desktop entry not found. Skipping...${RESET}" + echo -e "${RED}Desktop entry not found. Skipping...${RESET}" fi - # Remove the installation directory and its contents if [ -d "$INSTALL_DIR" ]; then echo -e "${YELLOW}Removing installation directory and its contents...${RESET}" rm -rf "$INSTALL_DIR" else echo -e "${RED}Installation directory not found. Skipping...${RESET}" fi + echo -e "${GREEN}Uninstallation of Phoenix Code completed.${RESET}" } @@ -1009,7 +659,6 @@ show_help() { echo "Without any options, the script will install Phoenix Code." } -# Check for GUI session by looking for DISPLAY or WAYLAND_DISPLAY variables if [ -z "${DISPLAY:-}" ] && [ -z "${WAYLAND_DISPLAY:-}" ]; then echo "This script should only be run from terminals in GUI sessions." exit 1 @@ -1017,22 +666,20 @@ fi case "${1-}" in -h|--help) - show_help # Function to show help + show_help ;; --uninstall) - uninstall # Function to uninstall + uninstall ;; --upgrade) - upgrade # Function to upgrade + upgrade ;; "") - # This case handles when $1 is unset (acts as a default action) - install # Function to install + install ;; *) - # This case handles unexpected arguments echo "Invalid option: $1" >&2 - show_help # Assuming you have a function to show usage information + show_help exit 1 ;; esac From 1e87b516726d0abc3e6f5cd2209a0ff91de27ce5 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 May 2026 20:00:54 +0530 Subject: [PATCH 844/864] fix: download before uninstall and point prod installer to stable update URL Swap uninstall/download order in reinstall path so a failed download doesn't leave the user with nothing installed. Rename downloadAndInstall to downloadAndVerifyDeps to reflect what the function actually does. Update prod installer URL to update-latest-stable-prod.json. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/linux/installer-latest-experimental-build.sh | 10 +++++----- docs/linux/installer.sh | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/linux/installer-latest-experimental-build.sh b/docs/linux/installer-latest-experimental-build.sh index e71f3ef9..ecde9707 100755 --- a/docs/linux/installer-latest-experimental-build.sh +++ b/docs/linux/installer-latest-experimental-build.sh @@ -456,7 +456,7 @@ EOF print_keyring_hint_if_locked } -downloadAndInstall() { +downloadAndVerifyDeps() { echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null check_architecture @@ -549,16 +549,16 @@ install() { echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" if [ ! -t 0 ]; then echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + downloadAndVerifyDeps uninstall - downloadAndInstall copyFilesToDestination else read -r -p "Would you like to reinstall it? (y/N): " response case "$response" in [Yy]* ) echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + downloadAndVerifyDeps uninstall - downloadAndInstall copyFilesToDestination ;; * ) @@ -568,7 +568,7 @@ install() { esac fi else - downloadAndInstall + downloadAndVerifyDeps copyFilesToDestination fi } @@ -597,7 +597,7 @@ upgrade() { if [ -n "$latest_version" ] && [ "$(printf '%s\n' "$latest_version" "$current_version" | sort -V | tail -n1)" = "$latest_version" ] && [ "$latest_version" != "$current_version" ]; then echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" - downloadAndInstall + downloadAndVerifyDeps uninstall copyFilesToDestination echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index e71f3ef9..33e3678c 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -25,7 +25,7 @@ set -euo pipefail # AppImage launch fallbacks. DESKTOP_DIR=$HOME/.local/share/applications -UPDATE_JSON_URL="https://updates.phcode.io/tauri/update-latest-experimental-build.json" +UPDATE_JSON_URL="https://updates.phcode.io/tauri/update-latest-stable-prod.json" ICON_URL="https://updates.phcode.io/icons/phoenix_icon.png" INSTALL_DIR="$HOME/.phoenix-code" LINK_DIR="$HOME/.local/bin" @@ -456,7 +456,7 @@ EOF print_keyring_hint_if_locked } -downloadAndInstall() { +downloadAndVerifyDeps() { echo "Using temporary directory $TMP_DIR for processing" downloadLatestReleaseInfo > /dev/null check_architecture @@ -549,16 +549,16 @@ install() { echo -e "${YELLOW}Phoenix Code appears to be already installed.${RESET}" if [ ! -t 0 ]; then echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + downloadAndVerifyDeps uninstall - downloadAndInstall copyFilesToDestination else read -r -p "Would you like to reinstall it? (y/N): " response case "$response" in [Yy]* ) echo -e "${GREEN}Reinstalling Phoenix Code...${RESET}" + downloadAndVerifyDeps uninstall - downloadAndInstall copyFilesToDestination ;; * ) @@ -568,7 +568,7 @@ install() { esac fi else - downloadAndInstall + downloadAndVerifyDeps copyFilesToDestination fi } @@ -597,7 +597,7 @@ upgrade() { if [ -n "$latest_version" ] && [ "$(printf '%s\n' "$latest_version" "$current_version" | sort -V | tail -n1)" = "$latest_version" ] && [ "$latest_version" != "$current_version" ]; then echo -e "${YELLOW}A newer version of Phoenix Code is available. Proceeding with the upgrade...${RESET}" - downloadAndInstall + downloadAndVerifyDeps uninstall copyFilesToDestination echo -e "${GREEN}Upgrade completed successfully. Phoenix Code has been updated to the latest version.${RESET}" From a47bd3fd9504b733547d77762d4079ceabac8f34 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 27 May 2026 14:37:09 +0000 Subject: [PATCH 845/864] ci: update phcode version to 5.1.21 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 7bccd983..b85e7a0b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.20", + "version": "5.1.21", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "c66c9ce7c54bb73d2785be089dddd96f4c8f1963" + "commit": "ccb68667de575fd57a7593f8b6de416330e1952f" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index c1487de2..0bc88c29 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.20", + "version": "5.1.21", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5c687d58..47cf3e0c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.20" +version = "5.1.21" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index cd6af7cf..eb7a83f5 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.20" + "version": "5.1.21" }, "tauri": { "allowlist": { From 97f68e755931c9d3961454c800155b1cf478d9ab Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 May 2026 22:49:43 +0530 Subject: [PATCH 846/864] fix: allow npm install to succeed when node binary was previously extracted The adm-zip extractEntryTo call in downloadNodeBinary.js did not pass the overwrite flag, causing postinstall to fail with "Target file already exists" on repeat runs. Co-Authored-By: Claude Opus 4.7 (1M context) --- src-build/downloadNodeBinary.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-build/downloadNodeBinary.js b/src-build/downloadNodeBinary.js index 2568517e..445d8e71 100644 --- a/src-build/downloadNodeBinary.js +++ b/src-build/downloadNodeBinary.js @@ -187,7 +187,7 @@ function unzipFile(zipFilePath, extractPath) { } if (!zipEntry.isDirectory) { - zip.extractEntryTo(zipEntry.entryName, extractPath); + zip.extractEntryTo(zipEntry.entryName, extractPath, /*maintainEntryPath*/true, /*overwrite*/true); } }); From cddeee66b5cb6a375b6bdf7a404d4ae61e3f3aad Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 May 2026 22:50:38 +0530 Subject: [PATCH 847/864] fix(tauri): correct screenshot rect on Windows under DPI scaling GDI APIs (GetClientRect, PrintWindow, GetDIBits) operate in physical pixels for DPI-aware processes, but the JS caller sends the capture rect in CSS pixels (scaled only by the webview zoom factor, not the OS DPI). At Windows display scaling >100%, this produced screenshots that were both shifted and undersized. Multiply the incoming rect by window.scale_factor() (the OS DPI scale, e.g. 1.25 at 125% scaling) before clamping to the physical client area. macOS is unaffected because WKSnapshotConfiguration.setRect takes view points, which map 1:1 to CSS pixels. Electron (Linux) is unaffected because capturePage already accepts CSS-pixel rects. --- src-tauri/src/main.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 03ca5d0c..1947585d 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -538,6 +538,11 @@ fn capture_page_windows(window: tauri::Window, rect: Option) -> Res }; use winapi::shared::windef::{RECT, HGDIOBJ}; + // GDI works in physical pixels, but the JS caller sends the rect in CSS pixels + // (scaled only by the webview zoom factor, not by the OS DPI). Convert by + // multiplying with the window's OS scale factor (1.25 at Windows 125% scaling). + let dpi_scale = window.scale_factor().unwrap_or(1.0); + unsafe { let hwnd = window.hwnd().map_err(|e| e.to_string())?; let hwnd = hwnd.0 as winapi::shared::windef::HWND; @@ -584,12 +589,13 @@ fn capture_page_windows(window: tauri::Window, rect: Option) -> Res chunk.swap(0, 2); } - // Extract the requested region (or full image) + // Extract the requested region (or full image). Convert the incoming + // CSS-pixel rect into physical pixels using the OS DPI scale factor. let (cap_x, cap_y, cap_w, cap_h) = if let Some(r) = &rect { - let x = (r.x as i32).max(0).min(full_width); - let y = (r.y as i32).max(0).min(full_height); - let w = (r.width as i32).min(full_width - x).max(0); - let h = (r.height as i32).min(full_height - y).max(0); + let x = ((r.x * dpi_scale).round() as i32).max(0).min(full_width); + let y = ((r.y * dpi_scale).round() as i32).max(0).min(full_height); + let w = ((r.width * dpi_scale).round() as i32).min(full_width - x).max(0); + let h = ((r.height * dpi_scale).round() as i32).min(full_height - y).max(0); (x, y, w, h) } else { (0, 0, full_width, full_height) From 1d1644080a523cc0acf97a37a5ea9ae5b4b2af02 Mon Sep 17 00:00:00 2001 From: abose Date: Wed, 27 May 2026 22:51:26 +0530 Subject: [PATCH 848/864] ci: sync lock files with version 5.1.21 Co-Authored-By: Claude Opus 4.7 (1M context) --- package-lock.json | 4 ++-- src-electron/package-lock.json | 4 ++-- src-tauri/Cargo.lock | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0a260352..88ca6de9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-ide", - "version": "5.1.8", + "version": "5.1.21", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-ide", - "version": "5.1.8", + "version": "5.1.21", "hasInstallScript": true, "devDependencies": { "@tauri-apps/cli": "1.6.3", diff --git a/src-electron/package-lock.json b/src-electron/package-lock.json index 776f661f..d0ffd691 100644 --- a/src-electron/package-lock.json +++ b/src-electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "phoenix-code-electron-shell", - "version": "5.1.8", + "version": "5.1.21", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "phoenix-code-electron-shell", - "version": "5.1.8", + "version": "5.1.21", "dependencies": { "keytar": "^7.9.0" }, diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index dfa1a4cd..bd7c6be2 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -3398,7 +3398,7 @@ dependencies = [ [[package]] name = "phoenix-code-ide" -version = "5.1.4" +version = "5.1.21" dependencies = [ "aes-gcm", "backtrace", From 06cb0d3f25e43a5698cd199d8deaca4f130529f8 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Wed, 27 May 2026 19:16:58 +0000 Subject: [PATCH 849/864] ci: update phcode version to 5.1.22 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b85e7a0b..4eada5a2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.21", + "version": "5.1.22", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "ccb68667de575fd57a7593f8b6de416330e1952f" + "commit": "36969452b10ea721de4ec00e0f038b04d0b2a581" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 0bc88c29..51a897da 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.21", + "version": "5.1.22", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 47cf3e0c..d9a401a8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.21" +version = "5.1.22" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index eb7a83f5..f84bcc1b 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.21" + "version": "5.1.22" }, "tauri": { "allowlist": { From 32c8d8441361843cc532d1712208ac6ef1b7a4a2 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 28 May 2026 01:12:56 +0530 Subject: [PATCH 850/864] fix(tauri): remove server-side DPI scaling from screenshot capture The JS caller now sends the rect in physical pixels on Windows (multiplied by devicePixelRatio), so the Rust side no longer needs to apply window.scale_factor(). This avoids potential disagreement between the browser's devicePixelRatio and Tauri's scale_factor on some Windows devices. --- src-tauri/src/main.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 1947585d..142fd705 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -538,11 +538,6 @@ fn capture_page_windows(window: tauri::Window, rect: Option) -> Res }; use winapi::shared::windef::{RECT, HGDIOBJ}; - // GDI works in physical pixels, but the JS caller sends the rect in CSS pixels - // (scaled only by the webview zoom factor, not by the OS DPI). Convert by - // multiplying with the window's OS scale factor (1.25 at Windows 125% scaling). - let dpi_scale = window.scale_factor().unwrap_or(1.0); - unsafe { let hwnd = window.hwnd().map_err(|e| e.to_string())?; let hwnd = hwnd.0 as winapi::shared::windef::HWND; @@ -589,13 +584,14 @@ fn capture_page_windows(window: tauri::Window, rect: Option) -> Res chunk.swap(0, 2); } - // Extract the requested region (or full image). Convert the incoming - // CSS-pixel rect into physical pixels using the OS DPI scale factor. + // The JS caller already sends the rect in physical pixels (it multiplies + // getBoundingClientRect() by devicePixelRatio on Windows). Just clamp to + // the actual client area from GetClientRect, which is also in physical pixels. let (cap_x, cap_y, cap_w, cap_h) = if let Some(r) = &rect { - let x = ((r.x * dpi_scale).round() as i32).max(0).min(full_width); - let y = ((r.y * dpi_scale).round() as i32).max(0).min(full_height); - let w = ((r.width * dpi_scale).round() as i32).min(full_width - x).max(0); - let h = ((r.height * dpi_scale).round() as i32).min(full_height - y).max(0); + let x = (r.x as i32).max(0).min(full_width); + let y = (r.y as i32).max(0).min(full_height); + let w = (r.width as i32).min(full_width - x).max(0); + let h = (r.height as i32).min(full_height - y).max(0); (x, y, w, h) } else { (0, 0, full_width, full_height) From dcd8521772e776db8f076d5a705056eedea87e7f Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 28 May 2026 09:17:21 +0000 Subject: [PATCH 851/864] ci: update phcode version to 5.1.23 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 4eada5a2..24c78991 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.22", + "version": "5.1.23", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "36969452b10ea721de4ec00e0f038b04d0b2a581" + "commit": "e08463b35a48a1e1426d5e7ef2c67b1041c98816" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 51a897da..ab84bd66 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.22", + "version": "5.1.23", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index d9a401a8..b834e16b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.22" +version = "5.1.23" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f84bcc1b..5022f5fd 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.22" + "version": "5.1.23" }, "tauri": { "allowlist": { From 1a6b92c05ef34f0ea44d5db8c9dd69dce317b7a1 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Thu, 28 May 2026 14:25:39 +0000 Subject: [PATCH 852/864] ci: update phcode version to 5.1.24 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 24c78991..8338ecfd 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.23", + "version": "5.1.24", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "e08463b35a48a1e1426d5e7ef2c67b1041c98816" + "commit": "f5e96376c01d264b6f517c3c63d22adc22a97a42" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index ab84bd66..a2fd3543 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.23", + "version": "5.1.24", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b834e16b..35a48c23 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.23" +version = "5.1.24" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 5022f5fd..03c7481d 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.23" + "version": "5.1.24" }, "tauri": { "allowlist": { From 65df0547bac0fd9ccd0b64af48511810ca17f832 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 28 May 2026 18:52:08 +0000 Subject: [PATCH 853/864] ci: tauri release update notification json --- docs/install.json | 9 +++--- docs/tauri/update-latest-stable-prod.json | 34 +++++++++++++---------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/docs/install.json b/docs/install.json index fa11c15b..81add328 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,8 +1,9 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_x64.dmg", - "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa" + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_x64.dmg", + "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa", + "linux_appimage": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/phoenix-code_5.1.24.AppImage" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 389dba8c..6cce28f2 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,31 +1,35 @@ { - "version": "5.0.5", - "notes": "2026 January release (5.0) of Phoenix Code is now available for download at [phcode.io](https://phcode.io).\r\n\r\nOur biggest update yet - introducing `Phoenix Pro` and major upgrades like `Live Preview Edit`, `Emmet`, `Tab Bar`, and `Custom Snippets`.\r\n\r\n## Phoenix Pro - A Sustainable Future\r\n\r\nPhoenix Code has been free and open source from day one - and **everything you’ve used so far will remain free forever**, including **Live Preview**.\r\n\r\nWe’re a small, full-time indie team with **no VC backing**, building Phoenix Code because we believe the web deserves a code editor that’s genuinely **simple and joyful to use**. We tried to sustain development through community donations ([Open Collective](https://opencollective.com/phoenix-ide)), but over the last few years it hasn’t been enough to support full-time work - and we reached a hard choice: slow down drastically, or find a sustainable path that keeps Phoenix Code healthy.\r\n\r\nSo we’re introducing **Phoenix Pro** as an *optional* way to support Phoenix Code’s future - with **one Pro feature: Live Preview Edit**.\r\nIf Phoenix Code has helped you, Phoenix Pro is a way to help keep the project moving forward.\r\n\r\nStudents & educators get **Phoenix Pro for Education** at no cost, because we want classrooms to have easy access to modern, easy-to-use development tooling. [Read More](https://docs.phcode.dev/docs/phoenix-pro-school)\r\n\r\n## Live Preview Edit\r\n\r\n*Included with Phoenix Pro.*\r\n\r\n**Live Preview Edit** lets you make changes directly on your page — and updates your source code instantly.\r\n\r\nEdit text, links, and images. Drag & drop to rearrange elements. Cut, copy, paste, and use measurement tools to place things precisely.\r\n\r\nLearn more: [Live Preview Edit](https://docs.phcode.dev/docs/Pro%20Features/live-preview-edit), [Image Gallery](https://docs.phcode.dev/docs/Pro%20Features/image-gallery), [Measurements](https://docs.phcode.dev/docs/Pro%20Features/measurements).\r\n\r\n![image](https://github.com/user-attachments/assets/5ef26ba0-12bd-4145-9e30-d404aabe5092)\r\n\r\n## Emmet\r\n\r\n**Emmet** one of our most requested features is finally here.\r\n\r\nWrite Emmet abbreviations and Phoenix Code shows you hints. Select a hint to expand it into a full code snippet. Code faster than ever. [Read More](https://docs.phcode.dev/docs/Features/emmet)\r\n\r\n![emmet](https://github.com/user-attachments/assets/fe767274-cb03-491c-9cf8-bfbc560490d6)\r\n\r\n## Tab Bar\r\n\r\nTab Bar is here. View all your open files at the top of the editor and switch between them instantly.\r\n\r\nChoose what works for you - Tab Bar, Working Files, or both at the same time. [Read More](https://docs.phcode.dev/docs/file-management#tab-bar)\r\n\r\n![tab bar](https://github.com/user-attachments/assets/3febc149-d3e6-44a7-bbe6-f305e7726703)\r\n\r\n## Custom Snippets\r\n\r\nDefine your own code hints with Custom Snippets.\r\n\r\nCreate hints that expand into full code blocks. You can also add cursor positions so Phoenix Code places your cursor exactly where you need it after expansion. [Read More](https://docs.phcode.dev/docs/Features/custom-snippets)\r\n\r\n![snippets](https://github.com/user-attachments/assets/b3ff85db-82db-468b-ba65-c1878b371292)\r\n\r\n## Collapse Folders\r\n\r\nAfter working for some time, your project structure gets messy with lots of open and nested directories.\r\n\r\nBut no worries now. Phoenix Code supports Collapse All Folders, which lets you reset your view by collapsing all expanded folders to their root level in one click. [Read More](https://docs.phcode.dev/docs/file-management#collapse-all-folders)\r\n\r\n![collapse](https://github.com/user-attachments/assets/e230e87f-25da-4bd4-a43c-91f13398acee)\r\n\r\n## Notable changes and fixes\r\n\r\n- Improved Live Preview to support internal stylesheets and SVGs better than before.\r\n- Smarter color hints. Phoenix Code prioritizes your previously used colors. [Read More](https://docs.phcode.dev/docs/editing-colors#color-hints)\r\n- Git markers now appear in the scrollbar, making it easier to locate changes in a file.\r\n- Improved Git so that it doesn't show stale project status.\r\n- Reduced the number of popups shown when first installing Phoenix.\r\n- Fixed an issue where macOS/iOS and browser autocorrect or smart keyboards altered filenames during renames.\r\n- Added a dialog to notify users when they have security compromised extensions installed.\r\n- Slowed down the Quick View popup on hover as it was interfering with user workflows.\r\n- Fixed ghost image appearing in Safari when dragging from CodeMirror.\r\n- Long names in Working Files are now truncated for better readability.\r\n- Added Horizontal Scroll support. Use Shift + mouse scroll.\r\n\r\n## All changes\r\n\r\nPlease see [this link](https://github.com/phcode-dev/phoenix/commits/main/?since=2025-01-30&until=2026-01-18) for a full list of changes\r\nin GitHub.\r\n\r\n## A Request from the Phoenix Team:\r\n\r\n- **Share your feedback:** https://github.com/orgs/phcode-dev/discussions\r\n- **Spread the word** about Phoenix to friends and colleagues.\r\n\r\nWith gratitude,\r\n\r\nThe Phoenix Team\r\n", - "pub_date": "2026-01-19T16:14:31.777Z", + "version": "5.1.24", + "notes": "2026 May release (5.1) of Phoenix Code is now available for download at [phcode.io](https://phcode.io). \r\n\r\nOur biggest update yet - this release brings AI into the editor with [Claude Code](#try-ideas-build-pages-and-fix-issues-with-ai), a new [Design Mode](#design-mode) for visual editing, a rich [Markdown editor](#rich-markdown-editor), a built-in [terminal](#built-in-terminal), responsive [device previews](#view-your-page-at-any-device-size), a [rebuilt Linux app](#linux), and a fresh new look with the [Phoenix Neo](#phoenix-neo-themes) themes.\r\n\r\n\r\n## [Try ideas, build pages, and fix issues with AI](https://docs.phcode.dev/app-links/ai-chat)\r\n\r\nPhoenix Code now includes an AI assistant powered by Claude Code - one that sees what you see, not just your code. Try ideas, make changes, and refine your work just by chatting.\r\n\r\nAttach files or capture a screenshot to show the AI exactly what you mean. It stays out of your way until you need it, so you can stay focused on the creative work.\r\n\r\n> This feature is available only in desktop apps.\r\n\r\n![](https://docs-images.phcode.dev/in-app/pro-aiChat.png)\r\n\r\n## [Design Mode](https://docs.phcode.dev/app-links/design-mode)\r\n\r\nFocus fully on your content while your code stays out of the way. Work side by side with AI and Live Preview. Edit content visually - whether you’re building web pages or Markdown documents.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-designMode.png)\r\n\r\n\r\n## [Rich Markdown Editor](https://docs.phcode.dev/app-links/markdown-editor)\r\n\r\nEdit Markdown like a document in Live Preview. Now it’s easy to add images - just paste or pick one from your device, like in Google Docs or Word.\r\n\r\nFormat text, edit tables, and add diagrams with real-time sync between code and live preview. An easier way to create Markdown files that you can share anywhere.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-markdownEditor.png)\r\n\r\n## [Live Preview Edit Upgrades](https://docs.phcode.dev/app-links/live-preview-edit)\r\n\r\nFormat text with bold, italic, and more. Add elements and update tags, classes, and attributes - all directly in Live Preview.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-controlBox.png)\r\n\r\n## [View your page at any device size](https://docs.phcode.dev/app-links/resize-ruler)\r\n\r\nSwitch between popular phones, tablets, and desktops with a single click to see how your page looks at that size. \r\nPhoenix Code also picks up your CSS `@media` breakpoints so you can jump straight to where your layout switches.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-resizeRuler.png)\r\n\r\n## [Built-in Terminal](https://docs.phcode.dev/app-links/terminal)\r\n\r\nRun commands right next to your code in the new built-in terminal. \r\nPhoenix Code allows you to open multiple terminal tabs with your preferred shell.\r\n\r\n> This feature is available only in desktop apps.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/terminal.png)\r\n\r\n## [All Your Tools, One Place](https://docs.phcode.dev/app-links/git)\r\n\r\nA new tools drawer brings Git, Terminal, Problems, and more into one place. Switch between them instantly without panels getting in your way.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/bottom-panel.png)\r\n\r\n## New Linux Platform\r\n\r\nPhoenix Code for Linux has been rebuilt from the ground up.\r\n\r\nThe previous Linux app was harder to install and didn’t match the experience we wanted to deliver. We heard that feedback loud and clear. This release is powered by a brand-new Linux platform, bringing faster performance, easier installation, and a desktop experience that now stands alongside Windows and macOS.\r\n\r\n## [Phoenix Neo Themes](https://docs.phcode.dev/app-links/themes)\r\n\r\nMeet Phoenix Dark Neo and Phoenix Light Neo - the redesigned default themes with a cleaner, modernized look.\r\n\r\n> Switch between them anytime from `View > Themes...`.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/themes-settings.png)\r\n", + "pub_date": "2026-05-28T16:27:42.982Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5YL25INWhMOGpPd01XNTVNU0lYWHZsbWdTdTRISmdUQlMwb3pvMVJMWDl2OEkwMFRGczZadUhwN2RWMFBMeFBpU2ViYVJVQlFVSXNMYjNSMW5CZHdBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM3NDkyCWZpbGU6UGhvZW5peCBDb2RlXzUuMC41X3g2NC1zZXR1cC5uc2lzLnppcAo0VUxEMkt2OE1TMzFNdzMvYnNzakkxbnFuOFZhWTBuc3krN2dwcStjZVhRcm9zVk1SQ0xvVnR5bXpxZ2haaEh6S1hEaldpZGJLc2FtSXNCYU1laHhDZz09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxVNHRBcGJrRXIyK0FqT0E5dloyK0dkQnVPM1BwTTRkS05HZHpzTTgwV3dlVVZ1Rzk1aWMzeFBqUktjamNFQlJjNmNKeDRXbkhqL2FMVW5QeEtXVndZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTgyOTM1CWZpbGU6UGhvZW5peCBDb2RlXzUuMS4yNF94NjQtc2V0dXAubnNpcy56aXAKdndmMHhOWU16bjJuNXpoZ2ZNcnNzZjFsSWxoM213L1dNc3BHL09rSkRBaEN3dzVZaDZncHhtZ3o2STBCQnRQc0s1OUE2Skd2bndSbUJJbTFRU0N2RGc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_x64-setup.nsis.zip" }, "windows-x86_64-nsis": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5YL25INWhMOGpPd01XNTVNU0lYWHZsbWdTdTRISmdUQlMwb3pvMVJMWDl2OEkwMFRGczZadUhwN2RWMFBMeFBpU2ViYVJVQlFVSXNMYjNSMW5CZHdBPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM3NDkyCWZpbGU6UGhvZW5peCBDb2RlXzUuMC41X3g2NC1zZXR1cC5uc2lzLnppcAo0VUxEMkt2OE1TMzFNdzMvYnNzakkxbnFuOFZhWTBuc3krN2dwcStjZVhRcm9zVk1SQ0xvVnR5bXpxZ2haaEh6S1hEaldpZGJLc2FtSXNCYU1laHhDZz09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_5.0.5_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxVNHRBcGJrRXIyK0FqT0E5dloyK0dkQnVPM1BwTTRkS05HZHpzTTgwV3dlVVZ1Rzk1aWMzeFBqUktjamNFQlJjNmNKeDRXbkhqL2FMVW5QeEtXVndZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTgyOTM1CWZpbGU6UGhvZW5peCBDb2RlXzUuMS4yNF94NjQtc2V0dXAubnNpcy56aXAKdndmMHhOWU16bjJuNXpoZ2ZNcnNzZjFsSWxoM213L1dNc3BHL09rSkRBaEN3dzVZaDZncHhtZ3o2STBCQnRQc0s1OUE2Skd2bndSbUJJbTFRU0N2RGc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRQYWlKenFodTRUTThzUDh2d3pqby9yTUFxQmRsSm5nOVRFazNQdHhDWHc4YXcwZWxMOVdjek00RDJqNTFSYWNNZ3VJOVUrUEkzbHJ5WXh2NWlWcXdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM4NzE1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKU2NYRGJKVWdnMzY2dWVjNGZ3YWpFZWhlUzZYeXAzTXN3NmM2bVAvYjFQb2t0OE1YNG9NV0o1NVlJMmZKSmdVVFllUkRkaGFlejVDUzlFY1NwTHRoQ3c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmpxQXJTNExwYk9vTkxmaDd0SnlyVFBKQkVvYk5Qa01XenFlTy9vTmlhbXNIVWErSG02bTNUd0FwaFBSZE92MXNYS09kUlJ2WWZVVHFVWndEbVhYUmc4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTg0MTcxCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdk1uM0RMVEVZVUJWU1E5Q3RFQ3FPWU9NQmozNWVFVHFjNmtPcWgza2FwVVVIK3kwNjB4ek56WTZVR05IMC8weGcvUW1UNkJQVHdFTmxKMVd2YnkxQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_x64.app.tar.gz" }, "darwin-x86_64-app": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRQYWlKenFodTRUTThzUDh2d3pqby9yTUFxQmRsSm5nOVRFazNQdHhDWHc4YXcwZWxMOVdjek00RDJqNTFSYWNNZ3VJOVUrUEkzbHJ5WXh2NWlWcXdVPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM4NzE1CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKU2NYRGJKVWdnMzY2dWVjNGZ3YWpFZWhlUzZYeXAzTXN3NmM2bVAvYjFQb2t0OE1YNG9NV0o1NVlJMmZKSmdVVFllUkRkaGFlejVDUzlFY1NwTHRoQ3c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmpxQXJTNExwYk9vTkxmaDd0SnlyVFBKQkVvYk5Qa01XenFlTy9vTmlhbXNIVWErSG02bTNUd0FwaFBSZE92MXNYS09kUlJ2WWZVVHFVWndEbVhYUmc4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTg0MTcxCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdk1uM0RMVEVZVUJWU1E5Q3RFQ3FPWU9NQmozNWVFVHFjNmtPcWgza2FwVVVIK3kwNjB4ek56WTZVR05IMC8weGcvUW1UNkJQVHdFTmxKMVd2YnkxQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnFwY0ZBWEZiWGtRcVVkOTZHMWY5K2hJMG1VVHA5OXFvRUlBbExXNTdWcUJabzluL0tGTXNkR2xjTDQxSlp4TXY2S015NGRmUmliRWZTaVI2ZDhvREFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM5MjYzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKanA4TVZqRHgycGpKVGJyZEk4WEtoMndOYmN3dnl0ZEdTeGpBTkZmVEx6R1o1bThIcVdHVlpROG1YamplVVpERHgyQkoxamt0TE9Ua3RhZ1RVU3VhQ3c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVsUlVYRCtLMncwenlNN05NTU1JT1lFa29IYVFZRzhkczJZVXBsWi9RZUo5M2xpN1EyN1NISnVhTnZLVlBjOGhTMjBVR2N5RVh0NDhialBKSHZSNUE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTg1NjQxCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKNy9WMjJDdmQwYTZLUy83ZXk2K1dkMFh3Q2k2eS9sUHIxNkxTbVVxaXlMdDdZanN1dzJNZ1lGd1UzWDZyRTZnWlZtQjBoS3prc0hidU92V2xPTFFwQ2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_aarch64.app.tar.gz" }, "darwin-aarch64-app": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnFwY0ZBWEZiWGtRcVVkOTZHMWY5K2hJMG1VVHA5OXFvRUlBbExXNTdWcUJabzluL0tGTXNkR2xjTDQxSlp4TXY2S015NGRmUmliRWZTaVI2ZDhvREFRPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzY4ODM5MjYzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKanA4TVZqRHgycGpKVGJyZEk4WEtoMndOYmN3dnl0ZEdTeGpBTkZmVEx6R1o1bThIcVdHVlpROG1YamplVVpERHgyQkoxamt0TE9Ua3RhZ1RVU3VhQ3c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.0.5/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVsUlVYRCtLMncwenlNN05NTU1JT1lFa29IYVFZRzhkczJZVXBsWi9RZUo5M2xpN1EyN1NISnVhTnZLVlBjOGhTMjBVR2N5RVh0NDhialBKSHZSNUE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTg1NjQxCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKNy9WMjJDdmQwYTZLUy83ZXk2K1dkMFh3Q2k2eS9sUHIxNkxTbVVxaXlMdDdZanN1dzJNZ1lGd1UzWDZyRTZnWlZtQjBoS3prc0hidU92V2xPTFFwQ2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_aarch64.app.tar.gz" + }, + "linux-x86_64": { + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIG1pbmlzaWduIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRQZVVTenV0Rm0vcFErK1cwQTZ1bTc5WkJKVUo3Mzk3ajlBV2FUVkczVTcyL251Vjhnd1NGNUZ4ZS9JNnZhdHJKZlJvSTdiMk9UTHE3a0VLUGlCWVFFPQp0cnVzdGVkIGNvbW1lbnQ6IDE3Nzk5Nzg4NzQJZmlsZTpwaG9lbml4LWNvZGVfNS4xLjI0LkFwcEltYWdlClNEVXE2YVlaVjNwbys4TXNjQkZxL085cTJEUGRBTDhHc0h6QW43bUw5SytYRm81djNTSXVUeXJzeG94cmlPUEhLNEJuUTlISVNaay9PNGRLMG96d0RnPT0K", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/phoenix-code_5.1.24.AppImage" } } } \ No newline at end of file From af843d05e54751ff18977d5c5e18364154216d31 Mon Sep 17 00:00:00 2001 From: Charly Abraham Date: Mon, 8 Jun 2026 01:09:26 +0530 Subject: [PATCH 854/864] fix(installer): support TUXEDO OS and silence KDE Plasma 6 qtpaths noise - Resolve derivative distros to their base family via ID_LIKE (with a package-manager fallback) so TUXEDO OS (ID=tuxedo), Pop!_OS, Zorin, elementary, etc. install instead of failing 'Unsupported distribution'. - In set_default_application, drop the dead qtpaths PATH-munging block and filter the cosmetic 'qtpaths: not found' stderr that xdg-mime emits on Qt6-only KDE systems (TUXEDO OS, Ubuntu 24.04 KDE). The default is still set via xdg-mime's generic backend; only the noise is removed. Applied identically to installer.sh and installer-latest-experimental-build.sh. --- .../installer-latest-experimental-build.sh | 80 +++++++++++++------ docs/linux/installer.sh | 80 +++++++++++++------ 2 files changed, 108 insertions(+), 52 deletions(-) diff --git a/docs/linux/installer-latest-experimental-build.sh b/docs/linux/installer-latest-experimental-build.sh index ecde9707..5d78fd11 100755 --- a/docs/linux/installer-latest-experimental-build.sh +++ b/docs/linux/installer-latest-experimental-build.sh @@ -265,6 +265,38 @@ install_packages_for_distro() { esac } +# Resolves the running distro to one of the package-manager families the +# installer knows how to drive: ubuntu/debian (apt), fedora/rhel (dnf), or arch +# (pacman). Directly-named IDs map to themselves; derivative distros that aren't +# listed explicitly — TUXEDO OS (tuxedo), Pop!_OS (pop), Zorin, elementary, +# EndeavourOS, Nobara, Raspbian, … — resolve through their ID_LIKE chain, and +# as a last resort we key off whichever package manager is actually installed. +# Echoes the family on success; returns 1 only for a truly unknown system. +resolve_distro_family() { + local id="$1" id_like="$2" token + # 1. IDs the per-distro install logic already handles by name. + case "$id" in + ubuntu|debian|linuxmint|kali|neon|fedora|rhel|centos|arch|manjaro|cachyos) + echo "$id"; return 0 ;; + esac + # 2. Walk ID_LIKE (space-separated, most-derived first) for a known base. + # e.g. TUXEDO OS ships ID_LIKE="ubuntu debian" -> ubuntu. + # shellcheck disable=SC2086 + for token in $id_like; do + case "$token" in + ubuntu|debian|fedora|rhel|centos|arch) echo "$token"; return 0 ;; + esac + done + # 3. Fall back to the installed package manager. Package *names* differ + # between families but are identical within one (the apt branch picks + # libfuse2 vs libfuse2t64 by repo query), so any apt host can be driven as + # debian, any dnf host as fedora, any pacman host as arch. + if command -v apt-get >/dev/null 2>&1; then echo debian; return 0; fi + if command -v dnf >/dev/null 2>&1; then echo fedora; return 0; fi + if command -v pacman >/dev/null 2>&1; then echo arch; return 0; fi + return 1 +} + # Decides what (if anything) the user's system is missing for Phoenix Code to # run, then installs only the missing piece(s). Three independent probes: # @@ -283,13 +315,14 @@ ensure_runtime_dependencies() { fi . /etc/os-release local distro="${ID:-}" - case "$distro" in - ubuntu|debian|linuxmint|kali|neon|fedora|rhel|centos|arch|manjaro|cachyos) ;; - *) - echo -e "${RED}Unsupported distribution: $distro. Please install libfuse2/fuse2, libsecret, and (on non-KDE) gnome-keyring manually.${RESET}" - exit 1 - ;; - esac + local family + if ! family=$(resolve_distro_family "$distro" "${ID_LIKE:-}"); then + echo -e "${RED}Unsupported distribution: ${distro:-unknown}. Please install libfuse2/fuse2, libsecret, and (on non-KDE) gnome-keyring manually.${RESET}" + exit 1 + fi + if [ "$family" != "$distro" ]; then + echo -e "${GREEN}Detected '$distro'; installing dependencies as '$family'-compatible.${RESET}" + fi local keyring; keyring=$(gnome_keyring_pkg_if_needed) local libs_ok=1 keyring_ok=1 @@ -311,7 +344,7 @@ ensure_runtime_dependencies() { echo "Please enter your password to proceed." fi - install_packages_for_distro "$distro" "$keyring" + install_packages_for_distro "$family" "$keyring" # Re-probe libraries; if still failing, surface a clear warning but don't # abort — the AppImage may have a runtime-specific issue we can't fix here. if [ "$libs_ok" = 0 ] && ! verify_appimage_launches "$appimage"; then @@ -367,29 +400,24 @@ print_keyring_hint_if_locked() { set_default_application() { local desktop_file="$DESKTOP_ENTRY_NAME" - if [ "${KDE_SESSION_VERSION:-0}" -gt 0 ] && ! command -v qtpaths &> /dev/null; then - local qtpaths_locations=( - "/usr/lib/qt6/bin" - "/usr/lib/qt5/bin" - "/usr/lib64/qt6/bin" - "/usr/lib64/qt5/bin" - "/opt/qt6/bin" - "/opt/qt5/bin" - ) - for qtpath_dir in "${qtpaths_locations[@]}"; do - if [ -x "$qtpath_dir/qtpaths" ] || [ -x "$qtpath_dir/qtpaths6" ]; then - export PATH="$qtpath_dir:$PATH" - break - fi - done - fi - + # `xdg-mime default` sets the system default opener by writing [Default + # Applications] to ~/.config/mimeapps.list (its generic backend), which works on + # every desktop. On KDE it ALSO runs a qtpaths-based backend that is redundant + # for us; on Qt6-only systems (TUXEDO OS, Ubuntu 24.04 KDE, Fedora KDE) the + # `qtpaths` CLI is absent, so that backend prints a harmless "qtpaths: not found" + # per mimetype while the default is still set correctly. Collect stderr and drop + # only that cosmetic line, letting any genuine error through. + local mime_err + mime_err=$(mktemp) for mime_type in "${MIME_TYPES[@]}"; do if [ "$mime_type" = "text/html" ]; then continue fi - xdg-mime default "$desktop_file" "$mime_type" + xdg-mime default "$desktop_file" "$mime_type" 2>>"$mime_err" done + grep -vE 'qtpaths.*not found' "$mime_err" >&2 || true + rm -f "$mime_err" + echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" } diff --git a/docs/linux/installer.sh b/docs/linux/installer.sh index 33e3678c..73011455 100755 --- a/docs/linux/installer.sh +++ b/docs/linux/installer.sh @@ -265,6 +265,38 @@ install_packages_for_distro() { esac } +# Resolves the running distro to one of the package-manager families the +# installer knows how to drive: ubuntu/debian (apt), fedora/rhel (dnf), or arch +# (pacman). Directly-named IDs map to themselves; derivative distros that aren't +# listed explicitly — TUXEDO OS (tuxedo), Pop!_OS (pop), Zorin, elementary, +# EndeavourOS, Nobara, Raspbian, … — resolve through their ID_LIKE chain, and +# as a last resort we key off whichever package manager is actually installed. +# Echoes the family on success; returns 1 only for a truly unknown system. +resolve_distro_family() { + local id="$1" id_like="$2" token + # 1. IDs the per-distro install logic already handles by name. + case "$id" in + ubuntu|debian|linuxmint|kali|neon|fedora|rhel|centos|arch|manjaro|cachyos) + echo "$id"; return 0 ;; + esac + # 2. Walk ID_LIKE (space-separated, most-derived first) for a known base. + # e.g. TUXEDO OS ships ID_LIKE="ubuntu debian" -> ubuntu. + # shellcheck disable=SC2086 + for token in $id_like; do + case "$token" in + ubuntu|debian|fedora|rhel|centos|arch) echo "$token"; return 0 ;; + esac + done + # 3. Fall back to the installed package manager. Package *names* differ + # between families but are identical within one (the apt branch picks + # libfuse2 vs libfuse2t64 by repo query), so any apt host can be driven as + # debian, any dnf host as fedora, any pacman host as arch. + if command -v apt-get >/dev/null 2>&1; then echo debian; return 0; fi + if command -v dnf >/dev/null 2>&1; then echo fedora; return 0; fi + if command -v pacman >/dev/null 2>&1; then echo arch; return 0; fi + return 1 +} + # Decides what (if anything) the user's system is missing for Phoenix Code to # run, then installs only the missing piece(s). Three independent probes: # @@ -283,13 +315,14 @@ ensure_runtime_dependencies() { fi . /etc/os-release local distro="${ID:-}" - case "$distro" in - ubuntu|debian|linuxmint|kali|neon|fedora|rhel|centos|arch|manjaro|cachyos) ;; - *) - echo -e "${RED}Unsupported distribution: $distro. Please install libfuse2/fuse2, libsecret, and (on non-KDE) gnome-keyring manually.${RESET}" - exit 1 - ;; - esac + local family + if ! family=$(resolve_distro_family "$distro" "${ID_LIKE:-}"); then + echo -e "${RED}Unsupported distribution: ${distro:-unknown}. Please install libfuse2/fuse2, libsecret, and (on non-KDE) gnome-keyring manually.${RESET}" + exit 1 + fi + if [ "$family" != "$distro" ]; then + echo -e "${GREEN}Detected '$distro'; installing dependencies as '$family'-compatible.${RESET}" + fi local keyring; keyring=$(gnome_keyring_pkg_if_needed) local libs_ok=1 keyring_ok=1 @@ -311,7 +344,7 @@ ensure_runtime_dependencies() { echo "Please enter your password to proceed." fi - install_packages_for_distro "$distro" "$keyring" + install_packages_for_distro "$family" "$keyring" # Re-probe libraries; if still failing, surface a clear warning but don't # abort — the AppImage may have a runtime-specific issue we can't fix here. if [ "$libs_ok" = 0 ] && ! verify_appimage_launches "$appimage"; then @@ -367,29 +400,24 @@ print_keyring_hint_if_locked() { set_default_application() { local desktop_file="$DESKTOP_ENTRY_NAME" - if [ "${KDE_SESSION_VERSION:-0}" -gt 0 ] && ! command -v qtpaths &> /dev/null; then - local qtpaths_locations=( - "/usr/lib/qt6/bin" - "/usr/lib/qt5/bin" - "/usr/lib64/qt6/bin" - "/usr/lib64/qt5/bin" - "/opt/qt6/bin" - "/opt/qt5/bin" - ) - for qtpath_dir in "${qtpaths_locations[@]}"; do - if [ -x "$qtpath_dir/qtpaths" ] || [ -x "$qtpath_dir/qtpaths6" ]; then - export PATH="$qtpath_dir:$PATH" - break - fi - done - fi - + # `xdg-mime default` sets the system default opener by writing [Default + # Applications] to ~/.config/mimeapps.list (its generic backend), which works on + # every desktop. On KDE it ALSO runs a qtpaths-based backend that is redundant + # for us; on Qt6-only systems (TUXEDO OS, Ubuntu 24.04 KDE, Fedora KDE) the + # `qtpaths` CLI is absent, so that backend prints a harmless "qtpaths: not found" + # per mimetype while the default is still set correctly. Collect stderr and drop + # only that cosmetic line, letting any genuine error through. + local mime_err + mime_err=$(mktemp) for mime_type in "${MIME_TYPES[@]}"; do if [ "$mime_type" = "text/html" ]; then continue fi - xdg-mime default "$desktop_file" "$mime_type" + xdg-mime default "$desktop_file" "$mime_type" 2>>"$mime_err" done + grep -vE 'qtpaths.*not found' "$mime_err" >&2 || true + rm -f "$mime_err" + echo -e "${GREEN}Success! You can now right-click on files in your file manager and choose Phoenix Code to edit them.${RESET}" } From d045aa6b3aff7a84d67b78fab46b437af338c181 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 11 Jun 2026 16:26:54 +0530 Subject: [PATCH 855/864] content(banner): use limited-time-offer copy and add appBanner promo param Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/appNotifications/prod/de/banner.json | 2 +- docs/appNotifications/prod/fr/banner.json | 2 +- docs/appNotifications/prod/it/banner.json | 2 +- docs/appNotifications/prod/ja/banner.json | 2 +- docs/appNotifications/prod/ko/banner.json | 2 +- docs/appNotifications/prod/pt-BR/banner.json | 2 +- docs/appNotifications/prod/root/banner.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/appNotifications/prod/de/banner.json b/docs/appNotifications/prod/de/banner.json index 81979de3..67e12f75 100644 --- a/docs/appNotifications/prod/de/banner.json +++ b/docs/appNotifications/prod/de/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro Lifetime-Angebot
Besitzen Sie Phoenix Pro dauerhaft mit einer einmaligen Zahlung. Endet in 3 Tagen.
", + "HTML_CONTENT": "
Phoenix Pro Lifetime-Angebot
Besitzen Sie Phoenix Pro dauerhaft mit einer einmaligen Zahlung. Zeitlich begrenztes Angebot.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/fr/banner.json b/docs/appNotifications/prod/fr/banner.json index 9eed6749..c8633830 100644 --- a/docs/appNotifications/prod/fr/banner.json +++ b/docs/appNotifications/prod/fr/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Offre à vie Phoenix Pro
Obtenez Phoenix Pro pour toujours avec un paiement unique. Se termine dans 3 jours.
", + "HTML_CONTENT": "
Offre à vie Phoenix Pro
Obtenez Phoenix Pro pour toujours avec un paiement unique. Offre à durée limitée.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/it/banner.json b/docs/appNotifications/prod/it/banner.json index 691773e6..7dcedee8 100644 --- a/docs/appNotifications/prod/it/banner.json +++ b/docs/appNotifications/prod/it/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Offerta a vita Phoenix Pro
Ottieni Phoenix Pro per sempre con un pagamento unico. Scade tra 3 giorni.
", + "HTML_CONTENT": "
Offerta a vita Phoenix Pro
Ottieni Phoenix Pro per sempre con un pagamento unico. Offerta a tempo limitato.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/ja/banner.json b/docs/appNotifications/prod/ja/banner.json index 71a2e050..b6e4737a 100644 --- a/docs/appNotifications/prod/ja/banner.json +++ b/docs/appNotifications/prod/ja/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro 永久ライセンス
一度の支払いで Phoenix Pro を永久に利用できます。3日後に終了します。
", + "HTML_CONTENT": "
Phoenix Pro 永久ライセンス
一度の支払いで Phoenix Pro を永久に利用できます。期間限定オファーです。
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/ko/banner.json b/docs/appNotifications/prod/ko/banner.json index f666a6ff..54ff64ef 100644 --- a/docs/appNotifications/prod/ko/banner.json +++ b/docs/appNotifications/prod/ko/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro 평생 이용권
한 번의 결제로 Phoenix Pro 를 평생 사용하세요. 3일 후 종료됩니다.
", + "HTML_CONTENT": "
Phoenix Pro 평생 이용권
한 번의 결제로 Phoenix Pro 를 평생 사용하세요. 기간 한정 혜택입니다.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/pt-BR/banner.json b/docs/appNotifications/prod/pt-BR/banner.json index 8b0142f8..080f00f7 100644 --- a/docs/appNotifications/prod/pt-BR/banner.json +++ b/docs/appNotifications/prod/pt-BR/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Oferta vitalícia do Phoenix Pro
Tenha Phoenix Pro para sempre com um pagamento único. Termina em 3 dias.
", + "HTML_CONTENT": "
Oferta vitalícia do Phoenix Pro
Tenha Phoenix Pro para sempre com um pagamento único. Oferta por tempo limitado.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] diff --git a/docs/appNotifications/prod/root/banner.json b/docs/appNotifications/prod/root/banner.json index 39fe7eb2..e3b40559 100644 --- a/docs/appNotifications/prod/root/banner.json +++ b/docs/appNotifications/prod/root/banner.json @@ -7,7 +7,7 @@ }, "LIFETIME_DEAL_V_5_0_0_DEAL_1": { "DANGER_SHOW_ON_EVERY_BOOT": false, - "HTML_CONTENT": "
Phoenix Pro Lifetime Deal
Own Phoenix Pro forever with a one-time purchase. Ends in 3 days.
", + "HTML_CONTENT": "
Phoenix Pro Lifetime Deal
Own Phoenix Pro forever with a one-time purchase. Limited time offer.
", "FOR_VERSIONS": ">=5.0.0", "PLATFORM": "allDesktop", "USER_TYPE": ["trial"] From fc745d5a714f87dd8f9fdb9b666c48be81f91f74 Mon Sep 17 00:00:00 2001 From: Pluto Date: Fri, 19 Jun 2026 17:18:16 +0530 Subject: [PATCH 856/864] fix(tauri): add native macOS screen color picker for styles-bar eyedropper WebKit (the app's WKWebView) lacks the web EyeDropper API, so the styles-bar color picker routes the eyedropper through the editor to a new pick_screen_color Tauri command backed by NSColorSampler. Registers the command in the invoke handler. Non-macOS returns an explicit error. --- src-tauri/src/main.rs | 80 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 142fd705..b18277f2 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -425,6 +425,84 @@ struct CaptureRect { height: f64, } +// macOS native screen eyedropper for the styles-bar color picker. WebKit (the +// app's WKWebView) does not implement the web EyeDropper API, so the previewed +// page routes here through the editor. Shows the system color sampler +// (NSColorSampler, macOS 10.15+) and resolves with the picked color as +// "#rrggbb", or "" when the user dismisses the sampler without choosing. +#[tauri::command] +async fn pick_screen_color(window: tauri::Window) -> Result { + #[cfg(not(target_os = "macos"))] + { + let _ = &window; + return Err("pick_screen_color is only implemented on macOS".to_string()); + } + + #[cfg(target_os = "macos")] + { + let (tx, rx) = tokio::sync::oneshot::channel::>(); + + // with_webview runs the closure on the main (UI) thread, which + // NSColorSampler requires; the webview pointer itself is unused — the + // sampler is a screen-wide system picker independent of the webview. + window.with_webview(move |_webview| { + unsafe { + let cls = match objc::runtime::Class::get("NSColorSampler") { + Some(c) => c, + None => { + let _ = tx.send(Err( + "NSColorSampler is unavailable on this macOS version".to_string())); + return; + } + }; + // `new` returns a +1-retained instance; intentionally never + // released so it outlives the async selection handler. + let sampler: cocoa::base::id = msg_send![cls, new]; + + // Wrap the sender so the handler closure is Fn (not FnOnce). + let tx = std::sync::Arc::new(std::sync::Mutex::new(Some(tx))); + + let handler = block::ConcreteBlock::new(move |color: cocoa::base::id| { + let mut guard = tx.lock().unwrap(); + let tx = match guard.take() { + Some(tx) => tx, + None => return, + }; + if color.is_null() { + // dismissed without choosing a color + let _ = tx.send(Ok(String::new())); + return; + } + // Normalize to sRGB before reading components — the sampled + // color can arrive in an arbitrary color space. + let srgb_space: cocoa::base::id = + msg_send![class!(NSColorSpace), sRGBColorSpace]; + let srgb: cocoa::base::id = msg_send![color, colorUsingColorSpace: srgb_space]; + if srgb.is_null() { + let _ = tx.send(Ok(String::new())); + return; + } + let r: f64 = msg_send![srgb, redComponent]; + let g: f64 = msg_send![srgb, greenComponent]; + let b: f64 = msg_send![srgb, blueComponent]; + let to_byte = |v: f64| -> u8 { + let n = (v * 255.0).round(); + if n < 0.0 { 0 } else if n > 255.0 { 255 } else { n as u8 } + }; + let hex = format!("#{:02x}{:02x}{:02x}", to_byte(r), to_byte(g), to_byte(b)); + let _ = tx.send(Ok(hex)); + }); + let handler = handler.copy(); + let selection_handler: &block::Block<(cocoa::base::id,), ()> = &handler; + + let () = msg_send![sampler, showSamplerWithSelectionHandler: selection_handler]; + } + }).map_err(|e| e.to_string())?; + + return rx.await.map_err(|_| "Color picker channel closed".to_string())?; + } +} + #[tauri::command] async fn capture_page(window: tauri::Window, rect: Option) -> Result, String> { #[cfg(target_os = "linux")] @@ -883,7 +961,7 @@ fn main() { put_item, get_item, get_all_items, delete_item, trust_window_aes_key, remove_trust_window_aes_key, _get_windows_drives, _rename_path, show_in_folder, move_to_trash, zoom_window, - _get_clipboard_files, _open_url_in_browser_win, capture_page]) + _get_clipboard_files, _open_url_in_browser_win, capture_page, pick_screen_color]) .setup(|app| { init::init_app(app); #[cfg(target_os = "linux")] From ac283ea086681c201fc3121a8c53d09216cbe3ac Mon Sep 17 00:00:00 2001 From: phoenixide Date: Fri, 31 Jul 2026 14:11:01 +0000 Subject: [PATCH 857/864] ci: update phcode version to 5.2.0 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 8338ecfd..28281dc3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.1.24", + "version": "5.2.0", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "f5e96376c01d264b6f517c3c63d22adc22a97a42" + "commit": "956dff0a2dad254174d1c69869e2acb6b0b81d2e" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index a2fd3543..0b257f29 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.1.24", + "version": "5.2.0", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 35a48c23..fcdb7b1b 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.1.24" +version = "5.2.0" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 03c7481d..5de0a8d5 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.1.24" + "version": "5.2.0" }, "tauri": { "allowlist": { From 6e44118aab4232897f86ce21954f22417f0a95ea Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 1 Aug 2026 06:21:40 +0000 Subject: [PATCH 858/864] ci: update phcode version to 5.2.1 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 28281dc3..3fe2461c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.2.0", + "version": "5.2.1", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "956dff0a2dad254174d1c69869e2acb6b0b81d2e" + "commit": "caf51ace0a95c0ac46d45ed51e1d3f9e594c2594" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 0b257f29..da17e6ea 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.2.0", + "version": "5.2.1", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index fcdb7b1b..18c255b6 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.2.0" +version = "5.2.1" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 5de0a8d5..28eec4df 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.2.0" + "version": "5.2.1" }, "tauri": { "allowlist": { From 6ed0d26449096268d7950198e3830e6c52451268 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 1 Aug 2026 10:49:35 +0000 Subject: [PATCH 859/864] ci: update phcode version to 5.2.2 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3fe2461c..df2d3c26 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.2.1", + "version": "5.2.2", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "caf51ace0a95c0ac46d45ed51e1d3f9e594c2594" + "commit": "e4b46dff6e9da68cd233afcf4c9e64d0c92da3db" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index da17e6ea..978f3237 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.2.1", + "version": "5.2.2", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 18c255b6..7c7a4171 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.2.1" +version = "5.2.2" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 28eec4df..f50e6bd2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.2.1" + "version": "5.2.2" }, "tauri": { "allowlist": { From 291ebd3df9c89a6d8de7947147e70dfc686a232f Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 3 Aug 2026 06:29:00 +0000 Subject: [PATCH 860/864] ci: update phcode version to 5.2.3 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index df2d3c26..79e0916e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.2.2", + "version": "5.2.3", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "e4b46dff6e9da68cd233afcf4c9e64d0c92da3db" + "commit": "0bc80d07c151ff9ed710b7ae4ba347909267a4ff" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 978f3237..1984e878 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.2.2", + "version": "5.2.3", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 7c7a4171..021daf7f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.2.2" +version = "5.2.3" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f50e6bd2..ffb5174a 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.2.2" + "version": "5.2.3" }, "tauri": { "allowlist": { From dca99802d4ba5b95920fb692c448a9710ce835f9 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Sat, 8 Aug 2026 15:21:05 +0000 Subject: [PATCH 861/864] ci: update phcode version to 5.2.4 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 79e0916e..e85deb85 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.2.3", + "version": "5.2.4", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "0bc80d07c151ff9ed710b7ae4ba347909267a4ff" + "commit": "0ce5b16d30bb398db3798f621ba7bb1988130c16" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 1984e878..64017edf 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.2.3", + "version": "5.2.4", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 021daf7f..73dce7f0 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.2.3" +version = "5.2.4" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ffb5174a..a31aefa0 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.2.3" + "version": "5.2.4" }, "tauri": { "allowlist": { From 6fbd7ad0906d0e92f50968848ed1bbea73f65713 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 10 Aug 2026 10:46:45 +0000 Subject: [PATCH 862/864] ci: tauri release update notification json --- docs/install.json | 8 +++--- docs/tauri/update-latest-stable-prod.json | 34 +++++++++++------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/install.json b/docs/install.json index 81add328..a9e7ffc2 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,9 +1,9 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_x64.dmg", + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_x64.dmg", "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa", - "linux_appimage": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/phoenix-code_5.1.24.AppImage" + "linux_appimage": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/phoenix-code_5.2.4.AppImage" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index 6cce28f2..f5b41e8a 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,35 +1,35 @@ { - "version": "5.1.24", - "notes": "2026 May release (5.1) of Phoenix Code is now available for download at [phcode.io](https://phcode.io). \r\n\r\nOur biggest update yet - this release brings AI into the editor with [Claude Code](#try-ideas-build-pages-and-fix-issues-with-ai), a new [Design Mode](#design-mode) for visual editing, a rich [Markdown editor](#rich-markdown-editor), a built-in [terminal](#built-in-terminal), responsive [device previews](#view-your-page-at-any-device-size), a [rebuilt Linux app](#linux), and a fresh new look with the [Phoenix Neo](#phoenix-neo-themes) themes.\r\n\r\n\r\n## [Try ideas, build pages, and fix issues with AI](https://docs.phcode.dev/app-links/ai-chat)\r\n\r\nPhoenix Code now includes an AI assistant powered by Claude Code - one that sees what you see, not just your code. Try ideas, make changes, and refine your work just by chatting.\r\n\r\nAttach files or capture a screenshot to show the AI exactly what you mean. It stays out of your way until you need it, so you can stay focused on the creative work.\r\n\r\n> This feature is available only in desktop apps.\r\n\r\n![](https://docs-images.phcode.dev/in-app/pro-aiChat.png)\r\n\r\n## [Design Mode](https://docs.phcode.dev/app-links/design-mode)\r\n\r\nFocus fully on your content while your code stays out of the way. Work side by side with AI and Live Preview. Edit content visually - whether you’re building web pages or Markdown documents.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-designMode.png)\r\n\r\n\r\n## [Rich Markdown Editor](https://docs.phcode.dev/app-links/markdown-editor)\r\n\r\nEdit Markdown like a document in Live Preview. Now it’s easy to add images - just paste or pick one from your device, like in Google Docs or Word.\r\n\r\nFormat text, edit tables, and add diagrams with real-time sync between code and live preview. An easier way to create Markdown files that you can share anywhere.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-markdownEditor.png)\r\n\r\n## [Live Preview Edit Upgrades](https://docs.phcode.dev/app-links/live-preview-edit)\r\n\r\nFormat text with bold, italic, and more. Add elements and update tags, classes, and attributes - all directly in Live Preview.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-controlBox.png)\r\n\r\n## [View your page at any device size](https://docs.phcode.dev/app-links/resize-ruler)\r\n\r\nSwitch between popular phones, tablets, and desktops with a single click to see how your page looks at that size. \r\nPhoenix Code also picks up your CSS `@media` breakpoints so you can jump straight to where your layout switches.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-resizeRuler.png)\r\n\r\n## [Built-in Terminal](https://docs.phcode.dev/app-links/terminal)\r\n\r\nRun commands right next to your code in the new built-in terminal. \r\nPhoenix Code allows you to open multiple terminal tabs with your preferred shell.\r\n\r\n> This feature is available only in desktop apps.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/terminal.png)\r\n\r\n## [All Your Tools, One Place](https://docs.phcode.dev/app-links/git)\r\n\r\nA new tools drawer brings Git, Terminal, Problems, and more into one place. Switch between them instantly without panels getting in your way.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/bottom-panel.png)\r\n\r\n## New Linux Platform\r\n\r\nPhoenix Code for Linux has been rebuilt from the ground up.\r\n\r\nThe previous Linux app was harder to install and didn’t match the experience we wanted to deliver. We heard that feedback loud and clear. This release is powered by a brand-new Linux platform, bringing faster performance, easier installation, and a desktop experience that now stands alongside Windows and macOS.\r\n\r\n## [Phoenix Neo Themes](https://docs.phcode.dev/app-links/themes)\r\n\r\nMeet Phoenix Dark Neo and Phoenix Light Neo - the redesigned default themes with a cleaner, modernized look.\r\n\r\n> Switch between them anytime from `View > Themes...`.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/themes-settings.png)\r\n", - "pub_date": "2026-05-28T16:27:42.982Z", + "version": "5.2.4", + "notes": "2026 August release (5.2) of Phoenix Code is now available for download at [phcode.io](https://phcode.io/).\r\n\r\nThis release brings the [Styles Bar](#style-your-page-visually-with-the-styles-bar) for styling your page visually, State of the art [Code Intelligence](#code-intelligence-for-javascript-typescript-json-python-and-php) for JavaScript, TypeScript, JSON, Python, and PHP, [AI Model Selection](#choose-your-ai-model), a [Starter Bar](#start-from-a-blank-page) for blank pages, [Doc Comment Generation](#generate-doc-comments), an [Improved Git Panel](#git-improvements), and [Video and Audio Preview](#video-and-audio-preview) right in the editor.\r\n\r\n## [Style Your Page Visually with the Styles Bar](https://docs.phcode.dev/app-links/styles-bar)\r\n\r\nThe new Styles Bar in Live Preview lets you style any element on your page visually - change fonts, colors, backgrounds, borders, spacing, alignment, and layout directly in your page instantly.\r\n\r\nChoose where changes are saved in CSS. Edit states like hover and focus. Browse and search Google Fonts or system fonts. Starting from scratch? A blank page now shows a starter bar so you can add your first element right from the preview.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-stylesBar.png)\r\n\r\n## [Code Intelligence for JavaScript, TypeScript, JSON, Python, and PHP](https://docs.phcode.dev/app-links/code-intelligence)\r\n\r\nPhoenix Code now ships IDE-grade code intelligence for:\r\n\r\n- **JavaScript & TypeScript** - completions, go to definition, find usages, and error checking, with automatically managed project configuration.\r\n- **JSON and Npm smarts** - Package JSON and other known JSON formats code intelligence. npm package name and version suggestions as you type, dependency info on hover, and warnings for packages with known vulnerabilities.\r\n- **Python** - code intelligence with built-in code formatting.\r\n- **PHP** - full code intelligence, installed on demand when you open a PHP file.\r\n\r\nLanguage servers are downloaded and set up automatically in the background - no manual installation needed. Documentation is now shown with code hints and hovering code shows quick actions to jump to a definition or find usages.\r\n\r\n> This feature is available only in desktop apps.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/codeIntelligence.png)\r\n\r\n## [Choose Your AI Model/Disable AI](https://docs.phcode.dev/app-links/ai-models)\r\n\r\nPick which Claude model powers your AI chat, right from the chat panel. \r\n\r\nPrefer an editor without AI? It can now be switched off completely from `View > Enable AI` or the AI settings dialog. [Read More...](https://docs.phcode.dev/app-links/ai-models)\r\n\r\n> This feature is available only in desktop apps.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-aiModels.png)\r\n\r\n## Start from a blank page\r\n\r\nEdit Mode needs an element to work on, and a blank page has none. Now a Starter Bar appears on empty pages so you can add your first element right from the preview, and Phoenix Code creates the page structure for you. [Read More...](https://docs.phcode.dev/app-links/live-preview-edit)\r\n\r\n![image](https://github.com/user-attachments/assets/3c37ad87-f185-4a5b-8c4a-7807bb4a1712)\r\n\r\n## Generate Doc Comments\r\n\r\nType `/**` on the line above a function or class and accept the hint that appears. Phoenix Code reads the signature and generates a documentation comment with every parameter filled in, in each language's own convention: JSDoc for JavaScript and TypeScript, PHPDoc for PHP, docstrings for Python, and more. [Read More...](https://docs.phcode.dev/app-links/doc-comments)\r\n\r\n![image](https://github.com/user-attachments/assets/a0837a82-caac-4028-87fb-5f84fa96ce32)\r\n\r\n\r\n## Git improvements\r\n\r\nSee your current branch in the sidebar and Git panel, and click to switch or create branches.\r\n\r\nYou can also use `Open All Changed Files` in the Git panel menu to open every modified file at once. [Read More...](https://docs.phcode.dev/app-links/git)\r\n\r\n![image](https://github.com/user-attachments/assets/06958747-09e1-4f45-9331-0da6f48a210f)\r\n\r\n## [Video and Audio Preview](https://docs.phcode.dev/app-links/video-audio-preview)\r\n\r\nClick a video or audio file in your project to play it right inside the editor, just like image preview.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/videoAudioPreview.jpg)\r\n", + "pub_date": "2026-08-08T16:42:54.266Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxVNHRBcGJrRXIyK0FqT0E5dloyK0dkQnVPM1BwTTRkS05HZHpzTTgwV3dlVVZ1Rzk1aWMzeFBqUktjamNFQlJjNmNKeDRXbkhqL2FMVW5QeEtXVndZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTgyOTM1CWZpbGU6UGhvZW5peCBDb2RlXzUuMS4yNF94NjQtc2V0dXAubnNpcy56aXAKdndmMHhOWU16bjJuNXpoZ2ZNcnNzZjFsSWxoM213L1dNc3BHL09rSkRBaEN3dzVZaDZncHhtZ3o2STBCQnRQc0s1OUE2Skd2bndSbUJJbTFRU0N2RGc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnN1OTNzTEo4VTQrTEplWUE5ZmRDek1WVzJJdzFTL25Pdmx2ZHlWeHNLMnR4RGRndjg5cTNHdTQwcGVBaWJZS2orZmxkRWJZRTZDQVIvdHhJcVdwQkFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA0MDA2CWZpbGU6UGhvZW5peCBDb2RlXzUuMi40X3g2NC1zZXR1cC5uc2lzLnppcAo0Y2IwMUFYM3FEeFUxQ2syMWkzR2VjUy9CRVUrTlZmWmRpQkdFMHNWajk3LzE3akN2MWx6NTBqTkg1RzNHVmI3WkttSGdMTStYRENMbytPN1QxUFdDUT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_x64-setup.nsis.zip" }, "windows-x86_64-nsis": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmxVNHRBcGJrRXIyK0FqT0E5dloyK0dkQnVPM1BwTTRkS05HZHpzTTgwV3dlVVZ1Rzk1aWMzeFBqUktjamNFQlJjNmNKeDRXbkhqL2FMVW5QeEtXVndZPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTgyOTM1CWZpbGU6UGhvZW5peCBDb2RlXzUuMS4yNF94NjQtc2V0dXAubnNpcy56aXAKdndmMHhOWU16bjJuNXpoZ2ZNcnNzZjFsSWxoM213L1dNc3BHL09rSkRBaEN3dzVZaDZncHhtZ3o2STBCQnRQc0s1OUE2Skd2bndSbUJJbTFRU0N2RGc9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_5.1.24_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnN1OTNzTEo4VTQrTEplWUE5ZmRDek1WVzJJdzFTL25Pdmx2ZHlWeHNLMnR4RGRndjg5cTNHdTQwcGVBaWJZS2orZmxkRWJZRTZDQVIvdHhJcVdwQkFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA0MDA2CWZpbGU6UGhvZW5peCBDb2RlXzUuMi40X3g2NC1zZXR1cC5uc2lzLnppcAo0Y2IwMUFYM3FEeFUxQ2syMWkzR2VjUy9CRVUrTlZmWmRpQkdFMHNWajk3LzE3akN2MWx6NTBqTkg1RzNHVmI3WkttSGdMTStYRENMbytPN1QxUFdDUT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmpxQXJTNExwYk9vTkxmaDd0SnlyVFBKQkVvYk5Qa01XenFlTy9vTmlhbXNIVWErSG02bTNUd0FwaFBSZE92MXNYS09kUlJ2WWZVVHFVWndEbVhYUmc4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTg0MTcxCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdk1uM0RMVEVZVUJWU1E5Q3RFQ3FPWU9NQmozNWVFVHFjNmtPcWgza2FwVVVIK3kwNjB4ek56WTZVR05IMC8weGcvUW1UNkJQVHdFTmxKMVd2YnkxQ3c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdUL2U2ZTNGRHFuNXlKbnBtbVh4eHlZUjZNRTFPNGJmK1h6UnRFejRSV1F6akhtelZqMTFOSGpmaVZ5Q0ZvNGtBcUNlSnJhcWZvZ3lwcytJaThGWmd3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA1NDI2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKbVUwczZzSlQvT2FmWkRmZXBiSXoyV2Z4ajJHZU1INnRMeHpqdWFQVjErK3p0c043Y2MwUCtoL2ROWXlEWkNaaElaTzVKaFd3dTJFVHdnV2hXTkdpQkE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_x64.app.tar.gz" }, "darwin-x86_64-app": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmpxQXJTNExwYk9vTkxmaDd0SnlyVFBKQkVvYk5Qa01XenFlTy9vTmlhbXNIVWErSG02bTNUd0FwaFBSZE92MXNYS09kUlJ2WWZVVHFVWndEbVhYUmc4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTg0MTcxCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdk1uM0RMVEVZVUJWU1E5Q3RFQ3FPWU9NQmozNWVFVHFjNmtPcWgza2FwVVVIK3kwNjB4ek56WTZVR05IMC8weGcvUW1UNkJQVHdFTmxKMVd2YnkxQ3c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdUL2U2ZTNGRHFuNXlKbnBtbVh4eHlZUjZNRTFPNGJmK1h6UnRFejRSV1F6akhtelZqMTFOSGpmaVZ5Q0ZvNGtBcUNlSnJhcWZvZ3lwcytJaThGWmd3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA1NDI2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKbVUwczZzSlQvT2FmWkRmZXBiSXoyV2Z4ajJHZU1INnRMeHpqdWFQVjErK3p0c043Y2MwUCtoL2ROWXlEWkNaaElaTzVKaFd3dTJFVHdnV2hXTkdpQkE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVsUlVYRCtLMncwenlNN05NTU1JT1lFa29IYVFZRzhkczJZVXBsWi9RZUo5M2xpN1EyN1NISnVhTnZLVlBjOGhTMjBVR2N5RVh0NDhialBKSHZSNUE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTg1NjQxCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKNy9WMjJDdmQwYTZLUy83ZXk2K1dkMFh3Q2k2eS9sUHIxNkxTbVVxaXlMdDdZanN1dzJNZ1lGd1UzWDZyRTZnWlZtQjBoS3prc0hidU92V2xPTFFwQ2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm92UkJDU2hrKzFUTFdaL0dsdlJOZXRXRlRVVXZJcjUrQlRHek9VZTlmVjBSTHVRK2pTQjNrVzMwVUxwUEw2dXBEZU1HMnlyNUt6ZUZDQUtUS2pYL3dvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA3MzUzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdndiNWhIelFXTDVzSDlIU2dPQzQwUDZWaE1TWldBSjZPMENUNXpueERyRktKd3F2bjR6VlVjbEVZM2FoMmVMZVovaFlxYmR3WjRWZ3RzUlZpVFQ1Q2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_aarch64.app.tar.gz" }, "darwin-aarch64-app": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVsUlVYRCtLMncwenlNN05NTU1JT1lFa29IYVFZRzhkczJZVXBsWi9RZUo5M2xpN1EyN1NISnVhTnZLVlBjOGhTMjBVR2N5RVh0NDhialBKSHZSNUE4PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzc5OTg1NjQxCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKNy9WMjJDdmQwYTZLUy83ZXk2K1dkMFh3Q2k2eS9sUHIxNkxTbVVxaXlMdDdZanN1dzJNZ1lGd1UzWDZyRTZnWlZtQjBoS3prc0hidU92V2xPTFFwQ2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm92UkJDU2hrKzFUTFdaL0dsdlJOZXRXRlRVVXZJcjUrQlRHek9VZTlmVjBSTHVRK2pTQjNrVzMwVUxwUEw2dXBEZU1HMnlyNUt6ZUZDQUtUS2pYL3dvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA3MzUzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdndiNWhIelFXTDVzSDlIU2dPQzQwUDZWaE1TWldBSjZPMENUNXpueERyRktKd3F2bjR6VlVjbEVZM2FoMmVMZVovaFlxYmR3WjRWZ3RzUlZpVFQ1Q2c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_aarch64.app.tar.gz" }, "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIG1pbmlzaWduIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnRQZVVTenV0Rm0vcFErK1cwQTZ1bTc5WkJKVUo3Mzk3ajlBV2FUVkczVTcyL251Vjhnd1NGNUZ4ZS9JNnZhdHJKZlJvSTdiMk9UTHE3a0VLUGlCWVFFPQp0cnVzdGVkIGNvbW1lbnQ6IDE3Nzk5Nzg4NzQJZmlsZTpwaG9lbml4LWNvZGVfNS4xLjI0LkFwcEltYWdlClNEVXE2YVlaVjNwbys4TXNjQkZxL085cTJEUGRBTDhHc0h6QW43bUw5SytYRm81djNTSXVUeXJzeG94cmlPUEhLNEJuUTlISVNaay9PNGRLMG96d0RnPT0K", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.1.24/phoenix-code_5.1.24.AppImage" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIG1pbmlzaWduIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5xcGd4cHdFQWVmM1Q3djE1blYyejQ2VE4yYXpLUXlXWGxKQ0tFT0lSMkpudmZSc3VscVJOU1F5QmFjYWVKQzB3ZWhpRmdyWFU1SWpWemxRRE5paEE0PQp0cnVzdGVkIGNvbW1lbnQ6IDE3ODYyMDI5OTMJZmlsZTpwaG9lbml4LWNvZGVfNS4yLjQuQXBwSW1hZ2UKWXNTL20xVUp5WGpSd2diNjVPcldjcjNZNEFvUkNoTi9iUGZMOUZhZDFaalZhcnB2SkxXRVRiT3l2bXB5anpaNUY3QkxNMWZmUFNCMExZRXdUMUdDQlE9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/phoenix-code_5.2.4.AppImage" } } } \ No newline at end of file From 9078545a7b51f2051bd442122b22c2c8499eebb1 Mon Sep 17 00:00:00 2001 From: phoenixide Date: Mon, 10 Aug 2026 17:42:31 +0000 Subject: [PATCH 863/864] ci: update phcode version to 5.2.5 --- package.json | 4 ++-- src-electron/package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index e85deb85..6a4f071f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "phoenix-code-ide", "private": true, - "version": "5.2.4", + "version": "5.2.5", "type": "module", "scripts": { "tauri": "tauri", @@ -48,6 +48,6 @@ "phoenixRepo": { "gitClonrUrl": "https://github.com/phcode-dev/phoenix.git", "branch": "tauri", - "commit": "0ce5b16d30bb398db3798f621ba7bb1988130c16" + "commit": "db8ef6a1dc7dcb4f87b705fc92c7c17e30150720" } } \ No newline at end of file diff --git a/src-electron/package.json b/src-electron/package.json index 64017edf..3060ff5a 100644 --- a/src-electron/package.json +++ b/src-electron/package.json @@ -6,7 +6,7 @@ "phtauri://localhost/", "https://phcode.dev/" ], - "version": "5.2.4", + "version": "5.2.5", "productName": "Phoenix Code Experimental Build", "desktopName": "phoenix-code-experimental-build", "description": "Phoenix Code Experimental Build", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 73dce7f0..4432ebcb 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "phoenix-code-ide" -version = "5.2.4" +version = "5.2.5" description = "Phoenix Code" authors = ["arun@core.ai, charly@core.ai"] license = "GNU AGPL 3.0" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a31aefa0..121ea38f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Phoenix Code Experimental Build", - "version": "5.2.4" + "version": "5.2.5" }, "tauri": { "allowlist": { From e73d275d067dc4417d5d1bf907220e5f32c8c0c1 Mon Sep 17 00:00:00 2001 From: abose Date: Mon, 10 Aug 2026 18:58:04 +0000 Subject: [PATCH 864/864] ci: tauri release update notification json --- docs/install.json | 8 +++--- docs/tauri/update-latest-stable-prod.json | 32 +++++++++++------------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/install.json b/docs/install.json index a9e7ffc2..de124784 100644 --- a/docs/install.json +++ b/docs/install.json @@ -1,9 +1,9 @@ { "phcode.io.DownloadURL": { - "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_x64-setup.exe", - "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_aarch64.dmg", - "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_x64.dmg", + "windows_x64": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/Phoenix.Code_5.2.5_x64-setup.exe", + "mac_m1": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/Phoenix.Code_5.2.5_aarch64.dmg", + "mac_intel": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/Phoenix.Code_5.2.5_x64.dmg", "chrome_os": "https://play.google.com/store/apps/details?id=prod.phcode.twa", - "linux_appimage": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/phoenix-code_5.2.4.AppImage" + "linux_appimage": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/phoenix-code_5.2.5.AppImage" } } \ No newline at end of file diff --git a/docs/tauri/update-latest-stable-prod.json b/docs/tauri/update-latest-stable-prod.json index f5b41e8a..a5cff9d0 100644 --- a/docs/tauri/update-latest-stable-prod.json +++ b/docs/tauri/update-latest-stable-prod.json @@ -1,35 +1,35 @@ { - "version": "5.2.4", + "version": "5.2.5", "notes": "2026 August release (5.2) of Phoenix Code is now available for download at [phcode.io](https://phcode.io/).\r\n\r\nThis release brings the [Styles Bar](#style-your-page-visually-with-the-styles-bar) for styling your page visually, State of the art [Code Intelligence](#code-intelligence-for-javascript-typescript-json-python-and-php) for JavaScript, TypeScript, JSON, Python, and PHP, [AI Model Selection](#choose-your-ai-model), a [Starter Bar](#start-from-a-blank-page) for blank pages, [Doc Comment Generation](#generate-doc-comments), an [Improved Git Panel](#git-improvements), and [Video and Audio Preview](#video-and-audio-preview) right in the editor.\r\n\r\n## [Style Your Page Visually with the Styles Bar](https://docs.phcode.dev/app-links/styles-bar)\r\n\r\nThe new Styles Bar in Live Preview lets you style any element on your page visually - change fonts, colors, backgrounds, borders, spacing, alignment, and layout directly in your page instantly.\r\n\r\nChoose where changes are saved in CSS. Edit states like hover and focus. Browse and search Google Fonts or system fonts. Starting from scratch? A blank page now shows a starter bar so you can add your first element right from the preview.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-stylesBar.png)\r\n\r\n## [Code Intelligence for JavaScript, TypeScript, JSON, Python, and PHP](https://docs.phcode.dev/app-links/code-intelligence)\r\n\r\nPhoenix Code now ships IDE-grade code intelligence for:\r\n\r\n- **JavaScript & TypeScript** - completions, go to definition, find usages, and error checking, with automatically managed project configuration.\r\n- **JSON and Npm smarts** - Package JSON and other known JSON formats code intelligence. npm package name and version suggestions as you type, dependency info on hover, and warnings for packages with known vulnerabilities.\r\n- **Python** - code intelligence with built-in code formatting.\r\n- **PHP** - full code intelligence, installed on demand when you open a PHP file.\r\n\r\nLanguage servers are downloaded and set up automatically in the background - no manual installation needed. Documentation is now shown with code hints and hovering code shows quick actions to jump to a definition or find usages.\r\n\r\n> This feature is available only in desktop apps.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/codeIntelligence.png)\r\n\r\n## [Choose Your AI Model/Disable AI](https://docs.phcode.dev/app-links/ai-models)\r\n\r\nPick which Claude model powers your AI chat, right from the chat panel. \r\n\r\nPrefer an editor without AI? It can now be switched off completely from `View > Enable AI` or the AI settings dialog. [Read More...](https://docs.phcode.dev/app-links/ai-models)\r\n\r\n> This feature is available only in desktop apps.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/pro-aiModels.png)\r\n\r\n## Start from a blank page\r\n\r\nEdit Mode needs an element to work on, and a blank page has none. Now a Starter Bar appears on empty pages so you can add your first element right from the preview, and Phoenix Code creates the page structure for you. [Read More...](https://docs.phcode.dev/app-links/live-preview-edit)\r\n\r\n![image](https://github.com/user-attachments/assets/3c37ad87-f185-4a5b-8c4a-7807bb4a1712)\r\n\r\n## Generate Doc Comments\r\n\r\nType `/**` on the line above a function or class and accept the hint that appears. Phoenix Code reads the signature and generates a documentation comment with every parameter filled in, in each language's own convention: JSDoc for JavaScript and TypeScript, PHPDoc for PHP, docstrings for Python, and more. [Read More...](https://docs.phcode.dev/app-links/doc-comments)\r\n\r\n![image](https://github.com/user-attachments/assets/a0837a82-caac-4028-87fb-5f84fa96ce32)\r\n\r\n\r\n## Git improvements\r\n\r\nSee your current branch in the sidebar and Git panel, and click to switch or create branches.\r\n\r\nYou can also use `Open All Changed Files` in the Git panel menu to open every modified file at once. [Read More...](https://docs.phcode.dev/app-links/git)\r\n\r\n![image](https://github.com/user-attachments/assets/06958747-09e1-4f45-9331-0da6f48a210f)\r\n\r\n## [Video and Audio Preview](https://docs.phcode.dev/app-links/video-audio-preview)\r\n\r\nClick a video or audio file in your project to play it right inside the editor, just like image preview.\r\n\r\n![Image](https://docs-images.phcode.dev/in-app/videoAudioPreview.jpg)\r\n", - "pub_date": "2026-08-08T16:42:54.266Z", + "pub_date": "2026-08-10T18:56:45.483Z", "platforms": { "windows-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnN1OTNzTEo4VTQrTEplWUE5ZmRDek1WVzJJdzFTL25Pdmx2ZHlWeHNLMnR4RGRndjg5cTNHdTQwcGVBaWJZS2orZmxkRWJZRTZDQVIvdHhJcVdwQkFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA0MDA2CWZpbGU6UGhvZW5peCBDb2RlXzUuMi40X3g2NC1zZXR1cC5uc2lzLnppcAo0Y2IwMUFYM3FEeFUxQ2syMWkzR2VjUy9CRVUrTlZmWmRpQkdFMHNWajk3LzE3akN2MWx6NTBqTkg1RzNHVmI3WkttSGdMTStYRENMbytPN1QxUFdDUT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhiUjVNRnNueEs2dHcxbWx5dFphbHFZRkJTd2JZQ0ZtazV0N2JLclpkbHc2b3hVUXljVmtoSUlLUXpieHBOVW1KZmZ4Mkg5eXV6QURvTFRIV3JPd3dJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2Mzg1MTU3CWZpbGU6UGhvZW5peCBDb2RlXzUuMi41X3g2NC1zZXR1cC5uc2lzLnppcAphY0I0SUtldjlGeVRDQytDVG5Bc20yVGVkdzZUbXkrNG9IL0hQOEJtK1dDd2RseEdxejduYWxKckFwMGRqcEEvbnM2dlJxMmF4SjQ5bGR4UEFOaW9CQT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/Phoenix.Code_5.2.5_x64-setup.nsis.zip" }, "windows-x86_64-nsis": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnN1OTNzTEo4VTQrTEplWUE5ZmRDek1WVzJJdzFTL25Pdmx2ZHlWeHNLMnR4RGRndjg5cTNHdTQwcGVBaWJZS2orZmxkRWJZRTZDQVIvdHhJcVdwQkFjPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA0MDA2CWZpbGU6UGhvZW5peCBDb2RlXzUuMi40X3g2NC1zZXR1cC5uc2lzLnppcAo0Y2IwMUFYM3FEeFUxQ2syMWkzR2VjUy9CRVUrTlZmWmRpQkdFMHNWajk3LzE3akN2MWx6NTBqTkg1RzNHVmI3WkttSGdMTStYRENMbytPN1QxUFdDUT09Cg==", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_5.2.4_x64-setup.nsis.zip" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhiUjVNRnNueEs2dHcxbWx5dFphbHFZRkJTd2JZQ0ZtazV0N2JLclpkbHc2b3hVUXljVmtoSUlLUXpieHBOVW1KZmZ4Mkg5eXV6QURvTFRIV3JPd3dJPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2Mzg1MTU3CWZpbGU6UGhvZW5peCBDb2RlXzUuMi41X3g2NC1zZXR1cC5uc2lzLnppcAphY0I0SUtldjlGeVRDQytDVG5Bc20yVGVkdzZUbXkrNG9IL0hQOEJtK1dDd2RseEdxejduYWxKckFwMGRqcEEvbnM2dlJxMmF4SjQ5bGR4UEFOaW9CQT09Cg==", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/Phoenix.Code_5.2.5_x64-setup.nsis.zip" }, "darwin-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdUL2U2ZTNGRHFuNXlKbnBtbVh4eHlZUjZNRTFPNGJmK1h6UnRFejRSV1F6akhtelZqMTFOSGpmaVZ5Q0ZvNGtBcUNlSnJhcWZvZ3lwcytJaThGWmd3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA1NDI2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKbVUwczZzSlQvT2FmWkRmZXBiSXoyV2Z4ajJHZU1INnRMeHpqdWFQVjErK3p0c043Y2MwUCtoL2ROWXlEWkNaaElaTzVKaFd3dTJFVHdnV2hXTkdpQkE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdvS2hFK3lDcUpTM0dQK3hQbGZHd1RmRlpIRTRaYjRWUEthZWNRU0RYaWhyOTQyd3gwQ1JVNm5aOG1LQXo1S2dha2FIQ1lieEx4UGEzbnFaL1V4cmcwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2Mzg2MjMyCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKYWdvSVRld3FYbXcxcTZ4YVd3WGtVM2Q4bUJ4K2NMMFJMdW12bk9jbkc3Z3l4RWRZdWxiMmRNQm42cUVQR056VXM1VUl5TGRuQU44dGlYcE9mZ1dXQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/Phoenix.Code_x64.app.tar.gz" }, "darwin-x86_64-app": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdUL2U2ZTNGRHFuNXlKbnBtbVh4eHlZUjZNRTFPNGJmK1h6UnRFejRSV1F6akhtelZqMTFOSGpmaVZ5Q0ZvNGtBcUNlSnJhcWZvZ3lwcytJaThGWmd3PQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA1NDI2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKbVUwczZzSlQvT2FmWkRmZXBiSXoyV2Z4ajJHZU1INnRMeHpqdWFQVjErK3p0c043Y2MwUCtoL2ROWXlEWkNaaElaTzVKaFd3dTJFVHdnV2hXTkdpQkE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_x64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmdvS2hFK3lDcUpTM0dQK3hQbGZHd1RmRlpIRTRaYjRWUEthZWNRU0RYaWhyOTQyd3gwQ1JVNm5aOG1LQXo1S2dha2FIQ1lieEx4UGEzbnFaL1V4cmcwPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2Mzg2MjMyCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKYWdvSVRld3FYbXcxcTZ4YVd3WGtVM2Q4bUJ4K2NMMFJMdW12bk9jbkc3Z3l4RWRZdWxiMmRNQm42cUVQR056VXM1VUl5TGRuQU44dGlYcE9mZ1dXQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/Phoenix.Code_x64.app.tar.gz" }, "darwin-aarch64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm92UkJDU2hrKzFUTFdaL0dsdlJOZXRXRlRVVXZJcjUrQlRHek9VZTlmVjBSTHVRK2pTQjNrVzMwVUxwUEw2dXBEZU1HMnlyNUt6ZUZDQUtUS2pYL3dvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA3MzUzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdndiNWhIelFXTDVzSDlIU2dPQzQwUDZWaE1TWldBSjZPMENUNXpueERyRktKd3F2bjR6VlVjbEVZM2FoMmVMZVovaFlxYmR3WjRWZ3RzUlZpVFQ1Q2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVHN01pbWpKWUF2V3ZwVzFObzRIOHA1RTlNTWlqSndaYmtpSE5iT1hxT0JDTHJoT0c4OWhhc0dtMVhmUkFoS1pjVXpiUVpOK2dDRFpkdUNJQUZncGdnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2Mzg4MTg2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKNGZWWk0yVmg2cFZUVUlwMkRoNHlWSFhtM2Y5TVQ1SHJoQW42VU04STV0UWNldFRnMUxaTFdhRUFDYUpQWVBZKzdUZVVzM2tpMWtZYWJJZjJJQkRJQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/Phoenix.Code_aarch64.app.tar.gz" }, "darwin-aarch64-app": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm92UkJDU2hrKzFUTFdaL0dsdlJOZXRXRlRVVXZJcjUrQlRHek9VZTlmVjBSTHVRK2pTQjNrVzMwVUxwUEw2dXBEZU1HMnlyNUt6ZUZDQUtUS2pYL3dvPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2MjA3MzUzCWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKdndiNWhIelFXTDVzSDlIU2dPQzQwUDZWaE1TWldBSjZPMENUNXpueERyRktKd3F2bjR6VlVjbEVZM2FoMmVMZVovaFlxYmR3WjRWZ3RzUlZpVFQ1Q2c9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/Phoenix.Code_aarch64.app.tar.gz" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIHRhdXJpIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWnVHN01pbWpKWUF2V3ZwVzFObzRIOHA1RTlNTWlqSndaYmtpSE5iT1hxT0JDTHJoT0c4OWhhc0dtMVhmUkFoS1pjVXpiUVpOK2dDRFpkdUNJQUZncGdnPQp0cnVzdGVkIGNvbW1lbnQ6IHRpbWVzdGFtcDoxNzg2Mzg4MTg2CWZpbGU6UGhvZW5peCBDb2RlLmFwcC50YXIuZ3oKNGZWWk0yVmg2cFZUVUlwMkRoNHlWSFhtM2Y5TVQ1SHJoQW42VU04STV0UWNldFRnMUxaTFdhRUFDYUpQWVBZKzdUZVVzM2tpMWtZYWJJZjJJQkRJQ3c9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/Phoenix.Code_aarch64.app.tar.gz" }, "linux-x86_64": { - "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIG1pbmlzaWduIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWm5xcGd4cHdFQWVmM1Q3djE1blYyejQ2VE4yYXpLUXlXWGxKQ0tFT0lSMkpudmZSc3VscVJOU1F5QmFjYWVKQzB3ZWhpRmdyWFU1SWpWemxRRE5paEE0PQp0cnVzdGVkIGNvbW1lbnQ6IDE3ODYyMDI5OTMJZmlsZTpwaG9lbml4LWNvZGVfNS4yLjQuQXBwSW1hZ2UKWXNTL20xVUp5WGpSd2diNjVPcldjcjNZNEFvUkNoTi9iUGZMOUZhZDFaalZhcnB2SkxXRVRiT3l2bXB5anpaNUY3QkxNMWZmUFNCMExZRXdUMUdDQlE9PQo=", - "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.4/phoenix-code_5.2.4.AppImage" + "signature": "dW50cnVzdGVkIGNvbW1lbnQ6IHNpZ25hdHVyZSBmcm9tIG1pbmlzaWduIHNlY3JldCBrZXkKUlVUVTVEdXJNVyttWmhwWjFFUDBMZW9YaHRRTm1USnhMV3cvWGZ4L0wzbW95Mjg3c3l1aVl3OFpzR2lacWU0QWhHa1RaanVhTmRBRDI0WkNraWk4bEhMdE1tdWx2L2lUblF3PQp0cnVzdGVkIGNvbW1lbnQ6IDE3ODYzODQyMDgJZmlsZTpwaG9lbml4LWNvZGVfNS4yLjUuQXBwSW1hZ2UKNjRITEExNjFJUXZKanJrai9ybFg0a0kxUmJ0Q09RaDRSSUFFNWIxVk1FQksyK0pzbHgvdnRncVVXWWRRM3FYL0VyYU9LS0h0cDc0R3FpNzMyUDNSQnc9PQo=", + "url": "https://github.com/phcode-dev/phoenix-desktop/releases/download/prod-app-v5.2.5/phoenix-code_5.2.5.AppImage" } } } \ No newline at end of file