Merge branch 'experimental'

This commit is contained in:
Tw93
2024-12-19 20:33:11 +08:00
49 changed files with 2568 additions and 3069 deletions

View File

@@ -1,49 +1,49 @@
name: Build and Publish Docker Image name: Build and Publish Docker Image
on: on:
workflow_dispatch: # Manual workflow_dispatch: # Manual
env: env:
REGISTRY: ghcr.io REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }} IMAGE_NAME: ${{ github.repository }}
jobs: jobs:
build-and-push-image: build-and-push-image:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
permissions: permissions:
contents: read contents: read
packages: write packages: write
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry - name: Log in to the Container registry
uses: docker/login-action@v2 uses: docker/login-action@v2
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker - name: Extract metadata (tags, labels) for Docker
id: meta id: meta
uses: docker/metadata-action@v4 uses: docker/metadata-action@v4
with: with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=raw,value=latest,enable={{is_default_branch}} type=raw,value=latest,enable={{is_default_branch}}
type=sha type=sha
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v4 uses: docker/build-push-action@v4
with: with:
context: . context: .
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
platforms: linux/amd64 platforms: linux/amd64

View File

@@ -28,9 +28,6 @@ on:
description: '[Height, Optional]' description: '[Height, Optional]'
required: false required: false
default: '780' default: '780'
safe_domain:
description: '[Safe Domain, Optional]'
required: false
hide_title_bar: hide_title_bar:
description: '[Hide TitleBar, Optional, MacOS only]' description: '[Hide TitleBar, Optional, MacOS only]'
required: false required: false
@@ -92,7 +89,7 @@ jobs:
if: inputs.platform == 'ubuntu-20.04' if: inputs.platform == 'ubuntu-20.04'
uses: awalsh128/cache-apt-pkgs-action@latest uses: awalsh128/cache-apt-pkgs-action@latest
with: with:
packages: libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra packages: libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra
version: 1.1 version: 1.1
- name: Install pake-cli local - name: Install pake-cli local
@@ -132,7 +129,6 @@ jobs:
RESIZE: ${{ inputs.resize }} RESIZE: ${{ inputs.resize }}
MULTI_ARCH: ${{ inputs.multi_arch }} MULTI_ARCH: ${{ inputs.multi_arch }}
TARGETS: ${{ inputs.targets }} TARGETS: ${{ inputs.targets }}
SAFE_DOMAIN: ${{ inputs.safe_domain }}
- name: Upload archive - name: Upload archive
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3

View File

@@ -17,8 +17,8 @@ jobs:
- name: Get Apps Config - name: Get Apps Config
id: read-apps-config id: read-apps-config
run: | run: |
echo "apps_name=$(jq -c '[.apps| .[] | .name]' apps.conf.json)" >> $GITHUB_OUTPUT echo "apps_name=$(jq -c '[.[] | .name]' default_app_list.json)" >> $GITHUB_OUTPUT
echo "apps_config=$(jq -c '[.apps | .[]]' apps.conf.json)" >> $GITHUB_OUTPUT echo "apps_config=$(jq -c '[.[]]' default_app_list.json)" >> $GITHUB_OUTPUT
trigger_build: trigger_build:
needs: read_apps_config needs: read_apps_config

View File

@@ -75,7 +75,7 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
uses: awalsh128/cache-apt-pkgs-action@latest uses: awalsh128/cache-apt-pkgs-action@latest
with: with:
packages: libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra packages: libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra
version: 1.1 version: 1.1
- name: Rust cache restore - name: Rust cache restore

View File

@@ -40,12 +40,11 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
uses: awalsh128/cache-apt-pkgs-action@latest uses: awalsh128/cache-apt-pkgs-action@latest
with: with:
packages: libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra packages: libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev build-essential curl wget file libxdo-dev libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra
version: 1.0 version: 1.0
- name: Run unit & integration tests with nextest - name: Run unit & integration tests with nextest
run: cargo hack --feature-powerset --exclude-features cli-build nextest run run: cargo hack --feature-powerset --exclude-features cli-build nextest run --no-tests=pass
# - name: Run documentation tests with cargo test
# run: cargo hack --feature-powerset test --doc
cargo-clippy: cargo-clippy:
name: Check codebase quality (cargo clippy) name: Check codebase quality (cargo clippy)
@@ -67,7 +66,7 @@ jobs:
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
uses: awalsh128/cache-apt-pkgs-action@latest uses: awalsh128/cache-apt-pkgs-action@latest
with: with:
packages: libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra packages: libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev gnome-video-effects gnome-video-effects-extra
version: 1.0 version: 1.0
- name: Run all-features code quality checks - name: Run all-features code quality checks
run: cargo hack --feature-powerset --exclude-features cli-build --no-dev-deps clippy run: cargo hack --feature-powerset --exclude-features cli-build --no-dev-deps clippy

1
.gitignore vendored
View File

@@ -38,3 +38,4 @@ src-tauri/.cargo/config.toml
src-tauri/.cargo/ src-tauri/.cargo/
.next .next
src-tauri/.pake/ src-tauri/.pake/
src-tauri/gen

View File

@@ -18,7 +18,6 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \
mkdir -p /cargo-cache && \ mkdir -p /cargo-cache && \
cp -R /usr/local/cargo/registry /cargo-cache/ && \ cp -R /usr/local/cargo/registry /cargo-cache/ && \
cp -R /usr/local/cargo/git /cargo-cache/ cp -R /usr/local/cargo/git /cargo-cache/
# Verify the content of /cargo-cache && clean unnecessary files # Verify the content of /cargo-cache && clean unnecessary files
RUN ls -la /cargo-cache/registry && ls -la /cargo-cache/git && rm -rfd /cargo-cache/registry/src RUN ls -la /cargo-cache/registry && ls -la /cargo-cache/git && rm -rfd /cargo-cache/registry/src
@@ -28,8 +27,8 @@ FROM rust:1.80-slim AS builder
RUN --mount=type=cache,target=/var/cache/apt \ RUN --mount=type=cache,target=/var/cache/apt \
--mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/usr/local/cargo/registry \
apt-get update && apt-get install -y --no-install-recommends \ apt-get update && apt-get install -y --no-install-recommends \
libdbus-1-dev libsoup2.4-dev libjavascriptcoregtk-4.0-dev \ libdbus-1-dev libsoup2.4-dev libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev \ libwebkit2gtk-4.1-dev build-essential curl wget libssl-dev \
libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev \ libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev \
gnome-video-effects gnome-video-effects

View File

@@ -53,15 +53,15 @@
<a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x64.msi">Windows</a> <a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x86_64.deb">Linux</a> <a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x86_64.deb">Linux</a>
</td> </td>
<td>Poe <td>Qwerty
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe.dmg">Mac</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe_x64.msi">Windows</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe_x86_64.deb">Linux</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x86_64.deb">Linux</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ChatGPT.png width=600/></td> <td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ChatGPT.png width=600/></td>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Poe.png width=600/></td> <td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Qwerty.png width=600/></td>
</tr> </tr>
<tr> <tr>
<td>YouTube Music <td>YouTube Music
@@ -96,22 +96,6 @@
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ProgramMusic.jpg width=600/></td> <td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ProgramMusic.jpg width=600/></td>
</tr> </tr>
<tr> <tr>
<td>Qwerty
<a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x86_64.deb">Linux</a>
</td>
<td>CodeRunner
<a href="https://github.com/tw93/Pake/releases/latest/download/CodeRunner.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/CodeRunner_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/CodeRunner_x86_64.deb">Linux</a>
</td>
</tr>
<tr>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Qwerty.png width=600/></td>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/CodeRunner.jpg width=600/></td>
</tr>
<tr>
<td>Flomo <td>Flomo
<a href="https://github.com/tw93/Pake/releases/latest/download/Flomo.dmg">Mac</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Flomo.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Flomo_x64.msi">Windows</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Flomo_x64.msi">Windows</a>
@@ -154,7 +138,7 @@ In addition, double-click the title bar to switch to full-screen mode. For Mac u
## Before starting ## Before starting
1. **For beginners**: Play with Popular Packages to find out Pake's capabilities, or try to pack your application with [GitHub Actions](<https://github.com/tw93/Pake/wiki/Online-Compilation-(used-by-ordinary-users)>). Don't hesitate to reach for assistance at [Discussion](https://github.com/tw93/Pake/discussions)! 1. **For beginners**: Play with Popular Packages to find out Pake's capabilities, or try to pack your application with [GitHub Actions](<https://github.com/tw93/Pake/wiki/Online-Compilation-(used-by-ordinary-users)>). Don't hesitate to reach for assistance at [Discussion](https://github.com/tw93/Pake/discussions)!
2. **For developers**: “Command-Line Packaging” supports macOS fully. For Windows/Linux users, it requires some tinkering. [Configure your environment](https://tauri.app/v1/guides/getting-started/prerequisites) before getting started. 2. **For developers**: “Command-Line Packaging” supports macOS fully. For Windows/Linux users, it requires some tinkering. [Configure your environment](https://tauri.app/start/prerequisites/) before getting started.
3. **For hackers**: For people who are good at both front-end development and Rust, how about customizing your apps' function more with the following [Customized Development](#development)? 3. **For hackers**: For people who are good at both front-end development and Rust, how about customizing your apps' function more with the following [Customized Development](#development)?
## Command-Line Packaging ## Command-Line Packaging
@@ -179,7 +163,7 @@ If you are new to the command line, you can compile packages online with _GitHub
## Development ## Development
Prepare your environment before starting. Make sure you have Rust `>=1.63` and Node `>=16` (e.g., `16.18.1`) installed on your computer. For installation guidance, see [Tauri documentation](https://tauri.app/v1/guides/getting-started/prerequisites). Prepare your environment before starting. Make sure you have Rust `>=1.63` and Node `>=16` (e.g., `16.18.1`) installed on your computer. For installation guidance, see [Tauri documentation](https://tauri.app/start/prerequisites/).
If you are unfamiliar with these, it is better to try out the above tool to pack with one click. If you are unfamiliar with these, it is better to try out the above tool to pack with one click.

View File

@@ -52,15 +52,15 @@
<a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x64.msi">Windows</a> <a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x86_64.deb">Linux</a> <a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x86_64.deb">Linux</a>
</td> </td>
<td>Poe <td>Qwerty
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe.dmg">Mac</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe_x64.msi">Windows</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe_x86_64.deb">Linux</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x86_64.deb">Linux</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ChatGPT.png width=600/></td> <td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ChatGPT.png width=600/></td>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Poe.png width=600/></td> <td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Qwerty.png width=600/></td>
</tr> </tr>
<tr> <tr>
<td>YouTube Music <td>YouTube Music
@@ -95,22 +95,6 @@
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ProgramMusic.jpg width=600/></td> <td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ProgramMusic.jpg width=600/></td>
</tr> </tr>
<tr> <tr>
<td>Qwerty
<a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x86_64.deb">Linux</a>
</td>
<td>CodeRunner
<a href="https://github.com/tw93/Pake/releases/latest/download/CodeRunner.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/CodeRunner_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/CodeRunner_x86_64.deb">Linux</a>
</td>
</tr>
<tr>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Qwerty.png width=600/></td>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/CodeRunner.jpg width=600/></td>
</tr>
<tr>
<td>Flomo <td>Flomo
<a href="https://github.com/tw93/Pake/releases/latest/download/Flomo.dmg">Mac</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Flomo.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Flomo_x64.msi">Windows</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Flomo_x64.msi">Windows</a>
@@ -154,7 +138,7 @@
## 开始之前 ## 开始之前
1. **小白用户**:使用 「常用包下载」 方式来把玩 Pake 的能力,可去 [讨论群](https://github.com/tw93/Pake/discussions) 寻求帮助,也可试试 [Action](https://github.com/tw93/Pake/wiki/%E5%9C%A8%E7%BA%BF%E7%BC%96%E8%AF%91%EF%BC%88%E6%99%AE%E9%80%9A%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%EF%BC%89) 方式。 1. **小白用户**:使用 「常用包下载」 方式来把玩 Pake 的能力,可去 [讨论群](https://github.com/tw93/Pake/discussions) 寻求帮助,也可试试 [Action](https://github.com/tw93/Pake/wiki/%E5%9C%A8%E7%BA%BF%E7%BC%96%E8%AF%91%EF%BC%88%E6%99%AE%E9%80%9A%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%EF%BC%89) 方式。
2. **开发用户**:使用 「命令行一键打包」,对 Mac 比较友好Windows / Linux 需折腾下 [环境配置](https://tauri.app/v1/guides/getting-started/prerequisites)。 2. **开发用户**:使用 「命令行一键打包」,对 Mac 比较友好Windows / Linux 需折腾下 [环境配置](https://tauri.app/start/prerequisites/)。
3. **折腾用户**:假如你前端和 Rust 都会,那可试试下面的 「[定制开发](#定制开发)」,可深度二次开发定制你的功能。 3. **折腾用户**:假如你前端和 Rust 都会,那可试试下面的 「[定制开发](#定制开发)」,可深度二次开发定制你的功能。
## 命令行一键打包 ## 命令行一键打包
@@ -178,7 +162,7 @@ pake https://weekly.tw93.fun --name Weekly --hide-title-bar
## 定制开发 ## 定制开发
开始前请确保电脑已经安装了 Rust `>=1.63` 和 Node `>=16 如 16.18.1` 的环境,此外需参考 [Tauri 文档](https://tauri.app/v1/guides/getting-started/prerequisites) 快速配置好环境才可以开始使用,假如你太不懂,使用上面的命令行打包会更加合适。 开始前请确保电脑已经安装了 Rust `>=1.63` 和 Node `>=16 如 16.18.1` 的环境,此外需参考 [Tauri 文档](https://tauri.app/start/prerequisites/) 快速配置好环境才可以开始使用,假如你太不懂,使用上面的命令行打包会更加合适。
```sh ```sh
# 安装依赖 # 安装依赖

View File

@@ -53,15 +53,15 @@
<a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x64.msi">Windows</a> <a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x86_64.deb">Linux</a> <a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT_x86_64.deb">Linux</a>
</td> </td>
<td>Poe <td>Qwerty
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe.dmg">Mac</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe_x64.msi">Windows</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe_x86_64.deb">Linux</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x86_64.deb">Linux</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ChatGPT.png width=600/></td> <td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ChatGPT.png width=600/></td>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Poe.png width=600/></td> <td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Qwerty.png width=600/></td>
</tr> </tr>
<tr> <tr>
<td>YouTube Music <td>YouTube Music
@@ -96,22 +96,6 @@
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ProgramMusic.jpg width=600/></td> <td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ProgramMusic.jpg width=600/></td>
</tr> </tr>
<tr> <tr>
<td>Qwerty
<a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Qwerty_x86_64.deb">Linux</a>
</td>
<td>CodeRunner
<a href="https://github.com/tw93/Pake/releases/latest/download/CodeRunner.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/CodeRunner_x64.msi">Windows</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/CodeRunner_x86_64.deb">Linux</a>
</td>
</tr>
<tr>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Qwerty.png width=600/></td>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/CodeRunner.jpg width=600/></td>
</tr>
<tr>
<td>Flomo <td>Flomo
<a href="https://github.com/tw93/Pake/releases/latest/download/Flomo.dmg">Mac</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Flomo.dmg">Mac</a>
<a href="https://github.com/tw93/Pake/releases/latest/download/Flomo_x64.msi">Windows</a> <a href="https://github.com/tw93/Pake/releases/latest/download/Flomo_x64.msi">Windows</a>
@@ -154,7 +138,7 @@
## 始める前に ## 始める前に
1. **初心者の方へ**: 「人気のパッケージ」を使用して Pake の機能を試してみてください。または、[GitHub Actions](<https://github.com/tw93/Pake/wiki/Online-Compilation-(used-by-ordinary-users)>)を使用してアプリケーションをパッケージ化してみてください。[ディスカッション](https://github.com/tw93/Pake/discussions)で助けを求めることもできます! 1. **初心者の方へ**: 「人気のパッケージ」を使用して Pake の機能を試してみてください。または、[GitHub Actions](<https://github.com/tw93/Pake/wiki/Online-Compilation-(used-by-ordinary-users)>)を使用してアプリケーションをパッケージ化してみてください。[ディスカッション](https://github.com/tw93/Pake/discussions)で助けを求めることもできます!
2. **開発者の方へ**: 「コマンドラインパッケージング」を使用してください。macOS では完全にサポートされています。Windows/Linux ユーザーは、[環境を設定](https://tauri.app/v1/guides/getting-started/prerequisites)する必要があります。 2. **開発者の方へ**: 「コマンドラインパッケージング」を使用してください。macOS では完全にサポートされています。Windows/Linux ユーザーは、[環境を設定](https://tauri.app/start/prerequisites/)する必要があります。
3. **ハッカーの方へ**: フロントエンド開発と Rust の両方が得意な方は、以下の[カスタマイズ開発](#開発)でアプリの機能をさらにカスタマイズしてみてください。 3. **ハッカーの方へ**: フロントエンド開発と Rust の両方が得意な方は、以下の[カスタマイズ開発](#開発)でアプリの機能をさらにカスタマイズしてみてください。
## コマンドラインパッケージング ## コマンドラインパッケージング
@@ -178,7 +162,7 @@ pake https://weekly.tw93.fun --name Weekly --hide-title-bar
## 開発 ## 開発
開始する前に、Rust `>=1.63` と Node `>=16` (例: `16.18.1`) がコンピュータにインストールされていることを確認してください。インストールガイドについては、[Tauri ドキュメント](https://tauri.app/v1/guides/getting-started/prerequisites)を参照してください。 開始する前に、Rust `>=1.63` と Node `>=16` (例: `16.18.1`) がコンピュータにインストールされていることを確認してください。インストールガイドについては、[Tauri ドキュメント](https://tauri.app/start/prerequisites/)を参照してください。
これらに不慣れな場合は、上記のツールを使用してワンクリックでパッケージを作成することをお勧めします。 これらに不慣れな場合は、上記のツールを使用してワンクリックでパッケージを作成することをお勧めします。

View File

@@ -1,76 +0,0 @@
{
"apps": [
{
"name": "programmusic",
"title": "ProgramMusic",
"name_zh": "ProgramMusic",
"url": "https://musicforprogramming.net/"
},
{
"name": "twitter",
"title": "Twitter",
"name_zh": "推特",
"url": "https://twitter.com/"
},
{
"name": "youtube",
"title": "YouTube",
"name_zh": "YouTube",
"url": "https://www.youtube.com"
},
{
"name": "coderunner",
"title": "CodeRunner",
"name_zh": "CodeRunner",
"url": "https://riju.codes/"
},
{
"name": "chatgpt",
"title": "ChatGPT",
"name_zh": "ChatGPT",
"url": "https://chat.openai.com/chat"
},
{
"name": "flomo",
"title": "Flomo",
"name_zh": "浮墨",
"url": "https://v.flomoapp.com/mine"
},
{
"name": "qwerty",
"title": "Qwerty",
"name_zh": "Qwerty",
"url": "https://qwerty.kaiyi.cool/"
},
{
"name": "lizhi",
"title": "LiZhi",
"name_zh": "李志",
"url": "https://lizhi.turkyden.com/?from=pake"
},
{
"name": "xiaohongshu",
"title": "XiaoHongShu",
"name_zh": "小红书",
"url": "https://www.xiaohongshu.com/explore"
},
{
"name": "poe",
"title": "Poe",
"name_zh": "Poe",
"url": "https://poe.com/"
},
{
"name": "youtubemusic",
"title": "YouTubeMusic",
"name_zh": "YouTubeMusic",
"url": "https://music.youtube.com/"
},
{
"name": "weread",
"title": "WeRead",
"name_zh": "微信阅读",
"url": "https://weread.qq.com/"
}
]
}

65
bin/README.md vendored
View File

@@ -8,9 +8,10 @@ Ensure that your Node.js version is 18.0 or higher (e.g., 18.20.2). Avoid using
npm install pake-cli -g npm install pake-cli -g
``` ```
## Considerations for Windows & Linux Users <details>
<summary><strong>Considerations for Windows & Linux Users</strong></summary>
- **CRITICAL**: Consult [Tauri prerequisites](https://tauri.app/v1/guides/getting-started/prerequisites) before proceeding. - **CRITICAL**: Consult [Tauri prerequisites](https://tauri.app/start/prerequisites/) before proceeding.
- For Windows users (ensure that `Win10 SDK (10.0.19041.0)` and `Visual Studio build tool 2022 (>=17.2)` are installed), additional installations are required: - For Windows users (ensure that `Win10 SDK (10.0.19041.0)` and `Visual Studio build tool 2022 (>=17.2)` are installed), additional installations are required:
1. Microsoft Visual C++ 2015-2022 Redistributable (x64) 1. Microsoft Visual C++ 2015-2022 Redistributable (x64)
@@ -24,8 +25,8 @@ npm install pake-cli -g
```bash ```bash
sudo apt install libdbus-1-dev \ sudo apt install libdbus-1-dev \
libsoup2.4-dev \ libsoup2.4-dev \
libjavascriptcoregtk-4.0-dev \ libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.0-dev \ libwebkit2gtk-4.1-dev \
build-essential \ build-essential \
curl \ curl \
wget \ wget \
@@ -37,29 +38,9 @@ npm install pake-cli -g
gnome-video-effects-extra gnome-video-effects-extra
``` ```
## Usage </details>
### Development ## CLI Usage
The `DEFAULT_DEV_PAKE_OPTIONS` configuration in `bin/defaults.ts` can be modified at development time to match the `pake-cli` configuration description.
```typescript
export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & { url: string } = {
...DEFAULT_PAKE_OPTIONS,
url: 'https://weread.qq.com',
name: 'Weread',
};
```
then
```bash
yarn cli:dev
```
The script will read the above configuration and packages the specified `app` using `watch` mode, and changes to the `pake-cli` code and `pake` are hot updated in real time.
### CLI Usage
```bash ```bash
pake [url] [options] pake [url] [options]
@@ -221,7 +202,7 @@ Specify the system tray icon. This is only effective when the system tray is ena
#### [installer-language] #### [installer-language]
Set the Windows Installer language. Options include `zh-CN`, `ja-JP`, More at [Tauri Document](https://tauri.app/zh-cn/v1/guides/building/windows/#internationalization). Default is `en-US`. Set the Windows Installer language. Options include `zh-CN`, `ja-JP`, More at [Tauri Document](https://tauri.app/distribute/windows-installer/#internationalization). Default is `en-US`.
```shell ```shell
--installer-language <language> --installer-language <language>
@@ -243,14 +224,12 @@ Using `inject`, you can inject local absolute and relative path `css` and `js` f
--inject ./tools/style.css,./tools/hotkey.js --inject ./tools/style.css,./tools/hotkey.js
``` ```
#### [safe-domain] #### [proxy-url]
This secure domain is a domain other than your currently configured `url` to which you may be redirected or jumped to, and only in domains that have been configured as secure can you use `tauri` to expose `api` to browsers to ensure that pake's built-in enhancements work correctly. Only in a domain that has been configured as secure can you use the `tauri` to expose the `api` to the browser, ensuring that `pake's` built-in enhancements work correctly. If you need to proxy requests for some reason, you can set the proxy address using the `proxy-url` option.
PS: Secure domains do not need to carry protocols.
```shell ```shell
--safe-domain weread.qq.com,google.com --proxy-url <url>
``` ```
#### [debug] #### [debug]
@@ -261,10 +240,30 @@ The typed package has dev-tools for debugging, in addition to outputting more lo
--debug --debug
``` ```
## Conclusion ### Wait a moment
After completing the above steps, your application should be successfully packaged. Please note that the packaging process may take some time depending on your system configuration and network conditions. Be patient, and once the packaging is complete, you can find the application installer in the specified directory. After completing the above steps, your application should be successfully packaged. Please note that the packaging process may take some time depending on your system configuration and network conditions. Be patient, and once the packaging is complete, you can find the application installer in the specified directory.
## Development
The `DEFAULT_DEV_PAKE_OPTIONS` configuration in `bin/defaults.ts` can be modified at development time to match the `pake-cli` configuration description.
```typescript
export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & { url: string } = {
...DEFAULT_PAKE_OPTIONS,
url: 'https://weread.qq.com',
name: 'Weread',
};
```
then
```bash
npm run cli:dev
```
The script will read the above configuration and packages the specified `app` using `watch` mode, and changes to the `pake-cli` code and `pake` are hot updated in real time.
## Docker ## Docker
```shell ```shell

69
bin/README_CN.md vendored
View File

@@ -8,9 +8,10 @@
npm install pake-cli -g npm install pake-cli -g
``` ```
## Windows/Linux 注意事项 <details>
<summary><strong>Windows/Linux 注意事项</strong></summary>
- **非常重要**:请参阅 Tauri 的 [依赖项指南](https://tauri.app/v1/guides/getting-started/prerequisites)。 - **非常重要**:请参阅 Tauri 的 [依赖项指南](https://tauri.app/start/prerequisites/)。
- 对于 Windows 用户,请确保至少安装了 `Win10 SDK(10.0.19041.0)``Visual Studio Build Tools 2022版本 17.2 或更高)`,此外还需要安装以下组件: - 对于 Windows 用户,请确保至少安装了 `Win10 SDK(10.0.19041.0)``Visual Studio Build Tools 2022版本 17.2 或更高)`,此外还需要安装以下组件:
1. Microsoft Visual C++ 2015-2022 Redistributable (x64) 1. Microsoft Visual C++ 2015-2022 Redistributable (x64)
@@ -24,8 +25,8 @@ npm install pake-cli -g
```bash ```bash
sudo apt install libdbus-1-dev \ sudo apt install libdbus-1-dev \
libsoup2.4-dev \ libsoup2.4-dev \
libjavascriptcoregtk-4.0-dev \ libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.0-dev \ libwebkit2gtk-4.1-dev \
build-essential \ build-essential \
curl \ curl \
wget \ wget \
@@ -37,29 +38,9 @@ npm install pake-cli -g
gnome-video-effects-extra gnome-video-effects-extra
``` ```
## 使用方法 </details>
### 开发 ## 命令行使用
开发时可以修改 `bin/defaults.ts` 中 `DEFAULT_DEV_PAKE_OPTIONS` 配置,配置项和 `pake-cli` 配置说明保持一致
```typescript
export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & { url: string } = {
...DEFAULT_PAKE_OPTIONS,
url: 'https://weread.qq.com',
name: 'Weread',
};
```
之后运行
```bash
yarn cli:dev
```
脚本会读取上述配置并使用 `watch` 模式打包指定的 `app`,对 `pake-cli` 代码和 `pake` 的修改都会实时热更新。
### 使用 CLI
```bash ```bash
pake [url] [options] pake [url] [options]
@@ -222,7 +203,7 @@ Linux默认为 `all`。
#### [installer-language] #### [installer-language]
设置 Windows 安装包语言。支持 `zh-CN`、`ja-JP`,更多在 [Tauri 文档](https://tauri.app/zh-cn/v1/guides/building/windows/#internationalization)。默认为 `en-US`。 设置 Windows 安装包语言。支持 `zh-CN`、`ja-JP`,更多在 [Tauri 文档](https://tauri.app/distribute/windows-installer/#internationalization)。默认为 `en-US`。
```shell ```shell
--installer-language <language> --installer-language <language>
@@ -250,16 +231,12 @@ Linux默认为 `all`。
--inject ./tools/style.css --inject ./tools/hotkey.js --inject ./tools/style.css --inject ./tools/hotkey.js
``` ```
#### [safe-domain] #### [proxy-url]
这个安全域名是除你当前配置的 `url` 之外可能会出现重定向或跳转到的其他域名,只有在已配置为安全的域名中, 假如你由于某些缘故需要代理请求,你可以通过 `proxy-url` 选项来设置代理地址。
才能够使用 `tauri` 暴露到浏览器的 `api` ,保证 `pake` 内置增强功能的正确运行。
PS: 安全域名不需要携带协议。
```shell ```shell
--safe-domain weread.qq.com,google.com --proxy-url <url>
``` ```
#### [debug] #### [debug]
@@ -270,11 +247,31 @@ PS: 安全域名不需要携带协议。
--debug --debug
``` ```
## 结语 ### 稍等片刻
完成上述步骤后,您的应用程序应该已经成功打包。请注意,根据您的系统配置和网络状况,打包过程可能需要一些时间。请耐心等待,一旦打包完成,您就可以在指定的目录中找到应用程序安装包。 完成上述步骤后,您的应用程序应该已经成功打包。请注意,根据您的系统配置和网络状况,打包过程可能需要一些时间。请耐心等待,一旦打包完成,您就可以在指定的目录中找到应用程序安装包。
## Docker ## 开发调试
开发时可以修改 `bin/defaults.ts` 中 `DEFAULT_DEV_PAKE_OPTIONS` 配置,配置项和 `pake-cli` 配置说明保持一致
```typescript
export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & { url: string } = {
...DEFAULT_PAKE_OPTIONS,
url: 'https://weread.qq.com',
name: 'Weread',
};
```
之后运行
```bash
npm run cli:dev
```
脚本会读取上述配置并使用 `watch` 模式打包指定的 `app`,对 `pake-cli` 代码和 `pake` 的修改都会实时热更新。
## Docker 使用
```shell ```shell
# 在Linux上您可以通过 Docker 运行 Pake CLI。 # 在Linux上您可以通过 Docker 运行 Pake CLI。

View File

@@ -28,7 +28,7 @@ export default abstract class BaseBuilder {
if (!IS_MAC && !tauriTargetPathExists) { if (!IS_MAC && !tauriTargetPathExists) {
logger.warn('✼ The first use requires installing system dependencies.'); logger.warn('✼ The first use requires installing system dependencies.');
logger.warn('✼ See more in https://tauri.app/v1/guides/getting-started/prerequisites.'); logger.warn('✼ See more in https://tauri.app/guides/getting-started/prerequisites.');
} }
if (!checkRustInstalled()) { if (!checkRustInstalled()) {

View File

@@ -10,7 +10,7 @@ export default class LinuxBuilder extends BaseBuilder {
getFileName(): string { getFileName(): string {
const { name } = this.options; const { name } = this.options;
const arch = process.arch === 'x64' ? 'amd64' : process.arch; const arch = process.arch === 'x64' ? 'amd64' : process.arch;
return `${name}_${tauriConfig.package.version}_${arch}`; return `${name}_${tauriConfig.version}_${arch}`;
} }
// Customize it, considering that there are all targets. // Customize it, considering that there are all targets.

View File

@@ -16,7 +16,7 @@ export default class MacBuilder extends BaseBuilder {
} else { } else {
arch = process.arch === 'arm64' ? 'aarch64' : process.arch; arch = process.arch === 'arm64' ? 'aarch64' : process.arch;
} }
return `${name}_${tauriConfig.package.version}_${arch}`; return `${name}_${tauriConfig.version}_${arch}`;
} }
protected getBuildCommand(): string { protected getBuildCommand(): string {

View File

@@ -11,7 +11,7 @@ export default class WinBuilder extends BaseBuilder {
getFileName(): string { getFileName(): string {
const { name } = this.options; const { name } = this.options;
const { arch } = process; const { arch } = process;
const language = tauriConfig.tauri.bundle.windows.wix.language[0]; const language = tauriConfig.bundle.windows.wix.language[0];
return `${name}_${tauriConfig.package.version}_${arch}_${language}`; return `${name}_${tauriConfig.version}_${arch}_${language}`;
} }
} }

10
bin/cli.ts vendored
View File

@@ -30,9 +30,10 @@ program
.option('--fullscreen', 'Start in full screen', DEFAULT.fullscreen) .option('--fullscreen', 'Start in full screen', DEFAULT.fullscreen)
.option('--hide-title-bar', 'Only for Mac, hide title bar', DEFAULT.hideTitleBar) .option('--hide-title-bar', 'Only for Mac, hide title bar', DEFAULT.hideTitleBar)
.option('--activation-shortcut <string>', 'Shortcut key to active App', DEFAULT.activationShortcut) .option('--activation-shortcut <string>', 'Shortcut key to active App', DEFAULT.activationShortcut)
.option('--multi-arch', 'Only for Mac, supports both Intel and M1', DEFAULT.multiArch) .option('--inject <url>', 'Injection of .js or .css files', DEFAULT.inject)
.option('--inject [injects...]', 'Injection of .js or .css Files', DEFAULT.inject) .option('--proxy-url <url>', "Proxy URL for all network requests", DEFAULT.proxyUrl)
.option('--debug', 'Debug build and more output', DEFAULT.debug) .option('--debug', 'Debug build and more output', DEFAULT.debug)
.option('--multi-arch', 'Only for Mac, supports both Intel and M1', DEFAULT.multiArch)
.addOption(new Option('--user-agent <string>', 'Custom user agent').default(DEFAULT.userAgent).hideHelp()) .addOption(new Option('--user-agent <string>', 'Custom user agent').default(DEFAULT.userAgent).hideHelp())
.addOption( .addOption(
new Option('--targets <string>', 'Only for Linux, option "deb" or "appimage"').default(DEFAULT.targets).hideHelp(), new Option('--targets <string>', 'Only for Linux, option "deb" or "appimage"').default(DEFAULT.targets).hideHelp(),
@@ -44,11 +45,6 @@ program
.default(DEFAULT.disabledWebShortcuts) .default(DEFAULT.disabledWebShortcuts)
.hideHelp(), .hideHelp(),
) )
.addOption(
new Option('--safe-domain [domains...]', 'Domains that Require Security Configuration')
.default(DEFAULT.safeDomain)
.hideHelp(),
)
.addOption(new Option('--show-system-tray', 'Show system tray in app').default(DEFAULT.showSystemTray).hideHelp()) .addOption(new Option('--show-system-tray', 'Show system tray in app').default(DEFAULT.showSystemTray).hideHelp())
.addOption( .addOption(
new Option('--system-tray-icon <string>', 'Custom system tray icon').default(DEFAULT.systemTrayIcon).hideHelp(), new Option('--system-tray-icon <string>', 'Custom system tray icon').default(DEFAULT.systemTrayIcon).hideHelp(),

3
bin/defaults.ts vendored
View File

@@ -17,9 +17,9 @@ export const DEFAULT_PAKE_OPTIONS: PakeCliOptions = {
targets: 'deb', targets: 'deb',
useLocalFile: false, useLocalFile: false,
systemTrayIcon: '', systemTrayIcon: '',
proxyUrl: "",
debug: false, debug: false,
inject: [], inject: [],
safeDomain: [],
installerLanguage: 'en-US', installerLanguage: 'en-US',
}; };
@@ -28,6 +28,5 @@ export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & { url: string } = {
...DEFAULT_PAKE_OPTIONS, ...DEFAULT_PAKE_OPTIONS,
url: 'https://weread.qq.com', url: 'https://weread.qq.com',
name: 'WeRead', name: 'WeRead',
safeDomain: ['weread.qq.com'],
hideTitleBar: true, hideTitleBar: true,
}; };

67
bin/helpers/merge.ts vendored
View File

@@ -25,7 +25,7 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
name, name,
resizable = true, resizable = true,
inject, inject,
safeDomain, proxyUrl,
installerLanguage, installerLanguage,
} = options; } = options;
@@ -45,10 +45,11 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
}; };
Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions }); Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
tauriConf.package.productName = name; tauriConf.productName = name;
tauriConf.tauri.bundle.identifier = identifier; tauriConf.identifier = identifier;
if (platform == "win32") {
tauriConf.tauri.bundle.windows.wix.language[0] = installerLanguage; if (platform == 'win32') {
tauriConf.bundle.windows.wix.language[0] = installerLanguage;
} }
//Judge the type of URL, whether it is a file or a website. //Judge the type of URL, whether it is a file or a website.
@@ -73,34 +74,13 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
// ignore it, because about_pake.html have be erased. // ignore it, because about_pake.html have be erased.
// const filesToCopyBack = ['cli.js', 'about_pake.html']; // const filesToCopyBack = ['cli.js', 'about_pake.html'];
const filesToCopyBack = ['cli.js']; const filesToCopyBack = ['cli.js'];
await Promise.all( await Promise.all(filesToCopyBack.map(file => fsExtra.copy(path.join(distBakDir, file), path.join(distDir, file))));
filesToCopyBack.map(file => fsExtra.copy(path.join(distBakDir, file), path.join(distDir, file))),
);
} }
tauriConf.pake.windows[0].url = fileName; tauriConf.pake.windows[0].url = fileName;
tauriConf.pake.windows[0].url_type = 'local'; tauriConf.pake.windows[0].url_type = 'local';
} else { } else {
tauriConf.pake.windows[0].url_type = 'web'; tauriConf.pake.windows[0].url_type = 'web';
// Set the secure domain for calling window.__TAURI__ to the application domain that has been set.
tauriConf.tauri.security.dangerousRemoteDomainIpcAccess = [
{
domain: new URL(url).hostname,
windows: ['pake'],
enableTauriAPI: true,
},
];
}
if (safeDomain.length > 0) {
tauriConf.tauri.security.dangerousRemoteDomainIpcAccess = [
...tauriConf.tauri.security.dangerousRemoteDomainIpcAccess,
...safeDomain.map(domain => ({
domain,
windows: ['pake'],
enableTauriAPI: true,
})),
];
} }
const platformMap: PlatformMap = { const platformMap: PlatformMap = {
@@ -118,10 +98,10 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
// Processing targets are currently only open to Linux. // Processing targets are currently only open to Linux.
if (platform === 'linux') { if (platform === 'linux') {
delete tauriConf.tauri.bundle.deb.files; delete tauriConf.bundle.linux.deb.files;
const validTargets = ['all', 'deb', 'appimage']; const validTargets = ['all', 'deb', 'appimage', 'rpm'];
if (validTargets.includes(options.targets)) { if (validTargets.includes(options.targets)) {
tauriConf.tauri.bundle.targets = options.targets === 'all' ? ['deb', 'appimage'] : [options.targets]; tauriConf.bundle.targets = options.targets === 'all' ? ['deb', 'appimage', 'rpm'] : [options.targets];
} else { } else {
logger.warn(`✼ The target must be one of ${validTargets.join(', ')}, the default 'deb' will be used.`); logger.warn(`✼ The target must be one of ${validTargets.join(', ')}, the default 'deb' will be used.`);
} }
@@ -157,25 +137,25 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
if (customIconExt !== iconInfo.fileExt) { if (customIconExt !== iconInfo.fileExt) {
updateIconPath = false; updateIconPath = false;
logger.warn(`${iconInfo.message}, but you give ${customIconExt}`); logger.warn(`${iconInfo.message}, but you give ${customIconExt}`);
tauriConf.tauri.bundle.icon = [iconInfo.defaultIcon]; tauriConf.bundle.icon = [iconInfo.defaultIcon];
} else { } else {
const iconPath = path.join(npmDirectory, 'src-tauri/', iconInfo.path); const iconPath = path.join(npmDirectory, 'src-tauri/', iconInfo.path);
tauriConf.tauri.bundle.resources = [iconInfo.path]; tauriConf.bundle.resources = [iconInfo.path];
await fsExtra.copy(options.icon, iconPath); await fsExtra.copy(options.icon, iconPath);
} }
if (updateIconPath) { if (updateIconPath) {
tauriConf.tauri.bundle.icon = [options.icon]; tauriConf.bundle.icon = [options.icon];
} else { } else {
logger.warn(`✼ Icon will remain as default.`); logger.warn(`✼ Icon will remain as default.`);
} }
} else { } else {
logger.warn('✼ Custom icon path may be invalid, default icon will be used instead.'); logger.warn('✼ Custom icon path may be invalid, default icon will be used instead.');
tauriConf.tauri.bundle.icon = [iconInfo.defaultIcon]; tauriConf.bundle.icon = [iconInfo.defaultIcon];
} }
// Set tray icon path. // Set tray icon path.
let trayIconPath = platform === 'darwin' ? 'png/icon_512.png' : tauriConf.tauri.bundle.icon[0]; let trayIconPath = platform === 'darwin' ? 'png/icon_512.png' : tauriConf.bundle.icon[0];
if (systemTrayIcon.length > 0) { if (systemTrayIcon.length > 0) {
try { try {
await fsExtra.pathExists(systemTrayIcon); await fsExtra.pathExists(systemTrayIcon);
@@ -195,8 +175,13 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
} }
} }
tauriConf.tauri.systemTray.iconPath = trayIconPath; tauriConf.app.trayIcon.iconPath = trayIconPath;
tauriConf.pake.system_tray_path = trayIconPath;
delete tauriConf.app.trayIcon;
const injectFilePath = path.join(npmDirectory, `src-tauri/src/inject/custom.js`); const injectFilePath = path.join(npmDirectory, `src-tauri/src/inject/custom.js`);
// inject js or css files // inject js or css files
if (inject?.length > 0) { if (inject?.length > 0) {
if (!inject.every(item => item.endsWith('.css') || item.endsWith('.js'))) { if (!inject.every(item => item.endsWith('.css') || item.endsWith('.js'))) {
@@ -210,6 +195,7 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
tauriConf.pake.inject = []; tauriConf.pake.inject = [];
await fsExtra.writeFile(injectFilePath, ''); await fsExtra.writeFile(injectFilePath, '');
} }
tauriConf.pake.proxy_url = proxyUrl || '';
// Save config file. // Save config file.
const platformConfigPaths: PlatformMap = { const platformConfigPaths: PlatformMap = {
@@ -217,18 +203,21 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
darwin: 'tauri.macos.conf.json', darwin: 'tauri.macos.conf.json',
linux: 'tauri.linux.conf.json', linux: 'tauri.linux.conf.json',
}; };
const configPath = path.join(tauriConfigDirectory, platformConfigPaths[platform]); const configPath = path.join(tauriConfigDirectory, platformConfigPaths[platform]);
const bundleConf = { tauri: { bundle: tauriConf.tauri.bundle } }; const bundleConf = { bundle: tauriConf.bundle };
console.log('pakeConfig', tauriConf.pake);
await fsExtra.outputJSON(configPath, bundleConf, { spaces: 4 }); await fsExtra.outputJSON(configPath, bundleConf, { spaces: 4 });
const pakeConfigPath = path.join(tauriConfigDirectory, 'pake.json'); const pakeConfigPath = path.join(tauriConfigDirectory, 'pake.json');
await fsExtra.outputJSON(pakeConfigPath, tauriConf.pake, { spaces: 4 }); await fsExtra.outputJSON(pakeConfigPath, tauriConf.pake, { spaces: 4 });
let tauriConf2 = JSON.parse(JSON.stringify(tauriConf)); let tauriConf2 = JSON.parse(JSON.stringify(tauriConf));
delete tauriConf2.pake; delete tauriConf2.pake;
delete tauriConf2.tauri.bundle;
// delete tauriConf2.bundle;
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
tauriConf2.tauri.bundle = bundleConf.tauri.bundle; tauriConf2.bundle = bundleConf.bundle;
} }
const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json'); const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json');
await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 }); await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 });

View File

@@ -15,11 +15,15 @@ const { platform } = process;
const platformConfig = platformConfigs[platform]; const platformConfig = platformConfigs[platform];
let tauriConfig = { let tauriConfig = {
tauri: { ...CommonConf,
...CommonConf.tauri, bundle: platformConfig.bundle,
bundle: platformConfig.tauri.bundle, app: {
...CommonConf.app,
trayIcon: {
...CommonConf.app.trayIcon,
...(platformConfig?.app?.trayIcon ?? {}),
},
}, },
package: CommonConf.package,
build: CommonConf.build, build: CommonConf.build,
pake: pakeConf, pake: pakeConf,
}; };

7
bin/types.ts vendored
View File

@@ -27,7 +27,6 @@ export interface PakeCliOptions {
// Enable windows always on top, default false // Enable windows always on top, default false
alwaysOnTop: boolean; alwaysOnTop: boolean;
// Force Mac to use dark mode, default false // Force Mac to use dark mode, default false
darkMode: boolean; darkMode: boolean;
@@ -58,11 +57,11 @@ export interface PakeCliOptions {
// Debug mode, outputs more logs // Debug mode, outputs more logs
debug: boolean; debug: boolean;
/** 需要注入页面的外部脚本 */ /** External scripts that need to be injected into the page. */
inject: string[]; inject: string[];
/* the domain that can use ipc or tauri javascript sdk */ // Set Api Proxy
safeDomain: string[]; proxyUrl: string;
// Installer language, valid for Windows users, default is en-US // Installer language, valid for Windows users, default is en-US
installerLanguage: string; installerLanguage: string;

2
bin/utils/url.ts vendored
View File

@@ -1,4 +1,4 @@
import psl from 'psl'; import * as psl from 'psl';
import isUrl from 'is-url'; import isUrl from 'is-url';
// Extracts the domain from a given URL. // Extracts the domain from a given URL.

62
default_app_list.json Normal file
View File

@@ -0,0 +1,62 @@
[
{
"name": "programmusic",
"title": "ProgramMusic",
"name_zh": "ProgramMusic",
"url": "https://musicforprogramming.net/"
},
{
"name": "twitter",
"title": "Twitter",
"name_zh": "推特",
"url": "https://twitter.com/"
},
{
"name": "youtube",
"title": "YouTube",
"name_zh": "YouTube",
"url": "https://www.youtube.com"
},
{
"name": "chatgpt",
"title": "ChatGPT",
"name_zh": "ChatGPT",
"url": "https://chatgpt.com/"
},
{
"name": "flomo",
"title": "Flomo",
"name_zh": "浮墨",
"url": "https://v.flomoapp.com/mine"
},
{
"name": "qwerty",
"title": "Qwerty",
"name_zh": "Qwerty",
"url": "https://qwerty.kaiyi.cool/"
},
{
"name": "lizhi",
"title": "LiZhi",
"name_zh": "李志",
"url": "https://lizhi.turkyden.com/?from=pake"
},
{
"name": "xiaohongshu",
"title": "XiaoHongShu",
"name_zh": "小红书",
"url": "https://www.xiaohongshu.com/explore"
},
{
"name": "youtubemusic",
"title": "YouTubeMusic",
"name_zh": "YouTubeMusic",
"url": "https://music.youtube.com/"
},
{
"name": "weread",
"title": "WeRead",
"name_zh": "微信阅读",
"url": "https://weread.qq.com/"
}
]

294
dist/cli.js vendored
View File

@@ -16,11 +16,11 @@ import updateNotifier from 'update-notifier';
import axios from 'axios'; import axios from 'axios';
import { dir } from 'tmp-promise'; import { dir } from 'tmp-promise';
import { fileTypeFromBuffer } from 'file-type'; import { fileTypeFromBuffer } from 'file-type';
import psl from 'psl'; import * as psl from 'psl';
import isUrl from 'is-url'; import isUrl from 'is-url';
var name = "pake-cli"; var name = "pake-cli";
var version = "2.6.1"; var version$1 = "3.0.1";
var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 利用 Rust 轻松构建轻量级多端桌面应用。"; var description = "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 利用 Rust 轻松构建轻量级多端桌面应用。";
var engines = { var engines = {
node: ">=16.0.0" node: ">=16.0.0"
@@ -68,8 +68,8 @@ var exports = "./dist/pake.js";
var license = "MIT"; var license = "MIT";
var dependencies = { var dependencies = {
"@tauri-apps/api": "^1.6.0", "@tauri-apps/api": "^1.6.0",
"@tauri-apps/cli": "^1.6.1", "@tauri-apps/cli": "^2.1.0",
axios: "^1.7.7", axios: "^1.7.9",
chalk: "^5.3.0", chalk: "^5.3.0",
commander: "^11.1.0", commander: "^11.1.0",
"file-type": "^18.7.0", "file-type": "^18.7.0",
@@ -78,20 +78,20 @@ var dependencies = {
loglevel: "^1.9.2", loglevel: "^1.9.2",
ora: "^7.0.1", ora: "^7.0.1",
prompts: "^2.4.2", prompts: "^2.4.2",
psl: "^1.9.0", psl: "^1.15.0",
shelljs: "^0.8.5", shelljs: "^0.8.5",
"tmp-promise": "^3.0.3", "tmp-promise": "^3.0.3",
"update-notifier": "^7.3.1" "update-notifier": "^7.3.1"
}; };
var devDependencies = { var devDependencies = {
"@rollup/plugin-alias": "^5.1.0", "@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-json": "^6.1.0", "@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-replace": "^5.0.7", "@rollup/plugin-replace": "^5.0.7",
"@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-terser": "^0.4.4",
"@types/fs-extra": "^11.0.4", "@types/fs-extra": "^11.0.4",
"@types/is-url": "^1.2.32", "@types/is-url": "^1.2.32",
"@types/node": "^20.16.5", "@types/node": "^20.17.10",
"@types/page-icon": "^0.3.6", "@types/page-icon": "^0.3.6",
"@types/prompts": "^2.4.9", "@types/prompts": "^2.4.9",
"@types/psl": "^1.1.3", "@types/psl": "^1.1.3",
@@ -100,14 +100,14 @@ var devDependencies = {
"@types/update-notifier": "^6.0.8", "@types/update-notifier": "^6.0.8",
"app-root-path": "^3.1.0", "app-root-path": "^3.1.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
rollup: "^4.21.3", rollup: "^4.28.1",
"rollup-plugin-typescript2": "^0.36.0", "rollup-plugin-typescript2": "^0.36.0",
tslib: "^2.7.0", tslib: "^2.8.1",
typescript: "^5.6.2" typescript: "^5.7.2"
}; };
var packageJson = { var packageJson = {
name: name, name: name,
version: version, version: version$1,
description: description, description: description,
engines: engines, engines: engines,
bin: bin, bin: bin,
@@ -132,8 +132,8 @@ var windows = [
width: 1200, width: 1200,
height: 780, height: 780,
resizable: true, resizable: true,
dark_mode: false,
always_on_top: false, always_on_top: false,
dark_mode: false,
activation_shortcut: "", activation_shortcut: "",
disabled_web_shortcuts: false disabled_web_shortcuts: false
} }
@@ -148,139 +148,89 @@ var system_tray = {
linux: true, linux: true,
windows: true windows: true
}; };
var system_tray_path = "icons/icon.png";
var inject = [ var inject = [
]; ];
var proxy_url = "";
var pakeConf = { var pakeConf = {
windows: windows, windows: windows,
user_agent: user_agent, user_agent: user_agent,
system_tray: system_tray, system_tray: system_tray,
inject: inject system_tray_path: system_tray_path,
inject: inject,
proxy_url: proxy_url
}; };
var tauri$3 = { var productName$1 = "WeRead";
security: { var identifier = "com.pake.weread";
csp: null, var version = "1.0.0";
dangerousRemoteDomainIpcAccess: [ var app = {
{ withGlobalTauri: true,
domain: "weread.qq.com", trayIcon: {
windows: [ iconPath: "png/weread_512.png",
"pake" iconAsTemplate: false,
], id: "pake-tray"
enableTauriAPI: true
}
]
},
updater: {
active: false
},
systemTray: {
iconPath: "png/icon_512.png",
iconAsTemplate: false
},
allowlist: {
all: true,
fs: {
all: true,
scope: [
"$DOWNLOAD/*"
]
}
} }
}; };
var build = { var build = {
withGlobalTauri: true, frontendDist: "../dist"
devPath: "../dist",
distDir: "../dist",
beforeBuildCommand: "",
beforeDevCommand: ""
}; };
var CommonConf = { var CommonConf = {
"package": { productName: productName$1,
productName: "WeRead", identifier: identifier,
version: "1.0.0" version: version,
}, app: app,
tauri: tauri$3,
build: build build: build
}; };
var tauri$2 = { var bundle$2 = {
bundle: { icon: [
icon: [ "png/weread_256.ico",
"png/weread_256.ico", "png/weread_32.ico"
"png/weread_32.ico" ],
], active: true,
identifier: "com.pake.weread", resources: [
active: true, "png/weread_32.ico"
category: "DeveloperTool", ],
copyright: "", targets: [
externalBin: [ "msi"
], ],
longDescription: "", windows: {
resources: [ digestAlgorithm: "sha256",
"png/weread_32.ico" wix: {
], language: [
shortDescription: "", "en-US"
targets: [ ],
"msi" template: "assets/main.wxs"
],
windows: {
certificateThumbprint: null,
digestAlgorithm: "sha256",
timestampUrl: "",
wix: {
language: [
"en-US"
],
template: "assets/main.wxs"
}
} }
} }
}; };
var WinConf = { var WinConf = {
tauri: tauri$2 bundle: bundle$2
}; };
var tauri$1 = { var bundle$1 = {
bundle: { icon: [
icon: [ "icons/weread.icns"
"icons/weread.icns" ],
], active: true,
identifier: "com.pake.weread", macOS: {
active: true, },
category: "DeveloperTool", targets: [
copyright: "", "dmg"
externalBin: [ ]
],
longDescription: "",
macOS: {
entitlements: null,
exceptionDomain: "",
frameworks: [
],
providerShortName: null,
signingIdentity: null
},
resources: [
],
shortDescription: "",
targets: [
"dmg"
]
}
}; };
var MacConf = { var MacConf = {
tauri: tauri$1 bundle: bundle$1
}; };
var tauri = { var productName = "we-read";
bundle: { var bundle = {
icon: [ icon: [
"png/weread_512.png" "png/weread_512.png"
], ],
identifier: "com.pake.weread", active: true,
active: true, linux: {
category: "DeveloperTool",
copyright: "",
deb: { deb: {
depends: [ depends: [
"curl", "curl",
@@ -289,21 +239,16 @@ var tauri = {
files: { files: {
"/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop" "/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop"
} }
}, }
externalBin: [ },
], targets: [
longDescription: "", "deb",
resources: [ "appimage"
], ]
shortDescription: "",
targets: [
"deb",
"appimage"
]
}
}; };
var LinuxConf = { var LinuxConf = {
tauri: tauri productName: productName,
bundle: bundle
}; };
const platformConfigs = { const platformConfigs = {
@@ -315,11 +260,15 @@ const { platform: platform$2 } = process;
// @ts-ignore // @ts-ignore
const platformConfig = platformConfigs[platform$2]; const platformConfig = platformConfigs[platform$2];
let tauriConfig = { let tauriConfig = {
tauri: { ...CommonConf,
...CommonConf.tauri, bundle: platformConfig.bundle,
bundle: platformConfig.tauri.bundle, app: {
...CommonConf.app,
trayIcon: {
...CommonConf.app.trayIcon,
...(platformConfig?.app?.trayIcon ?? {}),
},
}, },
package: CommonConf.package,
build: CommonConf.build, build: CommonConf.build,
pake: pakeConf, pake: pakeConf,
}; };
@@ -477,7 +426,7 @@ async function combineFiles(files, output) {
} }
async function mergeConfig(url, options, tauriConf) { async function mergeConfig(url, options, tauriConf) {
const { width, height, fullscreen, hideTitleBar, alwaysOnTop, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name, resizable = true, inject, safeDomain, installerLanguage, } = options; const { width, height, fullscreen, hideTitleBar, alwaysOnTop, darkMode, disabledWebShortcuts, activationShortcut, userAgent, showSystemTray, systemTrayIcon, useLocalFile, identifier, name, resizable = true, inject, proxyUrl, installerLanguage, } = options;
const { platform } = process; const { platform } = process;
// Set Windows parameters. // Set Windows parameters.
const tauriConfWindowOptions = { const tauriConfWindowOptions = {
@@ -492,10 +441,10 @@ async function mergeConfig(url, options, tauriConf) {
disabled_web_shortcuts: disabledWebShortcuts, disabled_web_shortcuts: disabledWebShortcuts,
}; };
Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions }); Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
tauriConf.package.productName = name; tauriConf.productName = name;
tauriConf.tauri.bundle.identifier = identifier; tauriConf.identifier = identifier;
if (platform == "win32") { if (platform == 'win32') {
tauriConf.tauri.bundle.windows.wix.language[0] = installerLanguage; tauriConf.bundle.windows.wix.language[0] = installerLanguage;
} }
//Judge the type of URL, whether it is a file or a website. //Judge the type of URL, whether it is a file or a website.
const pathExists = await fsExtra.pathExists(url); const pathExists = await fsExtra.pathExists(url);
@@ -523,24 +472,6 @@ async function mergeConfig(url, options, tauriConf) {
} }
else { else {
tauriConf.pake.windows[0].url_type = 'web'; tauriConf.pake.windows[0].url_type = 'web';
// Set the secure domain for calling window.__TAURI__ to the application domain that has been set.
tauriConf.tauri.security.dangerousRemoteDomainIpcAccess = [
{
domain: new URL(url).hostname,
windows: ['pake'],
enableTauriAPI: true,
},
];
}
if (safeDomain.length > 0) {
tauriConf.tauri.security.dangerousRemoteDomainIpcAccess = [
...tauriConf.tauri.security.dangerousRemoteDomainIpcAccess,
...safeDomain.map(domain => ({
domain,
windows: ['pake'],
enableTauriAPI: true,
})),
];
} }
const platformMap = { const platformMap = {
win32: 'windows', win32: 'windows',
@@ -554,10 +485,10 @@ async function mergeConfig(url, options, tauriConf) {
tauriConf.pake.system_tray[currentPlatform] = showSystemTray; tauriConf.pake.system_tray[currentPlatform] = showSystemTray;
// Processing targets are currently only open to Linux. // Processing targets are currently only open to Linux.
if (platform === 'linux') { if (platform === 'linux') {
delete tauriConf.tauri.bundle.deb.files; delete tauriConf.bundle.linux.deb.files;
const validTargets = ['all', 'deb', 'appimage']; const validTargets = ['all', 'deb', 'appimage', 'rpm'];
if (validTargets.includes(options.targets)) { if (validTargets.includes(options.targets)) {
tauriConf.tauri.bundle.targets = options.targets === 'all' ? ['deb', 'appimage'] : [options.targets]; tauriConf.bundle.targets = options.targets === 'all' ? ['deb', 'appimage', 'rpm'] : [options.targets];
} }
else { else {
logger.warn(`✼ The target must be one of ${validTargets.join(', ')}, the default 'deb' will be used.`); logger.warn(`✼ The target must be one of ${validTargets.join(', ')}, the default 'deb' will be used.`);
@@ -592,15 +523,15 @@ async function mergeConfig(url, options, tauriConf) {
if (customIconExt !== iconInfo.fileExt) { if (customIconExt !== iconInfo.fileExt) {
updateIconPath = false; updateIconPath = false;
logger.warn(`${iconInfo.message}, but you give ${customIconExt}`); logger.warn(`${iconInfo.message}, but you give ${customIconExt}`);
tauriConf.tauri.bundle.icon = [iconInfo.defaultIcon]; tauriConf.bundle.icon = [iconInfo.defaultIcon];
} }
else { else {
const iconPath = path.join(npmDirectory, 'src-tauri/', iconInfo.path); const iconPath = path.join(npmDirectory, 'src-tauri/', iconInfo.path);
tauriConf.tauri.bundle.resources = [iconInfo.path]; tauriConf.bundle.resources = [iconInfo.path];
await fsExtra.copy(options.icon, iconPath); await fsExtra.copy(options.icon, iconPath);
} }
if (updateIconPath) { if (updateIconPath) {
tauriConf.tauri.bundle.icon = [options.icon]; tauriConf.bundle.icon = [options.icon];
} }
else { else {
logger.warn(`✼ Icon will remain as default.`); logger.warn(`✼ Icon will remain as default.`);
@@ -608,10 +539,10 @@ async function mergeConfig(url, options, tauriConf) {
} }
else { else {
logger.warn('✼ Custom icon path may be invalid, default icon will be used instead.'); logger.warn('✼ Custom icon path may be invalid, default icon will be used instead.');
tauriConf.tauri.bundle.icon = [iconInfo.defaultIcon]; tauriConf.bundle.icon = [iconInfo.defaultIcon];
} }
// Set tray icon path. // Set tray icon path.
let trayIconPath = platform === 'darwin' ? 'png/icon_512.png' : tauriConf.tauri.bundle.icon[0]; let trayIconPath = platform === 'darwin' ? 'png/icon_512.png' : tauriConf.bundle.icon[0];
if (systemTrayIcon.length > 0) { if (systemTrayIcon.length > 0) {
try { try {
await fsExtra.pathExists(systemTrayIcon); await fsExtra.pathExists(systemTrayIcon);
@@ -632,7 +563,9 @@ async function mergeConfig(url, options, tauriConf) {
logger.warn(`✼ Default system tray icon will remain unchanged.`); logger.warn(`✼ Default system tray icon will remain unchanged.`);
} }
} }
tauriConf.tauri.systemTray.iconPath = trayIconPath; tauriConf.app.trayIcon.iconPath = trayIconPath;
tauriConf.pake.system_tray_path = trayIconPath;
delete tauriConf.app.trayIcon;
const injectFilePath = path.join(npmDirectory, `src-tauri/src/inject/custom.js`); const injectFilePath = path.join(npmDirectory, `src-tauri/src/inject/custom.js`);
// inject js or css files // inject js or css files
if (inject?.length > 0) { if (inject?.length > 0) {
@@ -648,6 +581,7 @@ async function mergeConfig(url, options, tauriConf) {
tauriConf.pake.inject = []; tauriConf.pake.inject = [];
await fsExtra.writeFile(injectFilePath, ''); await fsExtra.writeFile(injectFilePath, '');
} }
tauriConf.pake.proxy_url = proxyUrl || '';
// Save config file. // Save config file.
const platformConfigPaths = { const platformConfigPaths = {
win32: 'tauri.windows.conf.json', win32: 'tauri.windows.conf.json',
@@ -655,13 +589,13 @@ async function mergeConfig(url, options, tauriConf) {
linux: 'tauri.linux.conf.json', linux: 'tauri.linux.conf.json',
}; };
const configPath = path.join(tauriConfigDirectory, platformConfigPaths[platform]); const configPath = path.join(tauriConfigDirectory, platformConfigPaths[platform]);
const bundleConf = { tauri: { bundle: tauriConf.tauri.bundle } }; const bundleConf = { bundle: tauriConf.bundle };
console.log('pakeConfig', tauriConf.pake);
await fsExtra.outputJSON(configPath, bundleConf, { spaces: 4 }); await fsExtra.outputJSON(configPath, bundleConf, { spaces: 4 });
const pakeConfigPath = path.join(tauriConfigDirectory, 'pake.json'); const pakeConfigPath = path.join(tauriConfigDirectory, 'pake.json');
await fsExtra.outputJSON(pakeConfigPath, tauriConf.pake, { spaces: 4 }); await fsExtra.outputJSON(pakeConfigPath, tauriConf.pake, { spaces: 4 });
let tauriConf2 = JSON.parse(JSON.stringify(tauriConf)); let tauriConf2 = JSON.parse(JSON.stringify(tauriConf));
delete tauriConf2.pake; delete tauriConf2.pake;
delete tauriConf2.tauri.bundle;
const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json'); const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json');
await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 }); await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 });
} }
@@ -676,7 +610,7 @@ class BaseBuilder {
const tauriTargetPathExists = await fsExtra.pathExists(tauriTargetPath); const tauriTargetPathExists = await fsExtra.pathExists(tauriTargetPath);
if (!IS_MAC && !tauriTargetPathExists) { if (!IS_MAC && !tauriTargetPathExists) {
logger.warn('✼ The first use requires installing system dependencies.'); logger.warn('✼ The first use requires installing system dependencies.');
logger.warn('✼ See more in https://tauri.app/v1/guides/getting-started/prerequisites.'); logger.warn('✼ See more in https://tauri.app/guides/getting-started/prerequisites.');
} }
if (!checkRustInstalled()) { if (!checkRustInstalled()) {
const res = await prompts({ const res = await prompts({
@@ -764,7 +698,7 @@ class MacBuilder extends BaseBuilder {
else { else {
arch = process.arch === 'arm64' ? 'aarch64' : process.arch; arch = process.arch === 'arm64' ? 'aarch64' : process.arch;
} }
return `${name}_${tauriConfig.package.version}_${arch}`; return `${name}_${tauriConfig.version}_${arch}`;
} }
getBuildCommand() { getBuildCommand() {
return this.options.multiArch ? 'npm run build:mac' : super.getBuildCommand(); return this.options.multiArch ? 'npm run build:mac' : super.getBuildCommand();
@@ -784,8 +718,8 @@ class WinBuilder extends BaseBuilder {
getFileName() { getFileName() {
const { name } = this.options; const { name } = this.options;
const { arch } = process; const { arch } = process;
const language = tauriConfig.tauri.bundle.windows.wix.language[0]; const language = tauriConfig.bundle.windows.wix.language[0];
return `${name}_${tauriConfig.package.version}_${arch}_${language}`; return `${name}_${tauriConfig.version}_${arch}_${language}`;
} }
} }
@@ -796,7 +730,7 @@ class LinuxBuilder extends BaseBuilder {
getFileName() { getFileName() {
const { name } = this.options; const { name } = this.options;
const arch = process.arch === 'x64' ? 'amd64' : process.arch; const arch = process.arch === 'x64' ? 'amd64' : process.arch;
return `${name}_${tauriConfig.package.version}_${arch}`; return `${name}_${tauriConfig.version}_${arch}`;
} }
// Customize it, considering that there are all targets. // Customize it, considering that there are all targets.
async build(url) { async build(url) {
@@ -848,9 +782,9 @@ const DEFAULT_PAKE_OPTIONS = {
targets: 'deb', targets: 'deb',
useLocalFile: false, useLocalFile: false,
systemTrayIcon: '', systemTrayIcon: '',
proxyUrl: "",
debug: false, debug: false,
inject: [], inject: [],
safeDomain: [],
installerLanguage: 'en-US', installerLanguage: 'en-US',
}; };
@@ -1034,9 +968,10 @@ program
.option('--fullscreen', 'Start in full screen', DEFAULT_PAKE_OPTIONS.fullscreen) .option('--fullscreen', 'Start in full screen', DEFAULT_PAKE_OPTIONS.fullscreen)
.option('--hide-title-bar', 'Only for Mac, hide title bar', DEFAULT_PAKE_OPTIONS.hideTitleBar) .option('--hide-title-bar', 'Only for Mac, hide title bar', DEFAULT_PAKE_OPTIONS.hideTitleBar)
.option('--activation-shortcut <string>', 'Shortcut key to active App', DEFAULT_PAKE_OPTIONS.activationShortcut) .option('--activation-shortcut <string>', 'Shortcut key to active App', DEFAULT_PAKE_OPTIONS.activationShortcut)
.option('--multi-arch', 'Only for Mac, supports both Intel and M1', DEFAULT_PAKE_OPTIONS.multiArch) .option('--inject <url>', 'Injection of .js or .css files', DEFAULT_PAKE_OPTIONS.inject)
.option('--inject [injects...]', 'Injection of .js or .css Files', DEFAULT_PAKE_OPTIONS.inject) .option('--proxy-url <url>', "Proxy URL for all network requests", DEFAULT_PAKE_OPTIONS.proxyUrl)
.option('--debug', 'Debug build and more output', DEFAULT_PAKE_OPTIONS.debug) .option('--debug', 'Debug build and more output', DEFAULT_PAKE_OPTIONS.debug)
.option('--multi-arch', 'Only for Mac, supports both Intel and M1', DEFAULT_PAKE_OPTIONS.multiArch)
.addOption(new Option('--user-agent <string>', 'Custom user agent').default(DEFAULT_PAKE_OPTIONS.userAgent).hideHelp()) .addOption(new Option('--user-agent <string>', 'Custom user agent').default(DEFAULT_PAKE_OPTIONS.userAgent).hideHelp())
.addOption(new Option('--targets <string>', 'Only for Linux, option "deb" or "appimage"').default(DEFAULT_PAKE_OPTIONS.targets).hideHelp()) .addOption(new Option('--targets <string>', 'Only for Linux, option "deb" or "appimage"').default(DEFAULT_PAKE_OPTIONS.targets).hideHelp())
.addOption(new Option('--always-on-top', 'Always on the top level').default(DEFAULT_PAKE_OPTIONS.alwaysOnTop).hideHelp()) .addOption(new Option('--always-on-top', 'Always on the top level').default(DEFAULT_PAKE_OPTIONS.alwaysOnTop).hideHelp())
@@ -1044,9 +979,6 @@ program
.addOption(new Option('--disabled-web-shortcuts', 'Disabled webPage shortcuts') .addOption(new Option('--disabled-web-shortcuts', 'Disabled webPage shortcuts')
.default(DEFAULT_PAKE_OPTIONS.disabledWebShortcuts) .default(DEFAULT_PAKE_OPTIONS.disabledWebShortcuts)
.hideHelp()) .hideHelp())
.addOption(new Option('--safe-domain [domains...]', 'Domains that Require Security Configuration')
.default(DEFAULT_PAKE_OPTIONS.safeDomain)
.hideHelp())
.addOption(new Option('--show-system-tray', 'Show system tray in app').default(DEFAULT_PAKE_OPTIONS.showSystemTray).hideHelp()) .addOption(new Option('--show-system-tray', 'Show system tray in app').default(DEFAULT_PAKE_OPTIONS.showSystemTray).hideHelp())
.addOption(new Option('--system-tray-icon <string>', 'Custom system tray icon').default(DEFAULT_PAKE_OPTIONS.systemTrayIcon).hideHelp()) .addOption(new Option('--system-tray-icon <string>', 'Custom system tray icon').default(DEFAULT_PAKE_OPTIONS.systemTrayIcon).hideHelp())
.addOption(new Option('--installer-language <string>', 'Installer language').default(DEFAULT_PAKE_OPTIONS.installerLanguage).hideHelp()) .addOption(new Option('--installer-language <string>', 'Installer language').default(DEFAULT_PAKE_OPTIONS.installerLanguage).hideHelp())

View File

@@ -1,6 +1,6 @@
{ {
"name": "pake-cli", "name": "pake-cli",
"version": "2.6.1", "version": "3.0.1",
"description": "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 利用 Rust 轻松构建轻量级多端桌面应用。", "description": "🤱🏻 Turn any webpage into a desktop app with Rust. 🤱🏻 利用 Rust 轻松构建轻量级多端桌面应用。",
"engines": { "engines": {
"node": ">=16.0.0" "node": ">=16.0.0"
@@ -48,8 +48,8 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@tauri-apps/api": "^1.6.0", "@tauri-apps/api": "^1.6.0",
"@tauri-apps/cli": "^1.6.1", "@tauri-apps/cli": "^2.1.0",
"axios": "^1.7.7", "axios": "^1.7.9",
"chalk": "^5.3.0", "chalk": "^5.3.0",
"commander": "^11.1.0", "commander": "^11.1.0",
"file-type": "^18.7.0", "file-type": "^18.7.0",
@@ -58,20 +58,20 @@
"loglevel": "^1.9.2", "loglevel": "^1.9.2",
"ora": "^7.0.1", "ora": "^7.0.1",
"prompts": "^2.4.2", "prompts": "^2.4.2",
"psl": "^1.9.0", "psl": "^1.15.0",
"shelljs": "^0.8.5", "shelljs": "^0.8.5",
"tmp-promise": "^3.0.3", "tmp-promise": "^3.0.3",
"update-notifier": "^7.3.1" "update-notifier": "^7.3.1"
}, },
"devDependencies": { "devDependencies": {
"@rollup/plugin-alias": "^5.1.0", "@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-commonjs": "^25.0.8", "@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-json": "^6.1.0", "@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-replace": "^5.0.7", "@rollup/plugin-replace": "^5.0.7",
"@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-terser": "^0.4.4",
"@types/fs-extra": "^11.0.4", "@types/fs-extra": "^11.0.4",
"@types/is-url": "^1.2.32", "@types/is-url": "^1.2.32",
"@types/node": "^20.16.5", "@types/node": "^20.17.10",
"@types/page-icon": "^0.3.6", "@types/page-icon": "^0.3.6",
"@types/prompts": "^2.4.9", "@types/prompts": "^2.4.9",
"@types/psl": "^1.1.3", "@types/psl": "^1.1.3",
@@ -80,9 +80,9 @@
"@types/update-notifier": "^6.0.8", "@types/update-notifier": "^6.0.8",
"app-root-path": "^3.1.0", "app-root-path": "^3.1.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"rollup": "^4.21.3", "rollup": "^4.28.1",
"rollup-plugin-typescript2": "^0.36.0", "rollup-plugin-typescript2": "^0.36.0",
"tslib": "^2.7.0", "tslib": "^2.8.1",
"typescript": "^5.6.2" "typescript": "^5.7.2"
} }
} }

15
script/app_config.mjs vendored
View File

@@ -127,10 +127,7 @@ function updatePakeJson() {
} }
function updateTauriJson() { function updateTauriJson() {
const url = new URL(variables.url); tauriJson.productName = variables.title;
tauriJson.tauri.security.dangerousRemoteDomainIpcAccess[0].domain = url.hostname;
tauriJson.package.productName = variables.title;
writeFileSync('src-tauri/tauri.conf.json', JSON.stringify(tauriJson, null, 2)); writeFileSync('src-tauri/tauri.conf.json', JSON.stringify(tauriJson, null, 2));
} }
@@ -142,8 +139,8 @@ function updateIconFile(iconPath, defaultIconPath) {
} }
function updatePlatformConfig(platformConfig, platformVariables) { function updatePlatformConfig(platformConfig, platformVariables) {
platformConfig.tauri.bundle['icon'] = platformVariables.icon; platformConfig.bundle['icon'] = platformVariables.icon;
platformConfig.tauri.bundle['identifier'] = variables.identifier; platformConfig.identifier = variables.identifier;
} }
function save() { function save() {
@@ -159,11 +156,11 @@ function save() {
} }
function updateDesktopEntry() { function updateDesktopEntry() {
linuxJson.tauri.bundle.deb.files = {}; linuxJson.bundle.linux.deb.files = {};
linuxJson.tauri.bundle.deb.files[variables.linux.desktopEntryConfig.configKey] = variables.linux.desktopEntryConfig.configValue; linuxJson.bundle.linux.deb.files[variables.linux.desktopEntryConfig.configKey] = variables.linux.desktopEntryConfig.configValue;
writeFileSync(variables.linux.desktopEntryPath, variables.linux.desktopEntry); writeFileSync(variables.linux.desktopEntryPath, variables.linux.desktopEntry);
} }
function updateResources() { function updateResources() {
windowsJson.tauri.bundle.resources = variables.windows.resources; windowsJson.bundle.resources = variables.windows.resources;
} }

View File

@@ -17,7 +17,6 @@ console.log('hide-title-bar: ', process.env.HIDE_TITLE_BAR);
console.log('resize: ', process.env.RESIZE); console.log('resize: ', process.env.RESIZE);
console.log('is multi arch? only for Mac: ', process.env.MULTI_ARCH); console.log('is multi arch? only for Mac: ', process.env.MULTI_ARCH);
console.log('targets type? only for Linux: ', process.env.TARGETS); console.log('targets type? only for Linux: ', process.env.TARGETS);
console.log('safe-domain: ', process.env.SAFE_DOMAIN);
console.log('===========================\n'); console.log('===========================\n');
cd('node_modules/pake-cli'); cd('node_modules/pake-cli');
@@ -40,10 +39,6 @@ if (process.env.TARGETS) {
params = `${params} --targets ${process.env.TARGETS}`; params = `${params} --targets ${process.env.TARGETS}`;
} }
if (process.env.SAFE_DOMAIN) {
params = `${params} --safe-domain ${process.env.SAFE_DOMAIN}`;
}
if (process.platform === 'win32' || process.platform === 'linux') { if (process.platform === 'win32' || process.platform === 'linux') {
params = `${params} --show-system-tray`; params = `${params} --show-system-tray`;
} }

4027
src-tauri/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,30 +1,34 @@
[package] [package]
name = "app" name = "pake"
version = "0.1.0" version = "3.0.0"
description = "🤱🏻 Turn any webpage into a desktop app with Rust." description = "🤱🏻 Turn any webpage into a desktop app with Rust."
authors = ["Tw93"] authors = ["Tw93"]
license = "MIT" license = "MIT"
repository = "https://github.com/tw93/Pake" repository = "https://github.com/tw93/Pake"
default-run = "app"
edition = "2021" edition = "2021"
rust-version = "1.78.0" rust-version = "1.78.0"
[lib]
name = "app_lib"
crate-type = ["staticlib", "cdylib", "lib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies] [build-dependencies]
tauri-build = { version = "1.5.2", features = [] } tauri-build = { version = "2.0.3", features = [] }
[dependencies] [dependencies]
serde_json = "1.0.117" serde_json = "1.0.133"
serde = { version = "1.0.202", features = ["derive"] } serde = { version = "1.0.215", features = ["derive"] }
tauri = { version = "1.6.6", features = ["api-all", "system-tray"] } tauri = { version = "2.1.1", features = ["tray-icon", "image-ico", "image-png", "macos-proxy"] }
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } tauri-plugin-window-state = "2.2.0"
tauri-plugin-oauth = { git = "https://github.com/FabianLars/tauri-plugin-oauth", branch = "main" } tauri-plugin-oauth = "2"
tauri-plugin-http = "2.2.0"
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
tauri-plugin-global-shortcut = { version = "2.2.0" }
tauri-plugin-shell = "2.2.0"
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
[dev-dependencies]
cargo-bloat = "0.11.1"
[features] [features]
# this feature is used for development builds from development cli # this feature is used for development builds from development cli
cli-build = [] cli-build = []

View File

@@ -4,6 +4,9 @@
<?elseif $(sys.BUILDARCH)="x64"?> <?elseif $(sys.BUILDARCH)="x64"?>
<?define Win64 = "yes" ?> <?define Win64 = "yes" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?> <?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?elseif $(sys.BUILDARCH)="arm64"?>
<?define Win64 = "yes" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?else?> <?else?>
<?error Unsupported value of sys.BUILDARCH=$(sys.BUILDARCH)?> <?error Unsupported value of sys.BUILDARCH=$(sys.BUILDARCH)?>
<?endif?> <?endif?>
@@ -11,11 +14,11 @@
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product <Product
Id="*" Id="*"
Name="{{{product_name}}}" Name="{{product_name}}"
UpgradeCode="{{{upgrade_code}}}" UpgradeCode="{{upgrade_code}}"
Language="!(loc.TauriLanguage)" Language="!(loc.TauriLanguage)"
Manufacturer="{{{manufacturer}}}" Manufacturer="{{manufacturer}}"
Version="{{{version}}}"> Version="{{version}}">
<Package Id="*" <Package Id="*"
Keywords="Installer" Keywords="Installer"
@@ -29,6 +32,11 @@
<!-- reinstall all files; rewrite all registry entries; reinstall all shortcuts --> <!-- reinstall all files; rewrite all registry entries; reinstall all shortcuts -->
<Property Id="REINSTALLMODE" Value="amus" /> <Property Id="REINSTALLMODE" Value="amus" />
<!-- Auto launch app after installation, useful for passive mode which usually used in updates -->
<Property Id="AUTOLAUNCHAPP" Secure="yes" />
<!-- Property to forward cli args to the launched app to not lose those of the pre-update instance -->
<Property Id="LAUNCHAPPARGS" Secure="yes" />
{{#if allow_downgrades}} {{#if allow_downgrades}}
<MajorUpgrade Schedule="afterInstallInitialize" AllowDowngrades="yes" /> <MajorUpgrade Schedule="afterInstallInitialize" AllowDowngrades="yes" />
{{else}} {{else}}
@@ -42,29 +50,35 @@
<Media Id="1" Cabinet="app.cab" EmbedCab="yes" /> <Media Id="1" Cabinet="app.cab" EmbedCab="yes" />
{{#if banner_path}} {{#if banner_path}}
<WixVariable Id="WixUIBannerBmp" Value="{{{banner_path}}}" /> <WixVariable Id="WixUIBannerBmp" Value="{{banner_path}}" />
{{/if}} {{/if}}
{{#if dialog_image_path}} {{#if dialog_image_path}}
<WixVariable Id="WixUIDialogBmp" Value="{{{dialog_image_path}}}" /> <WixVariable Id="WixUIDialogBmp" Value="{{dialog_image_path}}" />
{{/if}} {{/if}}
{{#if license}} {{#if license}}
<WixVariable Id="WixUILicenseRtf" Value="{{{license}}}" /> <WixVariable Id="WixUILicenseRtf" Value="{{license}}" />
{{/if}} {{/if}}
<Icon Id="ProductIcon" SourceFile="{{{icon_path}}}"/> <Icon Id="ProductIcon" SourceFile="{{icon_path}}"/>
<Property Id="ARPPRODUCTICON" Value="ProductIcon" /> <Property Id="ARPPRODUCTICON" Value="ProductIcon" />
<Property Id="ARPNOREPAIR" Value="yes" Secure="yes" /> <!-- Remove repair --> <Property Id="ARPNOREPAIR" Value="yes" Secure="yes" /> <!-- Remove repair -->
<SetProperty Id="ARPNOMODIFY" Value="1" After="InstallValidate" Sequence="execute"/> <SetProperty Id="ARPNOMODIFY" Value="1" After="InstallValidate" Sequence="execute"/>
{{#if homepage}}
<Property Id="ARPURLINFOABOUT" Value="{{homepage}}"/>
<Property Id="ARPHELPLINK" Value="{{homepage}}"/>
<Property Id="ARPURLUPDATEINFO" Value="{{homepage}}"/>
{{/if}}
<!-- initialize with previous InstallDir --> <!-- initialize with previous InstallDir -->
<Property Id="INSTALLDIR"> <Property Id="INSTALLDIR">
<RegistrySearch Id="PrevInstallDirReg" Root="HKCU" Key="Software\\{{{manufacturer}}}\\{{{product_name}}}" Name="InstallDir" Type="raw"/> <RegistrySearch Id="PrevInstallDirReg" Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="InstallDir" Type="raw"/>
</Property> </Property>
<!-- launch app checkbox --> <!-- launch app checkbox -->
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="!(loc.LaunchApp)" /> <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="!(loc.LaunchApp)" />
<Property Id="WixShellExecTarget" Value="[!Path]" /> <Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1"/>
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" /> <CustomAction Id="LaunchApplication" Impersonate="yes" FileKey="Path" ExeCommand="[LAUNCHAPPARGS]" Return="asyncNoWait" />
<UI> <UI>
<!-- launch app checkbox --> <!-- launch app checkbox -->
@@ -92,27 +106,49 @@
<Directory Id="TARGETDIR" Name="SourceDir"> <Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="DesktopFolder" Name="Desktop"> <Directory Id="DesktopFolder" Name="Desktop">
<Component Id="ApplicationShortcutDesktop" Guid="*"> <Component Id="ApplicationShortcutDesktop" Guid="*">
<Shortcut Id="ApplicationDesktopShortcut" Name="{{{product_name}}}" Description="Runs {{{product_name}}}" Target="[!Path]" WorkingDirectory="INSTALLDIR" /> <Shortcut Id="ApplicationDesktopShortcut" Name="{{product_name}}" Description="Runs {{product_name}}" Target="[!Path]" WorkingDirectory="INSTALLDIR" />
<RemoveFolder Id="DesktopFolder" On="uninstall" /> <RemoveFolder Id="DesktopFolder" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\\{{{manufacturer}}}\\{{{product_name}}}" Name="Desktop Shortcut" Type="integer" Value="1" KeyPath="yes" /> <RegistryValue Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="Desktop Shortcut" Type="integer" Value="1" KeyPath="yes" />
</Component> </Component>
</Directory> </Directory>
<Directory Id="$(var.PlatformProgramFilesFolder)" Name="PFiles"> <Directory Id="$(var.PlatformProgramFilesFolder)" Name="PFiles">
<Directory Id="INSTALLDIR" Name="{{{product_name}}}"/> <Directory Id="INSTALLDIR" Name="{{product_name}}"/>
</Directory> </Directory>
<Directory Id="ProgramMenuFolder"> <Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="{{{product_name}}}"/> <Directory Id="ApplicationProgramsFolder" Name="{{product_name}}"/>
</Directory> </Directory>
</Directory> </Directory>
<DirectoryRef Id="INSTALLDIR"> <DirectoryRef Id="INSTALLDIR">
<Component Id="RegistryEntries" Guid="*"> <Component Id="RegistryEntries" Guid="*">
<RegistryKey Root="HKCU" Key="Software\\{{{manufacturer}}}\\{{{product_name}}}"> <RegistryKey Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}">
<RegistryValue Name="InstallDir" Type="string" Value="[INSTALLDIR]" KeyPath="yes" /> <RegistryValue Name="InstallDir" Type="string" Value="[INSTALLDIR]" KeyPath="yes" />
</RegistryKey> </RegistryKey>
<!-- Change the Root to HKCU for perUser installations -->
{{#each deep_link_protocols as |protocol| ~}}
<RegistryKey Root="HKLM" Key="Software\Classes\\{{protocol}}">
<RegistryValue Type="string" Name="URL Protocol" Value=""/>
<RegistryValue Type="string" Value="URL:{{bundle_id}} protocol"/>
<RegistryKey Key="DefaultIcon">
<RegistryValue Type="string" Value="&quot;[!Path]&quot;,0" />
</RegistryKey>
<RegistryKey Key="shell\open\command">
<RegistryValue Type="string" Value="&quot;[!Path]&quot; &quot;%1&quot;" />
</RegistryKey>
</RegistryKey>
{{/each~}}
</Component> </Component>
<Component Id="Path" Guid="{{{path_component_guid}}}" Win64="$(var.Win64)"> <Component Id="Path" Guid="{{path_component_guid}}" Win64="$(var.Win64)">
<File Id="Path" Source="{{{app_exe_source}}}" KeyPath="yes" Checksum="yes"/> <File Id="Path" Source="{{main_binary_path}}" KeyPath="yes" Checksum="yes"/>
{{#each file_associations as |association| ~}}
{{#each association.ext as |ext| ~}}
<ProgId Id="{{../../product_name}}.{{ext}}" Advertise="yes" Description="{{association.description}}">
<Extension Id="{{ext}}" Advertise="yes">
<Verb Id="open" Command="Open with {{../../product_name}}" Argument="&quot;%1&quot;" />
</Extension>
</ProgId>
{{/each~}}
{{/each~}}
</Component> </Component>
{{#each binaries as |bin| ~}} {{#each binaries as |bin| ~}}
<Component Id="{{ bin.id }}" Guid="{{bin.guid}}" Win64="$(var.Win64)"> <Component Id="{{ bin.id }}" Guid="{{bin.guid}}" Win64="$(var.Win64)">
@@ -130,12 +166,12 @@
<File Id="UpdateTaskUninstaller" Source="uninstall-task.ps1" KeyPath="yes" Checksum="yes"/> <File Id="UpdateTaskUninstaller" Source="uninstall-task.ps1" KeyPath="yes" Checksum="yes"/>
</Component> </Component>
{{/if}} {{/if}}
{{{resources}}} {{resources}}
<Component Id="CMP_UninstallShortcut" Guid="*"> <Component Id="CMP_UninstallShortcut" Guid="*">
<Shortcut Id="UninstallShortcut" <Shortcut Id="UninstallShortcut"
Name="Uninstall {{{product_name}}}" Name="Uninstall {{product_name}}"
Description="Uninstalls {{{product_name}}}" Description="Uninstalls {{product_name}}"
Target="[System64Folder]msiexec.exe" Target="[System64Folder]msiexec.exe"
Arguments="/x [ProductCode]" /> Arguments="/x [ProductCode]" />
@@ -143,7 +179,7 @@
On="uninstall" /> On="uninstall" />
<RegistryValue Root="HKCU" <RegistryValue Root="HKCU"
Key="Software\\{{{manufacturer}}}\\{{{product_name}}}" Key="Software\\{{manufacturer}}\\{{product_name}}"
Name="Uninstaller Shortcut" Name="Uninstaller Shortcut"
Type="integer" Type="integer"
Value="1" Value="1"
@@ -154,15 +190,15 @@
<DirectoryRef Id="ApplicationProgramsFolder"> <DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="ApplicationShortcut" Guid="*"> <Component Id="ApplicationShortcut" Guid="*">
<Shortcut Id="ApplicationStartMenuShortcut" <Shortcut Id="ApplicationStartMenuShortcut"
Name="{{{product_name}}}" Name="{{product_name}}"
Description="Runs {{{product_name}}}" Description="Runs {{product_name}}"
Target="[!Path]" Target="[!Path]"
Icon="ProductIcon" Icon="ProductIcon"
WorkingDirectory="INSTALLDIR"> WorkingDirectory="INSTALLDIR">
<ShortcutProperty Key="System.AppUserModel.ID" Value="{{{bundle_id}}}"/> <ShortcutProperty Key="System.AppUserModel.ID" Value="{{bundle_id}}"/>
</Shortcut> </Shortcut>
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/> <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
<RegistryValue Root="HKCU" Key="Software\\{{{manufacturer}}}\\{{{product_name}}}" Name="Start Menu Shortcut" Type="integer" Value="1" KeyPath="yes"/> <RegistryValue Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="Start Menu Shortcut" Type="integer" Value="1" KeyPath="yes"/>
</Component> </Component>
</DirectoryRef> </DirectoryRef>
@@ -246,7 +282,7 @@
</Property> </Property>
{{#if download_bootstrapper}} {{#if download_bootstrapper}}
<CustomAction Id='DownloadAndInvokeBootstrapper' Directory="INSTALLDIR" Execute="deferred" ExeCommand='powershell.exe -NoProfile -windowstyle hidden try [\{] [\[]Net.ServicePointManager[\]]::SecurityProtocol = [\[]Net.SecurityProtocolType[\]]::Tls12 [\}] catch [\{][\}]; Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -OutFile "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" ; Start-Process -FilePath "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" -ArgumentList ({{{webview_installer_args}}} &apos;/install&apos;) -Wait' Return='check'/> <CustomAction Id='DownloadAndInvokeBootstrapper' Directory="INSTALLDIR" Execute="deferred" ExeCommand='powershell.exe -NoProfile -windowstyle hidden try [\{] [\[]Net.ServicePointManager[\]]::SecurityProtocol = [\[]Net.SecurityProtocolType[\]]::Tls12 [\}] catch [\{][\}]; Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -OutFile "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" ; Start-Process -FilePath "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" -ArgumentList ({{webview_installer_args}} &apos;/install&apos;) -Wait' Return='check'/>
<InstallExecuteSequence> <InstallExecuteSequence>
<Custom Action='DownloadAndInvokeBootstrapper' Before='InstallFinalize'> <Custom Action='DownloadAndInvokeBootstrapper' Before='InstallFinalize'>
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]> <![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
@@ -256,8 +292,8 @@
<!-- Embedded webview bootstrapper mode --> <!-- Embedded webview bootstrapper mode -->
{{#if webview2_bootstrapper_path}} {{#if webview2_bootstrapper_path}}
<Binary Id="MicrosoftEdgeWebview2Setup.exe" SourceFile="{{{webview2_bootstrapper_path}}}"/> <Binary Id="MicrosoftEdgeWebview2Setup.exe" SourceFile="{{webview2_bootstrapper_path}}"/>
<CustomAction Id='InvokeBootstrapper' BinaryKey='MicrosoftEdgeWebview2Setup.exe' Execute="deferred" ExeCommand='{{{webview_installer_args}}} /install' Return='check' /> <CustomAction Id='InvokeBootstrapper' BinaryKey='MicrosoftEdgeWebview2Setup.exe' Execute="deferred" ExeCommand='{{webview_installer_args}} /install' Return='check' />
<InstallExecuteSequence> <InstallExecuteSequence>
<Custom Action='InvokeBootstrapper' Before='InstallFinalize'> <Custom Action='InvokeBootstrapper' Before='InstallFinalize'>
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]> <![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
@@ -267,8 +303,8 @@
<!-- Embedded offline installer --> <!-- Embedded offline installer -->
{{#if webview2_installer_path}} {{#if webview2_installer_path}}
<Binary Id="MicrosoftEdgeWebView2RuntimeInstaller.exe" SourceFile="{{{webview2_installer_path}}}"/> <Binary Id="MicrosoftEdgeWebView2RuntimeInstaller.exe" SourceFile="{{webview2_installer_path}}"/>
<CustomAction Id='InvokeStandalone' BinaryKey='MicrosoftEdgeWebView2RuntimeInstaller.exe' Execute="deferred" ExeCommand='{{{webview_installer_args}}} /install' Return='check' /> <CustomAction Id='InvokeStandalone' BinaryKey='MicrosoftEdgeWebView2RuntimeInstaller.exe' Execute="deferred" ExeCommand='{{webview_installer_args}} /install' Return='check' />
<InstallExecuteSequence> <InstallExecuteSequence>
<Custom Action='InvokeStandalone' Before='InstallFinalize'> <Custom Action='InvokeStandalone' Before='InstallFinalize'>
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]> <![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
@@ -305,6 +341,10 @@
</InstallExecuteSequence> </InstallExecuteSequence>
{{/if}} {{/if}}
<InstallExecuteSequence>
<Custom Action="LaunchApplication" After="InstallFinalize">AUTOLAUNCHAPP AND NOT Installed</Custom>
</InstallExecuteSequence>
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize"/> <SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize"/>
</Product> </Product>
</Wix> </Wix>

View File

@@ -0,0 +1,18 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "pake-capability",
"description": "Capability for the pake app.",
"webviews": ["pake"],
"remote": {
"urls": ["https://*.*"]
},
"permissions": [
"core:window:allow-theme",
"core:window:allow-start-dragging",
"core:window:allow-toggle-maximize",
"core:window:allow-is-fullscreen",
"core:window:allow-set-fullscreen",
"core:webview:allow-internal-toggle-devtools",
"shell:allow-open"
]
}

BIN
src-tauri/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

View File

@@ -8,8 +8,8 @@
"width": 1200, "width": 1200,
"height": 780, "height": 780,
"resizable": true, "resizable": true,
"dark_mode": false,
"always_on_top": false, "always_on_top": false,
"dark_mode": false,
"activation_shortcut": "", "activation_shortcut": "",
"disabled_web_shortcuts": false "disabled_web_shortcuts": false
} }
@@ -24,5 +24,7 @@
"linux": true, "linux": true,
"windows": true "windows": true
}, },
"inject": [] "system_tray_path": "icons/icon.png",
"inject": [],
"proxy_url": ""
} }

View File

@@ -52,6 +52,8 @@ pub struct PakeConfig {
pub windows: Vec<WindowConfig>, pub windows: Vec<WindowConfig>,
pub user_agent: UserAgent, pub user_agent: UserAgent,
pub system_tray: FunctionON, pub system_tray: FunctionON,
pub system_tray_path: String,
pub proxy_url: String,
} }
impl PakeConfig { impl PakeConfig {

View File

@@ -1,8 +1,10 @@
use crate::util::{check_file_or_append, get_download_message, show_toast, MessageType}; use crate::util::{check_file_or_append, get_download_message, show_toast, MessageType};
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::Write; use std::io::Write;
use tauri::api::http::{ClientBuilder, HttpRequestBuilder, ResponseType}; use std::str::FromStr;
use tauri::{api, command, AppHandle, Manager, Window}; use tauri::http::Method;
use tauri::{command, AppHandle, Manager, Url, WebviewWindow};
use tauri_plugin_http::reqwest::{ClientBuilder, Request};
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
pub struct DownloadFileParams { pub struct DownloadFileParams {
@@ -18,24 +20,23 @@ pub struct BinaryDownloadParams {
#[command] #[command]
pub async fn download_file(app: AppHandle, params: DownloadFileParams) -> Result<(), String> { pub async fn download_file(app: AppHandle, params: DownloadFileParams) -> Result<(), String> {
let window: Window = app.get_window("pake").unwrap(); let window: WebviewWindow = app.get_webview_window("pake").unwrap();
show_toast(&window, &get_download_message(MessageType::Start)); show_toast(&window, &get_download_message(MessageType::Start));
let output_path = api::path::download_dir().unwrap().join(params.filename); let output_path = app.path().download_dir().unwrap().join(params.filename);
let file_path = check_file_or_append(output_path.to_str().unwrap()); let file_path = check_file_or_append(output_path.to_str().unwrap());
let client = ClientBuilder::new().build().unwrap(); let client = ClientBuilder::new().build().unwrap();
let response = client let response = client
.send( .execute(Request::new(
HttpRequestBuilder::new("GET", &params.url) Method::GET,
.unwrap() Url::from_str(&params.url).unwrap(),
.response_type(ResponseType::Binary), ))
)
.await; .await;
match response { match response {
Ok(res) => { Ok(res) => {
let bytes = res.bytes().await.unwrap().data; let bytes = res.bytes().await.unwrap();
let mut file = File::create(file_path).unwrap(); let mut file = File::create(file_path).unwrap();
file.write_all(&bytes).unwrap(); file.write_all(&bytes).unwrap();
@@ -54,9 +55,9 @@ pub async fn download_file_by_binary(
app: AppHandle, app: AppHandle,
params: BinaryDownloadParams, params: BinaryDownloadParams,
) -> Result<(), String> { ) -> Result<(), String> {
let window: Window = app.get_window("pake").unwrap(); let window: WebviewWindow = app.get_webview_window("pake").unwrap();
show_toast(&window, &get_download_message(MessageType::Start)); show_toast(&window, &get_download_message(MessageType::Start));
let output_path = api::path::download_dir().unwrap().join(params.filename); let output_path = app.path().download_dir().unwrap().join(params.filename);
let file_path = check_file_or_append(output_path.to_str().unwrap()); let file_path = check_file_or_append(output_path.to_str().unwrap());
let download_file_result = fs::write(file_path, &params.binary); let download_file_result = fs::write(file_path, &params.binary);
match download_file_result { match download_file_result {

View File

@@ -1,31 +1,36 @@
use tauri::{CustomMenuItem, Manager, SystemTray, SystemTrayEvent, SystemTrayMenu}; use tauri::{
menu::{MenuBuilder, MenuItemBuilder},
tray::TrayIconBuilder,
AppHandle, Manager,
};
use tauri_plugin_window_state::{AppHandleExt, StateFlags}; use tauri_plugin_window_state::{AppHandleExt, StateFlags};
pub fn get_system_tray() -> SystemTray { pub fn set_system_tray(app: &AppHandle) -> tauri::Result<()> {
let hide_app = CustomMenuItem::new("hide_app".to_string(), "Hide"); let hide_app = MenuItemBuilder::with_id("hide_app", "Hide").build(app)?;
let show_app = CustomMenuItem::new("show_app".to_string(), "Show"); let show_app = MenuItemBuilder::with_id("show_app", "Show").build(app)?;
let quit = CustomMenuItem::new("quit".to_string(), "Quit"); let quit = MenuItemBuilder::with_id("quit", "Quit").build(app)?;
let tray_menu = SystemTrayMenu::new() let menu = MenuBuilder::new(app)
.add_item(show_app) .items(&[&hide_app, &show_app, &quit])
.add_item(hide_app) .build()?;
.add_item(quit); app.app_handle().remove_tray_by_id("pake-tray");
SystemTray::new().with_menu(tray_menu) let tray = TrayIconBuilder::new()
} .menu(&menu)
.on_menu_event(move |app, event| match event.id().as_ref() {
pub fn system_tray_handle(app: &tauri::AppHandle, event: SystemTrayEvent) {
if let SystemTrayEvent::MenuItemClick { tray_id: _, id, .. } = event {
match id.as_str() {
"hide_app" => { "hide_app" => {
app.get_window("pake").unwrap().minimize().unwrap(); app.get_webview_window("pake").unwrap().minimize().unwrap();
} }
"show_app" => { "show_app" => {
app.get_window("pake").unwrap().show().unwrap(); app.get_webview_window("pake").unwrap().show().unwrap();
} }
"quit" => { "quit" => {
let _res = app.save_window_state(StateFlags::all()); let _res = app.save_window_state(StateFlags::all());
std::process::exit(0); std::process::exit(0);
} }
_ => {} _ => (),
} })
}; .icon(app.default_window_icon().unwrap().clone())
.build(app)?;
tray.set_icon_as_template(false)?;
Ok(())
} }

View File

@@ -1,11 +1,11 @@
use crate::app::config::PakeConfig; use crate::app::config::PakeConfig;
use std::path::PathBuf; use std::{path::PathBuf, str::FromStr};
use tauri::{App, Window, WindowBuilder, WindowUrl}; use tauri::{App, Url, WebviewUrl, WebviewWindow, WebviewWindowBuilder};
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
use tauri::{Theme, TitleBarStyle}; use tauri::{Theme, TitleBarStyle};
pub fn build_window(app: &mut App, config: PakeConfig, _data_dir: PathBuf) -> Window { pub fn get_window(app: &mut App, config: &PakeConfig, _data_dir: PathBuf) -> WebviewWindow {
let window_config = config let window_config = config
.windows .windows
.first() .first()
@@ -14,8 +14,8 @@ pub fn build_window(app: &mut App, config: PakeConfig, _data_dir: PathBuf) -> Wi
let user_agent = config.user_agent.get(); let user_agent = config.user_agent.get();
let url = match window_config.url_type.as_str() { let url = match window_config.url_type.as_str() {
"web" => WindowUrl::App(window_config.url.parse().unwrap()), "web" => WebviewUrl::App(window_config.url.parse().unwrap()),
"local" => WindowUrl::App(PathBuf::from(&window_config.url)), "local" => WebviewUrl::App(PathBuf::from(&window_config.url)),
_ => panic!("url type can only be web or local"), _ => panic!("url type can only be web or local"),
}; };
@@ -24,7 +24,7 @@ pub fn build_window(app: &mut App, config: PakeConfig, _data_dir: PathBuf) -> Wi
serde_json::to_string(&window_config).unwrap() serde_json::to_string(&window_config).unwrap()
); );
let mut window_builder = WindowBuilder::new(app, "pake", url) let mut window_builder = WebviewWindowBuilder::new(app, "pake", url)
.title("") .title("")
.visible(false) .visible(false)
.user_agent(user_agent) .user_agent(user_agent)
@@ -32,12 +32,18 @@ pub fn build_window(app: &mut App, config: PakeConfig, _data_dir: PathBuf) -> Wi
.fullscreen(window_config.fullscreen) .fullscreen(window_config.fullscreen)
.inner_size(window_config.width, window_config.height) .inner_size(window_config.width, window_config.height)
.always_on_top(window_config.always_on_top) .always_on_top(window_config.always_on_top)
.disable_drag_drop_handler()
.initialization_script(&config_script) .initialization_script(&config_script)
.initialization_script(include_str!("../inject/component.js")) .initialization_script(include_str!("../inject/component.js"))
.initialization_script(include_str!("../inject/event.js")) .initialization_script(include_str!("../inject/event.js"))
.initialization_script(include_str!("../inject/style.js")) .initialization_script(include_str!("../inject/style.js"))
.initialization_script(include_str!("../inject/custom.js")); .initialization_script(include_str!("../inject/custom.js"));
if !config.proxy_url.is_empty() {
window_builder =
window_builder.proxy_url(Url::from_str(config.proxy_url.as_str()).unwrap());
}
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
let title_bar_style = if window_config.hide_title_bar { let title_bar_style = if window_config.hide_title_bar {
@@ -45,7 +51,6 @@ pub fn build_window(app: &mut App, config: PakeConfig, _data_dir: PathBuf) -> Wi
} else { } else {
TitleBarStyle::Visible TitleBarStyle::Visible
}; };
window_builder = window_builder.title_bar_style(title_bar_style); window_builder = window_builder.title_bar_style(title_bar_style);
if window_config.dark_mode { if window_config.dark_mode {
@@ -57,7 +62,7 @@ pub fn build_window(app: &mut App, config: PakeConfig, _data_dir: PathBuf) -> Wi
{ {
window_builder = window_builder window_builder = window_builder
.data_directory(_data_dir) .data_directory(_data_dir)
.title(app.package_info().name.clone()) .title(app.package_info().name.clone());
} }
window_builder.build().expect("Failed to build window") window_builder.build().expect("Failed to build window")

View File

@@ -1,6 +0,0 @@
/*
* This file serves as a collection point for external JS and CSS dependencies.
* It amalgamates these external resources for easier injection into the application.
* Additionally, you can directly include any script files in this file
* that you wish to attach to the application.
*/

View File

@@ -45,22 +45,16 @@ function isDownloadLink(url) {
'jpg', 'm3u8', 'mov', 'mp3', 'mp4', 'mpa', 'mpg', 'mpeg', 'msi', 'odt', 'jpg', 'm3u8', 'mov', 'mp3', 'mp4', 'mpa', 'mpg', 'mpeg', 'msi', 'odt',
'ogg', 'ogv', 'pdf', 'png', 'ppt', 'pptx', 'psd', 'rar', 'raw', 'ogg', 'ogv', 'pdf', 'png', 'ppt', 'pptx', 'psd', 'rar', 'raw',
'svg', 'swf', 'tar', 'tif', 'tiff', 'ts', 'txt', 'wav', 'webm', 'webp', 'svg', 'swf', 'tar', 'tif', 'tiff', 'ts', 'txt', 'wav', 'webm', 'webp',
'wma', 'wmv', 'xls', 'xlsx', 'xml', 'zip', 'json', 'yaml', '7zip', 'mkv' 'wma', 'wmv', 'xls', 'xlsx', 'xml', 'zip', 'json', 'yaml', '7zip', 'mkv',
]; ];
const downloadLinkPattern = new RegExp(`\\.(${fileExtensions.join('|')})$`, 'i'); const downloadLinkPattern = new RegExp(`\\.(${fileExtensions.join('|')})$`, 'i');
return downloadLinkPattern.test(url); return downloadLinkPattern.test(url);
} }
// No need to go to the download link.
function externalDownLoadLink() {
return ['quickref.me'].indexOf(location.hostname) > -1;
}
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const tauri = window.__TAURI__; const tauri = window.__TAURI__;
const appWindow = tauri.window.appWindow; const appWindow = tauri.window.getCurrentWindow();
const invoke = tauri.tauri.invoke; const invoke = tauri.core.invoke;
if (!document.getElementById('pake-top-dom')) { if (!document.getElementById('pake-top-dom')) {
const topDom = document.createElement('div'); const topDom = document.createElement('div');
@@ -71,19 +65,19 @@ document.addEventListener('DOMContentLoaded', () => {
const domEl = document.getElementById('pake-top-dom'); const domEl = document.getElementById('pake-top-dom');
domEl.addEventListener('touchstart', () => { domEl.addEventListener('touchstart', () => {
appWindow.startDragging().then(); appWindow.startDragging();
}); });
domEl.addEventListener('mousedown', e => { domEl.addEventListener('mousedown', e => {
e.preventDefault(); e.preventDefault();
if (e.buttons === 1 && e.detail !== 2) { if (e.buttons === 1 && e.detail !== 2) {
appWindow.startDragging().then(); appWindow.startDragging();
} }
}); });
domEl.addEventListener('dblclick', () => { domEl.addEventListener('dblclick', () => {
appWindow.isFullscreen().then(fullscreen => { appWindow.isFullscreen().then(fullscreen => {
appWindow.setFullscreen(!fullscreen).then(); appWindow.setFullscreen(!fullscreen);
}); });
}); });
@@ -186,30 +180,38 @@ document.addEventListener('DOMContentLoaded', () => {
const isDownloadRequired = (url, anchorElement, e) => anchorElement.download || e.metaKey || e.ctrlKey || isDownloadLink(url); const isDownloadRequired = (url, anchorElement, e) => anchorElement.download || e.metaKey || e.ctrlKey || isDownloadLink(url);
const handleExternalLink = (e, url) => { const handleExternalLink = url => {
e.preventDefault(); invoke('plugin:shell|open', {
tauri.shell.open(url); path: url,
}; });
const handleDownloadLink = (e, url, filename) => {
e.preventDefault();
invoke('download_file', { params: { url, filename } });
}; };
const detectAnchorElementClick = e => { const detectAnchorElementClick = e => {
const anchorElement = e.target.closest('a');
if (anchorElement && anchorElement.href) {
if (!anchorElement.target) {
anchorElement.target = '_self';
}
const anchorElement = e.target.closest('a');
if (anchorElement && anchorElement.href) {
const target = anchorElement.target;
const hrefUrl = new URL(anchorElement.href); const hrefUrl = new URL(anchorElement.href);
const absoluteUrl = hrefUrl.href; const absoluteUrl = hrefUrl.href;
let filename = anchorElement.download || getFilenameFromUrl(absoluteUrl); let filename = anchorElement.download || getFilenameFromUrl(absoluteUrl);
// Handling external link redirection, _blank will automatically open.
if (target === '_blank') {
e.preventDefault();
return;
}
if (target === '_new') {
e.preventDefault();
handleExternalLink(absoluteUrl);
return;
}
// Process download links for Rust to handle. // Process download links for Rust to handle.
if (isDownloadRequired(absoluteUrl, anchorElement, e) && !externalDownLoadLink() && !isSpecialDownload(absoluteUrl)) { if (isDownloadRequired(absoluteUrl, anchorElement, e) && !isSpecialDownload(absoluteUrl)) {
handleDownloadLink(e, absoluteUrl, filename); e.preventDefault();
invoke('download_file', { params: { url: absoluteUrl, filename } });
} }
} }
}; };
@@ -231,7 +233,7 @@ document.addEventListener('DOMContentLoaded', () => {
} else { } else {
const baseUrl = window.location.origin + window.location.pathname; const baseUrl = window.location.origin + window.location.pathname;
const hrefUrl = new URL(url, baseUrl); const hrefUrl = new URL(url, baseUrl);
tauri.shell.open(hrefUrl.href); handleExternalLink(hrefUrl.href);
} }
// Call the original window.open function to maintain its normal functionality. // Call the original window.open function to maintain its normal functionality.
return originalWindowOpen.call(window, url, name, specs); return originalWindowOpen.call(window, url, name, specs);

View File

@@ -119,7 +119,8 @@ window.addEventListener('DOMContentLoaded', _event => {
display: none !important; display: none !important;
} }
#react-root [data-testid="DMDrawer"] { #react-root [data-testid="DMDrawer"],
#root > main > footer.justify-center.ease-in {
visibility: hidden !important; visibility: hidden !important;
} }
@@ -333,6 +334,14 @@ window.addEventListener('DOMContentLoaded', _event => {
#__next>div>div>.flex.h-screen.w-full.flex-col.items-center { #__next>div>div>.flex.h-screen.w-full.flex-col.items-center {
padding-top: 20px; padding-top: 20px;
} }
body > div.relative.flex.h-full.w-full.overflow-hidden.transition-colors.z-0 > div.z-\\[21\\].flex-shrink-0.overflow-x-hidden.bg-token-sidebar-surface-primary.max-md\\:\\!w-0 > div > div > div > nav > div.flex.justify-between.h-\\[60px\\].items-center.md\\:h-header-height {
padding-top: 25px;
}
body > div.relative.flex.h-full.w-full.overflow-hidden.transition-colors.z-0 > div.relative.flex.h-full.max-w-full.flex-1.flex-col.overflow-hidden > main > div.composer-parent.flex.h-full.flex-col.focus-visible\\:outline-0 > div.flex-1.overflow-hidden.\\@container\\/thread > div > div.absolute.left-0.right-0 > div{
padding-top: 35px;
}
#__next .sticky.left-0.right-0.top-0.z-20.bg-black{ #__next .sticky.left-0.right-0.top-0.z-20.bg-black{
padding-top: 0px; padding-top: 0px;
@@ -378,6 +387,10 @@ window.addEventListener('DOMContentLoaded', _event => {
.lark > .main-wrapper [data-testid="aside"] { .lark > .main-wrapper [data-testid="aside"] {
top: 15px; top: 15px;
} }
#global > div.header-container > .mask-paper {
padding-top: 20px;
}
#background.ytd-masthead { #background.ytd-masthead {
height: 68px; height: 68px;

133
src-tauri/src/lib.rs Normal file
View File

@@ -0,0 +1,133 @@
#[cfg_attr(mobile, tauri::mobile_entry_point)]
mod app;
mod util;
use app::{invoke, menu::set_system_tray, window};
use invoke::{download_file, download_file_by_binary};
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use tauri::Manager;
use tauri_plugin_global_shortcut::{GlobalShortcutExt, Shortcut};
use tauri_plugin_window_state::Builder as windowStatePlugin;
use util::{get_data_dir, get_pake_config};
use window::get_window;
pub fn run_app() {
let (pake_config, tauri_config) = get_pake_config();
let tauri_app = tauri::Builder::default();
let show_system_tray = pake_config.show_system_tray();
// Save the value of toggle_app_shortcut before pake_config is moved
let activation_shortcut = pake_config.windows[0].activation_shortcut.clone();
let init_fullscreen = pake_config.windows[0].fullscreen;
let window_state_plugin = if init_fullscreen {
windowStatePlugin::default()
.with_state_flags(tauri_plugin_window_state::StateFlags::FULLSCREEN)
.build()
} else {
windowStatePlugin::default().build()
};
tauri_app
.plugin(window_state_plugin)
.plugin(tauri_plugin_oauth::init())
.plugin(tauri_plugin_http::init())
.plugin(tauri_plugin_shell::init())
.invoke_handler(tauri::generate_handler![
download_file,
download_file_by_binary
])
.setup(move |app| {
let data_dir = get_data_dir(app.app_handle(), tauri_config.clone());
let _window = get_window(app, &pake_config, data_dir);
// Prevent initial shaking
_window.show().unwrap();
if show_system_tray {
let _ = set_system_tray(app.app_handle());
} else {
app.app_handle().remove_tray_by_id("pake-tray");
}
if !activation_shortcut.is_empty() {
let app_handle = app.app_handle().clone();
let shortcut_hotkey = Shortcut::from_str(activation_shortcut.as_str()).unwrap();
let last_triggered = Arc::new(Mutex::new(Instant::now()));
app_handle
.plugin(
tauri_plugin_global_shortcut::Builder::new()
.with_handler({
let last_triggered = Arc::clone(&last_triggered);
move |app, event, _shortcut| {
// Fixed the bug of tauri's hidden call, which caused repeated execution
let now = Instant::now();
let mut last = last_triggered.lock().unwrap();
if now.duration_since(*last) < Duration::from_millis(500) {
return;
}
*last = now;
if shortcut_hotkey.eq(event) {
let window = app.get_webview_window("pake").unwrap();
let is_visible = window.is_visible().unwrap();
match is_visible {
true => {
window.minimize().unwrap();
}
false => {
window.unminimize().unwrap();
window.set_focus().unwrap();
}
}
}
}
})
.build(),
)
.expect("Error registering global evoke shortcuts!");
app.global_shortcut().register(shortcut_hotkey)?;
}
Ok(())
})
.on_window_event(|window, event| {
if let tauri::WindowEvent::CloseRequested { api, .. } = event {
let window = window.clone();
#[cfg(target_os = "macos")]
{
let window_handle = window.clone();
tauri::async_runtime::spawn(async move {
if window_handle.is_fullscreen().unwrap_or(false) {
window_handle.set_fullscreen(false).unwrap();
// Give a small delay to ensure the full-screen exit operation is completed.
tokio::time::sleep(Duration::from_millis(900)).await;
}
window_handle.minimize().unwrap();
window_handle.hide().unwrap();
});
}
#[cfg(not(target_os = "macos"))]
window.close().unwrap();
api.prevent_close();
}
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
pub fn run() {
run_app()
}

View File

@@ -3,93 +3,6 @@
windows_subsystem = "windows" windows_subsystem = "windows"
)] )]
mod app;
mod util;
use app::{invoke, menu, window};
use invoke::{download_file, download_file_by_binary};
use menu::{get_system_tray, system_tray_handle};
use tauri::{GlobalShortcutManager, Manager};
use util::{get_data_dir, get_pake_config};
use window::build_window;
#[cfg(target_os = "macos")]
use std::time::Duration;
pub fn run_app() {
let (pake_config, tauri_config) = get_pake_config();
let data_dir = get_data_dir(tauri_config);
let mut tauri_app = tauri::Builder::default();
let show_system_tray = pake_config.show_system_tray();
let system_tray = get_system_tray();
if show_system_tray {
tauri_app = tauri_app
.system_tray(system_tray)
.on_system_tray_event(system_tray_handle);
}
// Save the value of toggle_app_shortcut before pake_config is moved
let activation_shortcut = pake_config.windows[0].activation_shortcut.clone();
tauri_app
.plugin(tauri_plugin_window_state::Builder::default().build())
.plugin(tauri_plugin_oauth::init())
.invoke_handler(tauri::generate_handler![
download_file,
download_file_by_binary
])
.setup(move |app| {
let _window = build_window(app, pake_config, data_dir);
_window.show().unwrap();
if !activation_shortcut.is_empty() {
let app_handle = app.app_handle().clone();
app_handle
.global_shortcut_manager()
.register(activation_shortcut.as_str(), move || {
match _window.is_visible().unwrap() {
true => _window.hide().unwrap(),
false => {
_window.show().unwrap();
_window.set_focus().unwrap();
}
}
})
.expect("Error registering global evoke shortcuts!");
}
Ok(())
})
.on_window_event(|event| {
if let tauri::WindowEvent::CloseRequested { api, .. } = event.event() {
let window = event.window();
#[cfg(target_os = "macos")]
{
let window_handle = window.clone();
tauri::async_runtime::spawn(async move {
if window_handle.is_fullscreen().unwrap_or(false) {
window_handle.set_fullscreen(false).unwrap();
// Give a small delay to ensure the full-screen exit operation is completed.
tokio::time::sleep(Duration::from_millis(900)).await;
}
window_handle.minimize().unwrap();
window_handle.hide().unwrap();
});
}
#[cfg(not(target_os = "macos"))]
window.close().unwrap();
api.prevent_close();
}
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
fn main() { fn main() {
run_app() app_lib::run()
} }

View File

@@ -1,7 +1,7 @@
use crate::app::config::PakeConfig; use crate::app::config::PakeConfig;
use std::env; use std::env;
use std::path::PathBuf; use std::path::PathBuf;
use tauri::{api, Config, Window}; use tauri::{AppHandle, Config, Manager, WebviewWindow};
pub fn get_pake_config() -> (PakeConfig, Config) { pub fn get_pake_config() -> (PakeConfig, Config) {
#[cfg(feature = "cli-build")] #[cfg(feature = "cli-build")]
@@ -23,10 +23,12 @@ pub fn get_pake_config() -> (PakeConfig, Config) {
(pake_config, tauri_config) (pake_config, tauri_config)
} }
pub fn get_data_dir(_tauri_config: Config) -> PathBuf { pub fn get_data_dir(app: &AppHandle, _tauri_config: Config) -> PathBuf {
{ {
let package_name = _tauri_config.package.product_name.unwrap(); let package_name = _tauri_config.product_name.unwrap();
let data_dir = api::path::config_dir() let data_dir = app
.path()
.config_dir()
.expect("Failed to get data dirname") .expect("Failed to get data dirname")
.join(package_name); .join(package_name);
@@ -38,7 +40,7 @@ pub fn get_data_dir(_tauri_config: Config) -> PathBuf {
} }
} }
pub fn show_toast(window: &Window, message: &str) { pub fn show_toast(window: &WebviewWindow, message: &str) {
let script = format!(r#"pakeToast("{}");"#, message); let script = format!(r#"pakeToast("{}");"#, message);
window.eval(&script).unwrap(); window.eval(&script).unwrap();
} }

View File

@@ -1,39 +1,16 @@
{ {
"package": { "productName": "WeRead",
"productName": "WeRead", "identifier": "com.pake.weread",
"version": "1.0.0" "version": "1.0.0",
}, "app": {
"tauri": { "withGlobalTauri": true,
"security": { "trayIcon": {
"csp": null, "iconPath": "png/weread_512.png",
"dangerousRemoteDomainIpcAccess": [ "iconAsTemplate": false,
{ "id": "pake-tray"
"domain": "weread.qq.com",
"windows": ["pake"],
"enableTauriAPI": true
}
]
},
"updater": {
"active": false
},
"systemTray": {
"iconPath": "png/icon_512.png",
"iconAsTemplate": false
},
"allowlist": {
"all": true,
"fs": {
"all": true,
"scope": ["$DOWNLOAD/*"]
}
} }
}, },
"build": { "build": {
"withGlobalTauri": true, "frontendDist": "../dist"
"devPath": "../dist",
"distDir": "../dist",
"beforeBuildCommand": "",
"beforeDevCommand": ""
} }
} }

View File

@@ -1,20 +1,14 @@
{ {
"tauri": { "productName": "we-read",
"bundle": { "bundle": {
"icon": ["png/weread_512.png"], "icon": ["png/weread_512.png"],
"identifier": "com.pake.weread", "active": true,
"active": true, "linux": {
"category": "DeveloperTool",
"copyright": "",
"deb": { "deb": {
"depends": ["curl", "wget"], "depends": ["curl", "wget"],
"files": { "/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop" } "files": { "/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop" }
}, }
"externalBin": [], },
"longDescription": "", "targets": ["deb", "appimage"]
"resources": [],
"shortDescription": "",
"targets": ["deb", "appimage"]
}
} }
} }

View File

@@ -1,23 +1,8 @@
{ {
"tauri": { "bundle": {
"bundle": { "icon": ["icons/weread.icns"],
"icon": ["icons/weread.icns"], "active": true,
"identifier": "com.pake.weread", "macOS": {},
"active": true, "targets": ["dmg"]
"category": "DeveloperTool",
"copyright": "",
"externalBin": [],
"longDescription": "",
"macOS": {
"entitlements": null,
"exceptionDomain": "",
"frameworks": [],
"providerShortName": null,
"signingIdentity": null
},
"resources": [],
"shortDescription": "",
"targets": ["dmg"]
}
} }
} }

View File

@@ -1,24 +1,14 @@
{ {
"tauri": { "bundle": {
"bundle": { "icon": ["png/weread_256.ico", "png/weread_32.ico"],
"icon": ["png/weread_256.ico", "png/weread_32.ico"], "active": true,
"identifier": "com.pake.weread", "resources": ["png/weread_32.ico"],
"active": true, "targets": ["msi"],
"category": "DeveloperTool", "windows": {
"copyright": "", "digestAlgorithm": "sha256",
"externalBin": [], "wix": {
"longDescription": "", "language": ["en-US"],
"resources": ["png/weread_32.ico"], "template": "assets/main.wxs"
"shortDescription": "",
"targets": ["msi"],
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": "",
"wix": {
"language": ["en-US"],
"template": "assets/main.wxs"
}
} }
} }
} }