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

View File

@@ -28,9 +28,6 @@ on:
description: '[Height, Optional]'
required: false
default: '780'
safe_domain:
description: '[Safe Domain, Optional]'
required: false
hide_title_bar:
description: '[Hide TitleBar, Optional, MacOS only]'
required: false
@@ -92,7 +89,7 @@ jobs:
if: inputs.platform == 'ubuntu-20.04'
uses: awalsh128/cache-apt-pkgs-action@latest
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
- name: Install pake-cli local
@@ -132,7 +129,6 @@ jobs:
RESIZE: ${{ inputs.resize }}
MULTI_ARCH: ${{ inputs.multi_arch }}
TARGETS: ${{ inputs.targets }}
SAFE_DOMAIN: ${{ inputs.safe_domain }}
- name: Upload archive
uses: actions/upload-artifact@v3

View File

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

View File

@@ -75,7 +75,7 @@ jobs:
if: matrix.os == 'ubuntu-latest'
uses: awalsh128/cache-apt-pkgs-action@latest
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
- name: Rust cache restore

View File

@@ -40,12 +40,11 @@ jobs:
if: matrix.os == 'ubuntu-latest'
uses: awalsh128/cache-apt-pkgs-action@latest
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
- name: Run unit & integration tests with nextest
run: cargo hack --feature-powerset --exclude-features cli-build nextest run
# - name: Run documentation tests with cargo test
# run: cargo hack --feature-powerset test --doc
run: cargo hack --feature-powerset --exclude-features cli-build nextest run --no-tests=pass
cargo-clippy:
name: Check codebase quality (cargo clippy)
@@ -67,7 +66,7 @@ jobs:
if: matrix.os == 'ubuntu-latest'
uses: awalsh128/cache-apt-pkgs-action@latest
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
- name: Run all-features code quality checks
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/
.next
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 && \
cp -R /usr/local/cargo/registry /cargo-cache/ && \
cp -R /usr/local/cargo/git /cargo-cache/
# 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
@@ -28,8 +27,8 @@ FROM rust:1.80-slim AS builder
RUN --mount=type=cache,target=/var/cache/apt \
--mount=type=cache,target=/usr/local/cargo/registry \
apt-get update && apt-get install -y --no-install-recommends \
libdbus-1-dev libsoup2.4-dev libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.0-dev build-essential curl wget libssl-dev \
libdbus-1-dev libsoup2.4-dev 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

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_x86_64.deb">Linux</a>
</td>
<td>Poe
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe.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/Poe_x86_64.deb">Linux</a>
<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>
</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/Poe.png width=600/></td>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Qwerty.png width=600/></td>
</tr>
<tr>
<td>YouTube Music
@@ -96,22 +96,6 @@
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ProgramMusic.jpg width=600/></td>
</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
<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>
@@ -154,7 +138,7 @@ In addition, double-click the title bar to switch to full-screen mode. For Mac u
## 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)!
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)?
## Command-Line Packaging
@@ -179,7 +163,7 @@ If you are new to the command line, you can compile packages online with _GitHub
## 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.

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_x86_64.deb">Linux</a>
</td>
<td>Poe
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe.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/Poe_x86_64.deb">Linux</a>
<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>
</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/Poe.png width=600/></td>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Qwerty.png width=600/></td>
</tr>
<tr>
<td>YouTube Music
@@ -95,22 +95,6 @@
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ProgramMusic.jpg width=600/></td>
</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
<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>
@@ -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) 方式。
2. **开发用户**:使用 「命令行一键打包」,对 Mac 比较友好Windows / Linux 需折腾下 [环境配置](https://tauri.app/v1/guides/getting-started/prerequisites)。
2. **开发用户**:使用 「命令行一键打包」,对 Mac 比较友好Windows / Linux 需折腾下 [环境配置](https://tauri.app/start/prerequisites/)。
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
# 安装依赖

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_x86_64.deb">Linux</a>
</td>
<td>Poe
<a href="https://github.com/tw93/Pake/releases/latest/download/Poe.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/Poe_x86_64.deb">Linux</a>
<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>
</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/Poe.png width=600/></td>
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/Qwerty.png width=600/></td>
</tr>
<tr>
<td>YouTube Music
@@ -96,22 +96,6 @@
<td><img src=https://raw.githubusercontent.com/tw93/static/main/pake/ProgramMusic.jpg width=600/></td>
</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
<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>
@@ -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)で助けを求めることもできます!
2. **開発者の方へ**: 「コマンドラインパッケージング」を使用してください。macOS では完全にサポートされています。Windows/Linux ユーザーは、[環境を設定](https://tauri.app/v1/guides/getting-started/prerequisites)する必要があります。
2. **開発者の方へ**: 「コマンドラインパッケージング」を使用してください。macOS では完全にサポートされています。Windows/Linux ユーザーは、[環境を設定](https://tauri.app/start/prerequisites/)する必要があります。
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
```
## 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:
1. Microsoft Visual C++ 2015-2022 Redistributable (x64)
@@ -24,8 +25,8 @@ npm install pake-cli -g
```bash
sudo apt install libdbus-1-dev \
libsoup2.4-dev \
libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.0-dev \
libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.1-dev \
build-essential \
curl \
wget \
@@ -37,29 +38,9 @@ npm install pake-cli -g
gnome-video-effects-extra
```
## Usage
</details>
### 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
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
## CLI Usage
```bash
pake [url] [options]
@@ -221,7 +202,7 @@ Specify the system tray icon. This is only effective when the system tray is ena
#### [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
--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
```
#### [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.
PS: Secure domains do not need to carry protocols.
If you need to proxy requests for some reason, you can set the proxy address using the `proxy-url` option.
```shell
--safe-domain weread.qq.com,google.com
--proxy-url <url>
```
#### [debug]
@@ -261,10 +240,30 @@ The typed package has dev-tools for debugging, in addition to outputting more lo
--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.
## 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
```shell

69
bin/README_CN.md vendored
View File

@@ -8,9 +8,10 @@
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 或更高)`,此外还需要安装以下组件:
1. Microsoft Visual C++ 2015-2022 Redistributable (x64)
@@ -24,8 +25,8 @@ npm install pake-cli -g
```bash
sudo apt install libdbus-1-dev \
libsoup2.4-dev \
libjavascriptcoregtk-4.0-dev \
libwebkit2gtk-4.0-dev \
libjavascriptcoregtk-4.1-dev \
libwebkit2gtk-4.1-dev \
build-essential \
curl \
wget \
@@ -37,29 +38,9 @@ npm install pake-cli -g
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
pake [url] [options]
@@ -222,7 +203,7 @@ Linux默认为 `all`。
#### [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
--installer-language <language>
@@ -250,16 +231,12 @@ Linux默认为 `all`。
--inject ./tools/style.css --inject ./tools/hotkey.js
```
#### [safe-domain]
#### [proxy-url]
这个安全域名是除你当前配置的 `url` 之外可能会出现重定向或跳转到的其他域名,只有在已配置为安全的域名中,
才能够使用 `tauri` 暴露到浏览器的 `api` ,保证 `pake` 内置增强功能的正确运行。
PS: 安全域名不需要携带协议。
假如你由于某些缘故需要代理请求,你可以通过 `proxy-url` 选项来设置代理地址。
```shell
--safe-domain weread.qq.com,google.com
--proxy-url <url>
```
#### [debug]
@@ -270,11 +247,31 @@ PS: 安全域名不需要携带协议。
--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
# 在Linux上您可以通过 Docker 运行 Pake CLI。

View File

@@ -28,7 +28,7 @@ export default abstract class BaseBuilder {
if (!IS_MAC && !tauriTargetPathExists) {
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()) {

View File

@@ -10,7 +10,7 @@ export default class LinuxBuilder extends BaseBuilder {
getFileName(): string {
const { name } = this.options;
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.

View File

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

View File

@@ -11,7 +11,7 @@ export default class WinBuilder extends BaseBuilder {
getFileName(): string {
const { name } = this.options;
const { arch } = process;
const language = tauriConfig.tauri.bundle.windows.wix.language[0];
return `${name}_${tauriConfig.package.version}_${arch}_${language}`;
const language = tauriConfig.bundle.windows.wix.language[0];
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('--hide-title-bar', 'Only for Mac, hide title bar', DEFAULT.hideTitleBar)
.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 [injects...]', 'Injection of .js or .css Files', DEFAULT.inject)
.option('--inject <url>', '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('--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('--targets <string>', 'Only for Linux, option "deb" or "appimage"').default(DEFAULT.targets).hideHelp(),
@@ -44,11 +45,6 @@ program
.default(DEFAULT.disabledWebShortcuts)
.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('--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',
useLocalFile: false,
systemTrayIcon: '',
proxyUrl: "",
debug: false,
inject: [],
safeDomain: [],
installerLanguage: 'en-US',
};
@@ -28,6 +28,5 @@ export const DEFAULT_DEV_PAKE_OPTIONS: PakeCliOptions & { url: string } = {
...DEFAULT_PAKE_OPTIONS,
url: 'https://weread.qq.com',
name: 'WeRead',
safeDomain: ['weread.qq.com'],
hideTitleBar: true,
};

67
bin/helpers/merge.ts vendored
View File

@@ -25,7 +25,7 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
name,
resizable = true,
inject,
safeDomain,
proxyUrl,
installerLanguage,
} = options;
@@ -45,10 +45,11 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
};
Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
tauriConf.package.productName = name;
tauriConf.tauri.bundle.identifier = identifier;
if (platform == "win32") {
tauriConf.tauri.bundle.windows.wix.language[0] = installerLanguage;
tauriConf.productName = name;
tauriConf.identifier = identifier;
if (platform == 'win32') {
tauriConf.bundle.windows.wix.language[0] = installerLanguage;
}
//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.
// const filesToCopyBack = ['cli.js', 'about_pake.html'];
const filesToCopyBack = ['cli.js'];
await Promise.all(
filesToCopyBack.map(file => fsExtra.copy(path.join(distBakDir, file), path.join(distDir, file))),
);
await Promise.all(filesToCopyBack.map(file => fsExtra.copy(path.join(distBakDir, file), path.join(distDir, file))));
}
tauriConf.pake.windows[0].url = fileName;
tauriConf.pake.windows[0].url_type = 'local';
} else {
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 = {
@@ -118,10 +98,10 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
// Processing targets are currently only open to Linux.
if (platform === 'linux') {
delete tauriConf.tauri.bundle.deb.files;
const validTargets = ['all', 'deb', 'appimage'];
delete tauriConf.bundle.linux.deb.files;
const validTargets = ['all', 'deb', 'appimage', 'rpm'];
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 {
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) {
updateIconPath = false;
logger.warn(`${iconInfo.message}, but you give ${customIconExt}`);
tauriConf.tauri.bundle.icon = [iconInfo.defaultIcon];
tauriConf.bundle.icon = [iconInfo.defaultIcon];
} else {
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);
}
if (updateIconPath) {
tauriConf.tauri.bundle.icon = [options.icon];
tauriConf.bundle.icon = [options.icon];
} else {
logger.warn(`✼ Icon will remain as default.`);
}
} else {
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.
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) {
try {
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`);
// inject js or css files
if (inject?.length > 0) {
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 = [];
await fsExtra.writeFile(injectFilePath, '');
}
tauriConf.pake.proxy_url = proxyUrl || '';
// Save config file.
const platformConfigPaths: PlatformMap = {
@@ -217,18 +203,21 @@ export async function mergeConfig(url: string, options: PakeAppOptions, tauriCon
darwin: 'tauri.macos.conf.json',
linux: 'tauri.linux.conf.json',
};
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 });
const pakeConfigPath = path.join(tauriConfigDirectory, 'pake.json');
await fsExtra.outputJSON(pakeConfigPath, tauriConf.pake, { spaces: 4 });
let tauriConf2 = JSON.parse(JSON.stringify(tauriConf));
delete tauriConf2.pake;
delete tauriConf2.tauri.bundle;
// delete tauriConf2.bundle;
if (process.env.NODE_ENV === 'development') {
tauriConf2.tauri.bundle = bundleConf.tauri.bundle;
tauriConf2.bundle = bundleConf.bundle;
}
const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json');
await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 });

View File

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

7
bin/types.ts vendored
View File

@@ -27,7 +27,6 @@ export interface PakeCliOptions {
// Enable windows always on top, default false
alwaysOnTop: boolean;
// Force Mac to use dark mode, default false
darkMode: boolean;
@@ -58,11 +57,11 @@ export interface PakeCliOptions {
// Debug mode, outputs more logs
debug: boolean;
/** 需要注入页面的外部脚本 */
/** External scripts that need to be injected into the page. */
inject: string[];
/* the domain that can use ipc or tauri javascript sdk */
safeDomain: string[];
// Set Api Proxy
proxyUrl: string;
// Installer language, valid for Windows users, default is en-US
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';
// 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 { dir } from 'tmp-promise';
import { fileTypeFromBuffer } from 'file-type';
import psl from 'psl';
import * as psl from 'psl';
import isUrl from 'is-url';
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 engines = {
node: ">=16.0.0"
@@ -68,8 +68,8 @@ var exports = "./dist/pake.js";
var license = "MIT";
var dependencies = {
"@tauri-apps/api": "^1.6.0",
"@tauri-apps/cli": "^1.6.1",
axios: "^1.7.7",
"@tauri-apps/cli": "^2.1.0",
axios: "^1.7.9",
chalk: "^5.3.0",
commander: "^11.1.0",
"file-type": "^18.7.0",
@@ -78,20 +78,20 @@ var dependencies = {
loglevel: "^1.9.2",
ora: "^7.0.1",
prompts: "^2.4.2",
psl: "^1.9.0",
psl: "^1.15.0",
shelljs: "^0.8.5",
"tmp-promise": "^3.0.3",
"update-notifier": "^7.3.1"
};
var devDependencies = {
"@rollup/plugin-alias": "^5.1.0",
"@rollup/plugin-alias": "^5.1.1",
"@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-replace": "^5.0.7",
"@rollup/plugin-terser": "^0.4.4",
"@types/fs-extra": "^11.0.4",
"@types/is-url": "^1.2.32",
"@types/node": "^20.16.5",
"@types/node": "^20.17.10",
"@types/page-icon": "^0.3.6",
"@types/prompts": "^2.4.9",
"@types/psl": "^1.1.3",
@@ -100,14 +100,14 @@ var devDependencies = {
"@types/update-notifier": "^6.0.8",
"app-root-path": "^3.1.0",
"cross-env": "^7.0.3",
rollup: "^4.21.3",
rollup: "^4.28.1",
"rollup-plugin-typescript2": "^0.36.0",
tslib: "^2.7.0",
typescript: "^5.6.2"
tslib: "^2.8.1",
typescript: "^5.7.2"
};
var packageJson = {
name: name,
version: version,
version: version$1,
description: description,
engines: engines,
bin: bin,
@@ -132,8 +132,8 @@ var windows = [
width: 1200,
height: 780,
resizable: true,
dark_mode: false,
always_on_top: false,
dark_mode: false,
activation_shortcut: "",
disabled_web_shortcuts: false
}
@@ -148,139 +148,89 @@ var system_tray = {
linux: true,
windows: true
};
var system_tray_path = "icons/icon.png";
var inject = [
];
var proxy_url = "";
var pakeConf = {
windows: windows,
user_agent: user_agent,
system_tray: system_tray,
inject: inject
system_tray_path: system_tray_path,
inject: inject,
proxy_url: proxy_url
};
var tauri$3 = {
security: {
csp: null,
dangerousRemoteDomainIpcAccess: [
{
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/*"
]
}
var productName$1 = "WeRead";
var identifier = "com.pake.weread";
var version = "1.0.0";
var app = {
withGlobalTauri: true,
trayIcon: {
iconPath: "png/weread_512.png",
iconAsTemplate: false,
id: "pake-tray"
}
};
var build = {
withGlobalTauri: true,
devPath: "../dist",
distDir: "../dist",
beforeBuildCommand: "",
beforeDevCommand: ""
frontendDist: "../dist"
};
var CommonConf = {
"package": {
productName: "WeRead",
version: "1.0.0"
},
tauri: tauri$3,
productName: productName$1,
identifier: identifier,
version: version,
app: app,
build: build
};
var tauri$2 = {
bundle: {
icon: [
"png/weread_256.ico",
"png/weread_32.ico"
],
identifier: "com.pake.weread",
active: true,
category: "DeveloperTool",
copyright: "",
externalBin: [
],
longDescription: "",
resources: [
"png/weread_32.ico"
],
shortDescription: "",
targets: [
"msi"
],
windows: {
certificateThumbprint: null,
digestAlgorithm: "sha256",
timestampUrl: "",
wix: {
language: [
"en-US"
],
template: "assets/main.wxs"
}
var bundle$2 = {
icon: [
"png/weread_256.ico",
"png/weread_32.ico"
],
active: true,
resources: [
"png/weread_32.ico"
],
targets: [
"msi"
],
windows: {
digestAlgorithm: "sha256",
wix: {
language: [
"en-US"
],
template: "assets/main.wxs"
}
}
};
var WinConf = {
tauri: tauri$2
bundle: bundle$2
};
var tauri$1 = {
bundle: {
icon: [
"icons/weread.icns"
],
identifier: "com.pake.weread",
active: true,
category: "DeveloperTool",
copyright: "",
externalBin: [
],
longDescription: "",
macOS: {
entitlements: null,
exceptionDomain: "",
frameworks: [
],
providerShortName: null,
signingIdentity: null
},
resources: [
],
shortDescription: "",
targets: [
"dmg"
]
}
var bundle$1 = {
icon: [
"icons/weread.icns"
],
active: true,
macOS: {
},
targets: [
"dmg"
]
};
var MacConf = {
tauri: tauri$1
bundle: bundle$1
};
var tauri = {
bundle: {
icon: [
"png/weread_512.png"
],
identifier: "com.pake.weread",
active: true,
category: "DeveloperTool",
copyright: "",
var productName = "we-read";
var bundle = {
icon: [
"png/weread_512.png"
],
active: true,
linux: {
deb: {
depends: [
"curl",
@@ -289,21 +239,16 @@ var tauri = {
files: {
"/usr/share/applications/com-pake-weread.desktop": "assets/com-pake-weread.desktop"
}
},
externalBin: [
],
longDescription: "",
resources: [
],
shortDescription: "",
targets: [
"deb",
"appimage"
]
}
}
},
targets: [
"deb",
"appimage"
]
};
var LinuxConf = {
tauri: tauri
productName: productName,
bundle: bundle
};
const platformConfigs = {
@@ -315,11 +260,15 @@ const { platform: platform$2 } = process;
// @ts-ignore
const platformConfig = platformConfigs[platform$2];
let tauriConfig = {
tauri: {
...CommonConf.tauri,
bundle: platformConfig.tauri.bundle,
...CommonConf,
bundle: platformConfig.bundle,
app: {
...CommonConf.app,
trayIcon: {
...CommonConf.app.trayIcon,
...(platformConfig?.app?.trayIcon ?? {}),
},
},
package: CommonConf.package,
build: CommonConf.build,
pake: pakeConf,
};
@@ -477,7 +426,7 @@ async function combineFiles(files, output) {
}
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;
// Set Windows parameters.
const tauriConfWindowOptions = {
@@ -492,10 +441,10 @@ async function mergeConfig(url, options, tauriConf) {
disabled_web_shortcuts: disabledWebShortcuts,
};
Object.assign(tauriConf.pake.windows[0], { url, ...tauriConfWindowOptions });
tauriConf.package.productName = name;
tauriConf.tauri.bundle.identifier = identifier;
if (platform == "win32") {
tauriConf.tauri.bundle.windows.wix.language[0] = installerLanguage;
tauriConf.productName = name;
tauriConf.identifier = identifier;
if (platform == 'win32') {
tauriConf.bundle.windows.wix.language[0] = installerLanguage;
}
//Judge the type of URL, whether it is a file or a website.
const pathExists = await fsExtra.pathExists(url);
@@ -523,24 +472,6 @@ async function mergeConfig(url, options, tauriConf) {
}
else {
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 = {
win32: 'windows',
@@ -554,10 +485,10 @@ async function mergeConfig(url, options, tauriConf) {
tauriConf.pake.system_tray[currentPlatform] = showSystemTray;
// Processing targets are currently only open to Linux.
if (platform === 'linux') {
delete tauriConf.tauri.bundle.deb.files;
const validTargets = ['all', 'deb', 'appimage'];
delete tauriConf.bundle.linux.deb.files;
const validTargets = ['all', 'deb', 'appimage', 'rpm'];
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 {
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) {
updateIconPath = false;
logger.warn(`${iconInfo.message}, but you give ${customIconExt}`);
tauriConf.tauri.bundle.icon = [iconInfo.defaultIcon];
tauriConf.bundle.icon = [iconInfo.defaultIcon];
}
else {
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);
}
if (updateIconPath) {
tauriConf.tauri.bundle.icon = [options.icon];
tauriConf.bundle.icon = [options.icon];
}
else {
logger.warn(`✼ Icon will remain as default.`);
@@ -608,10 +539,10 @@ async function mergeConfig(url, options, tauriConf) {
}
else {
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.
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) {
try {
await fsExtra.pathExists(systemTrayIcon);
@@ -632,7 +563,9 @@ async function mergeConfig(url, options, tauriConf) {
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`);
// inject js or css files
if (inject?.length > 0) {
@@ -648,6 +581,7 @@ async function mergeConfig(url, options, tauriConf) {
tauriConf.pake.inject = [];
await fsExtra.writeFile(injectFilePath, '');
}
tauriConf.pake.proxy_url = proxyUrl || '';
// Save config file.
const platformConfigPaths = {
win32: 'tauri.windows.conf.json',
@@ -655,13 +589,13 @@ async function mergeConfig(url, options, tauriConf) {
linux: 'tauri.linux.conf.json',
};
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 });
const pakeConfigPath = path.join(tauriConfigDirectory, 'pake.json');
await fsExtra.outputJSON(pakeConfigPath, tauriConf.pake, { spaces: 4 });
let tauriConf2 = JSON.parse(JSON.stringify(tauriConf));
delete tauriConf2.pake;
delete tauriConf2.tauri.bundle;
const configJsonPath = path.join(tauriConfigDirectory, 'tauri.conf.json');
await fsExtra.outputJSON(configJsonPath, tauriConf2, { spaces: 4 });
}
@@ -676,7 +610,7 @@ class BaseBuilder {
const tauriTargetPathExists = await fsExtra.pathExists(tauriTargetPath);
if (!IS_MAC && !tauriTargetPathExists) {
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()) {
const res = await prompts({
@@ -764,7 +698,7 @@ class MacBuilder extends BaseBuilder {
else {
arch = process.arch === 'arm64' ? 'aarch64' : process.arch;
}
return `${name}_${tauriConfig.package.version}_${arch}`;
return `${name}_${tauriConfig.version}_${arch}`;
}
getBuildCommand() {
return this.options.multiArch ? 'npm run build:mac' : super.getBuildCommand();
@@ -784,8 +718,8 @@ class WinBuilder extends BaseBuilder {
getFileName() {
const { name } = this.options;
const { arch } = process;
const language = tauriConfig.tauri.bundle.windows.wix.language[0];
return `${name}_${tauriConfig.package.version}_${arch}_${language}`;
const language = tauriConfig.bundle.windows.wix.language[0];
return `${name}_${tauriConfig.version}_${arch}_${language}`;
}
}
@@ -796,7 +730,7 @@ class LinuxBuilder extends BaseBuilder {
getFileName() {
const { name } = this.options;
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.
async build(url) {
@@ -848,9 +782,9 @@ const DEFAULT_PAKE_OPTIONS = {
targets: 'deb',
useLocalFile: false,
systemTrayIcon: '',
proxyUrl: "",
debug: false,
inject: [],
safeDomain: [],
installerLanguage: 'en-US',
};
@@ -1034,9 +968,10 @@ program
.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('--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 [injects...]', 'Injection of .js or .css Files', DEFAULT_PAKE_OPTIONS.inject)
.option('--inject <url>', '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('--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('--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())
@@ -1044,9 +979,6 @@ program
.addOption(new Option('--disabled-web-shortcuts', 'Disabled webPage shortcuts')
.default(DEFAULT_PAKE_OPTIONS.disabledWebShortcuts)
.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('--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())

View File

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

15
script/app_config.mjs vendored
View File

@@ -127,10 +127,7 @@ function updatePakeJson() {
}
function updateTauriJson() {
const url = new URL(variables.url);
tauriJson.tauri.security.dangerousRemoteDomainIpcAccess[0].domain = url.hostname;
tauriJson.package.productName = variables.title;
tauriJson.productName = variables.title;
writeFileSync('src-tauri/tauri.conf.json', JSON.stringify(tauriJson, null, 2));
}
@@ -142,8 +139,8 @@ function updateIconFile(iconPath, defaultIconPath) {
}
function updatePlatformConfig(platformConfig, platformVariables) {
platformConfig.tauri.bundle['icon'] = platformVariables.icon;
platformConfig.tauri.bundle['identifier'] = variables.identifier;
platformConfig.bundle['icon'] = platformVariables.icon;
platformConfig.identifier = variables.identifier;
}
function save() {
@@ -159,11 +156,11 @@ function save() {
}
function updateDesktopEntry() {
linuxJson.tauri.bundle.deb.files = {};
linuxJson.tauri.bundle.deb.files[variables.linux.desktopEntryConfig.configKey] = variables.linux.desktopEntryConfig.configValue;
linuxJson.bundle.linux.deb.files = {};
linuxJson.bundle.linux.deb.files[variables.linux.desktopEntryConfig.configKey] = variables.linux.desktopEntryConfig.configValue;
writeFileSync(variables.linux.desktopEntryPath, variables.linux.desktopEntry);
}
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('is multi arch? only for Mac: ', process.env.MULTI_ARCH);
console.log('targets type? only for Linux: ', process.env.TARGETS);
console.log('safe-domain: ', process.env.SAFE_DOMAIN);
console.log('===========================\n');
cd('node_modules/pake-cli');
@@ -40,10 +39,6 @@ if (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') {
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]
name = "app"
version = "0.1.0"
name = "pake"
version = "3.0.0"
description = "🤱🏻 Turn any webpage into a desktop app with Rust."
authors = ["Tw93"]
license = "MIT"
repository = "https://github.com/tw93/Pake"
default-run = "app"
edition = "2021"
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
[build-dependencies]
tauri-build = { version = "1.5.2", features = [] }
tauri-build = { version = "2.0.3", features = [] }
[dependencies]
serde_json = "1.0.117"
serde = { version = "1.0.202", features = ["derive"] }
tauri = { version = "1.6.6", features = ["api-all", "system-tray"] }
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
tauri-plugin-oauth = { git = "https://github.com/FabianLars/tauri-plugin-oauth", branch = "main" }
serde_json = "1.0.133"
serde = { version = "1.0.215", features = ["derive"] }
tauri = { version = "2.1.1", features = ["tray-icon", "image-ico", "image-png", "macos-proxy"] }
tauri-plugin-window-state = "2.2.0"
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"] }
[dev-dependencies]
cargo-bloat = "0.11.1"
[features]
# this feature is used for development builds from development cli
cli-build = []

View File

@@ -4,6 +4,9 @@
<?elseif $(sys.BUILDARCH)="x64"?>
<?define Win64 = "yes" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?elseif $(sys.BUILDARCH)="arm64"?>
<?define Win64 = "yes" ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?else?>
<?error Unsupported value of sys.BUILDARCH=$(sys.BUILDARCH)?>
<?endif?>
@@ -11,11 +14,11 @@
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Product
Id="*"
Name="{{{product_name}}}"
UpgradeCode="{{{upgrade_code}}}"
Name="{{product_name}}"
UpgradeCode="{{upgrade_code}}"
Language="!(loc.TauriLanguage)"
Manufacturer="{{{manufacturer}}}"
Version="{{{version}}}">
Manufacturer="{{manufacturer}}"
Version="{{version}}">
<Package Id="*"
Keywords="Installer"
@@ -29,6 +32,11 @@
<!-- reinstall all files; rewrite all registry entries; reinstall all shortcuts -->
<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}}
<MajorUpgrade Schedule="afterInstallInitialize" AllowDowngrades="yes" />
{{else}}
@@ -42,29 +50,35 @@
<Media Id="1" Cabinet="app.cab" EmbedCab="yes" />
{{#if banner_path}}
<WixVariable Id="WixUIBannerBmp" Value="{{{banner_path}}}" />
<WixVariable Id="WixUIBannerBmp" Value="{{banner_path}}" />
{{/if}}
{{#if dialog_image_path}}
<WixVariable Id="WixUIDialogBmp" Value="{{{dialog_image_path}}}" />
<WixVariable Id="WixUIDialogBmp" Value="{{dialog_image_path}}" />
{{/if}}
{{#if license}}
<WixVariable Id="WixUILicenseRtf" Value="{{{license}}}" />
<WixVariable Id="WixUILicenseRtf" Value="{{license}}" />
{{/if}}
<Icon Id="ProductIcon" SourceFile="{{{icon_path}}}"/>
<Icon Id="ProductIcon" SourceFile="{{icon_path}}"/>
<Property Id="ARPPRODUCTICON" Value="ProductIcon" />
<Property Id="ARPNOREPAIR" Value="yes" Secure="yes" /> <!-- Remove repair -->
<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 -->
<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>
<!-- launch app checkbox -->
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="!(loc.LaunchApp)" />
<Property Id="WixShellExecTarget" Value="[!Path]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1"/>
<CustomAction Id="LaunchApplication" Impersonate="yes" FileKey="Path" ExeCommand="[LAUNCHAPPARGS]" Return="asyncNoWait" />
<UI>
<!-- launch app checkbox -->
@@ -92,27 +106,49 @@
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="DesktopFolder" Name="Desktop">
<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" />
<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>
</Directory>
<Directory Id="$(var.PlatformProgramFilesFolder)" Name="PFiles">
<Directory Id="INSTALLDIR" Name="{{{product_name}}}"/>
<Directory Id="INSTALLDIR" Name="{{product_name}}"/>
</Directory>
<Directory Id="ProgramMenuFolder">
<Directory Id="ApplicationProgramsFolder" Name="{{{product_name}}}"/>
<Directory Id="ApplicationProgramsFolder" Name="{{product_name}}"/>
</Directory>
</Directory>
<DirectoryRef Id="INSTALLDIR">
<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" />
</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 Id="Path" Guid="{{{path_component_guid}}}" Win64="$(var.Win64)">
<File Id="Path" Source="{{{app_exe_source}}}" KeyPath="yes" Checksum="yes"/>
<Component Id="Path" Guid="{{path_component_guid}}" Win64="$(var.Win64)">
<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>
{{#each binaries as |bin| ~}}
<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"/>
</Component>
{{/if}}
{{{resources}}}
{{resources}}
<Component Id="CMP_UninstallShortcut" Guid="*">
<Shortcut Id="UninstallShortcut"
Name="Uninstall {{{product_name}}}"
Description="Uninstalls {{{product_name}}}"
Name="Uninstall {{product_name}}"
Description="Uninstalls {{product_name}}"
Target="[System64Folder]msiexec.exe"
Arguments="/x [ProductCode]" />
@@ -143,7 +179,7 @@
On="uninstall" />
<RegistryValue Root="HKCU"
Key="Software\\{{{manufacturer}}}\\{{{product_name}}}"
Key="Software\\{{manufacturer}}\\{{product_name}}"
Name="Uninstaller Shortcut"
Type="integer"
Value="1"
@@ -154,15 +190,15 @@
<DirectoryRef Id="ApplicationProgramsFolder">
<Component Id="ApplicationShortcut" Guid="*">
<Shortcut Id="ApplicationStartMenuShortcut"
Name="{{{product_name}}}"
Description="Runs {{{product_name}}}"
Name="{{product_name}}"
Description="Runs {{product_name}}"
Target="[!Path]"
Icon="ProductIcon"
WorkingDirectory="INSTALLDIR">
<ShortcutProperty Key="System.AppUserModel.ID" Value="{{{bundle_id}}}"/>
<ShortcutProperty Key="System.AppUserModel.ID" Value="{{bundle_id}}"/>
</Shortcut>
<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>
</DirectoryRef>
@@ -246,7 +282,7 @@
</Property>
{{#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>
<Custom Action='DownloadAndInvokeBootstrapper' Before='InstallFinalize'>
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
@@ -256,8 +292,8 @@
<!-- Embedded webview bootstrapper mode -->
{{#if 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' />
<Binary Id="MicrosoftEdgeWebview2Setup.exe" SourceFile="{{webview2_bootstrapper_path}}"/>
<CustomAction Id='InvokeBootstrapper' BinaryKey='MicrosoftEdgeWebview2Setup.exe' Execute="deferred" ExeCommand='{{webview_installer_args}} /install' Return='check' />
<InstallExecuteSequence>
<Custom Action='InvokeBootstrapper' Before='InstallFinalize'>
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
@@ -267,8 +303,8 @@
<!-- Embedded offline installer -->
{{#if 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' />
<Binary Id="MicrosoftEdgeWebView2RuntimeInstaller.exe" SourceFile="{{webview2_installer_path}}"/>
<CustomAction Id='InvokeStandalone' BinaryKey='MicrosoftEdgeWebView2RuntimeInstaller.exe' Execute="deferred" ExeCommand='{{webview_installer_args}} /install' Return='check' />
<InstallExecuteSequence>
<Custom Action='InvokeStandalone' Before='InstallFinalize'>
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
@@ -305,6 +341,10 @@
</InstallExecuteSequence>
{{/if}}
<InstallExecuteSequence>
<Custom Action="LaunchApplication" After="InstallFinalize">AUTOLAUNCHAPP AND NOT Installed</Custom>
</InstallExecuteSequence>
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize"/>
</Product>
</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,
"height": 780,
"resizable": true,
"dark_mode": false,
"always_on_top": false,
"dark_mode": false,
"activation_shortcut": "",
"disabled_web_shortcuts": false
}
@@ -24,5 +24,7 @@
"linux": 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 user_agent: UserAgent,
pub system_tray: FunctionON,
pub system_tray_path: String,
pub proxy_url: String,
}
impl PakeConfig {

View File

@@ -1,8 +1,10 @@
use crate::util::{check_file_or_append, get_download_message, show_toast, MessageType};
use std::fs::{self, File};
use std::io::Write;
use tauri::api::http::{ClientBuilder, HttpRequestBuilder, ResponseType};
use tauri::{api, command, AppHandle, Manager, Window};
use std::str::FromStr;
use tauri::http::Method;
use tauri::{command, AppHandle, Manager, Url, WebviewWindow};
use tauri_plugin_http::reqwest::{ClientBuilder, Request};
#[derive(serde::Deserialize)]
pub struct DownloadFileParams {
@@ -18,24 +20,23 @@ pub struct BinaryDownloadParams {
#[command]
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));
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 client = ClientBuilder::new().build().unwrap();
let response = client
.send(
HttpRequestBuilder::new("GET", &params.url)
.unwrap()
.response_type(ResponseType::Binary),
)
.execute(Request::new(
Method::GET,
Url::from_str(&params.url).unwrap(),
))
.await;
match response {
Ok(res) => {
let bytes = res.bytes().await.unwrap().data;
let bytes = res.bytes().await.unwrap();
let mut file = File::create(file_path).unwrap();
file.write_all(&bytes).unwrap();
@@ -54,9 +55,9 @@ pub async fn download_file_by_binary(
app: AppHandle,
params: BinaryDownloadParams,
) -> 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));
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 download_file_result = fs::write(file_path, &params.binary);
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};
pub fn get_system_tray() -> SystemTray {
let hide_app = CustomMenuItem::new("hide_app".to_string(), "Hide");
let show_app = CustomMenuItem::new("show_app".to_string(), "Show");
let quit = CustomMenuItem::new("quit".to_string(), "Quit");
let tray_menu = SystemTrayMenu::new()
.add_item(show_app)
.add_item(hide_app)
.add_item(quit);
SystemTray::new().with_menu(tray_menu)
}
pub fn system_tray_handle(app: &tauri::AppHandle, event: SystemTrayEvent) {
if let SystemTrayEvent::MenuItemClick { tray_id: _, id, .. } = event {
match id.as_str() {
pub fn set_system_tray(app: &AppHandle) -> tauri::Result<()> {
let hide_app = MenuItemBuilder::with_id("hide_app", "Hide").build(app)?;
let show_app = MenuItemBuilder::with_id("show_app", "Show").build(app)?;
let quit = MenuItemBuilder::with_id("quit", "Quit").build(app)?;
let menu = MenuBuilder::new(app)
.items(&[&hide_app, &show_app, &quit])
.build()?;
app.app_handle().remove_tray_by_id("pake-tray");
let tray = TrayIconBuilder::new()
.menu(&menu)
.on_menu_event(move |app, event| match event.id().as_ref() {
"hide_app" => {
app.get_window("pake").unwrap().minimize().unwrap();
app.get_webview_window("pake").unwrap().minimize().unwrap();
}
"show_app" => {
app.get_window("pake").unwrap().show().unwrap();
app.get_webview_window("pake").unwrap().show().unwrap();
}
"quit" => {
let _res = app.save_window_state(StateFlags::all());
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 std::path::PathBuf;
use tauri::{App, Window, WindowBuilder, WindowUrl};
use std::{path::PathBuf, str::FromStr};
use tauri::{App, Url, WebviewUrl, WebviewWindow, WebviewWindowBuilder};
#[cfg(target_os = "macos")]
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
.windows
.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 url = match window_config.url_type.as_str() {
"web" => WindowUrl::App(window_config.url.parse().unwrap()),
"local" => WindowUrl::App(PathBuf::from(&window_config.url)),
"web" => WebviewUrl::App(window_config.url.parse().unwrap()),
"local" => WebviewUrl::App(PathBuf::from(&window_config.url)),
_ => 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()
);
let mut window_builder = WindowBuilder::new(app, "pake", url)
let mut window_builder = WebviewWindowBuilder::new(app, "pake", url)
.title("")
.visible(false)
.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)
.inner_size(window_config.width, window_config.height)
.always_on_top(window_config.always_on_top)
.disable_drag_drop_handler()
.initialization_script(&config_script)
.initialization_script(include_str!("../inject/component.js"))
.initialization_script(include_str!("../inject/event.js"))
.initialization_script(include_str!("../inject/style.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")]
{
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 {
TitleBarStyle::Visible
};
window_builder = window_builder.title_bar_style(title_bar_style);
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
.data_directory(_data_dir)
.title(app.package_info().name.clone())
.title(app.package_info().name.clone());
}
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',
'ogg', 'ogv', 'pdf', 'png', 'ppt', 'pptx', 'psd', 'rar', 'raw',
'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');
return downloadLinkPattern.test(url);
}
// No need to go to the download link.
function externalDownLoadLink() {
return ['quickref.me'].indexOf(location.hostname) > -1;
}
document.addEventListener('DOMContentLoaded', () => {
const tauri = window.__TAURI__;
const appWindow = tauri.window.appWindow;
const invoke = tauri.tauri.invoke;
const appWindow = tauri.window.getCurrentWindow();
const invoke = tauri.core.invoke;
if (!document.getElementById('pake-top-dom')) {
const topDom = document.createElement('div');
@@ -71,19 +65,19 @@ document.addEventListener('DOMContentLoaded', () => {
const domEl = document.getElementById('pake-top-dom');
domEl.addEventListener('touchstart', () => {
appWindow.startDragging().then();
appWindow.startDragging();
});
domEl.addEventListener('mousedown', e => {
e.preventDefault();
if (e.buttons === 1 && e.detail !== 2) {
appWindow.startDragging().then();
appWindow.startDragging();
}
});
domEl.addEventListener('dblclick', () => {
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 handleExternalLink = (e, url) => {
e.preventDefault();
tauri.shell.open(url);
};
const handleDownloadLink = (e, url, filename) => {
e.preventDefault();
invoke('download_file', { params: { url, filename } });
const handleExternalLink = url => {
invoke('plugin:shell|open', {
path: url,
});
};
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 absoluteUrl = hrefUrl.href;
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.
if (isDownloadRequired(absoluteUrl, anchorElement, e) && !externalDownLoadLink() && !isSpecialDownload(absoluteUrl)) {
handleDownloadLink(e, absoluteUrl, filename);
if (isDownloadRequired(absoluteUrl, anchorElement, e) && !isSpecialDownload(absoluteUrl)) {
e.preventDefault();
invoke('download_file', { params: { url: absoluteUrl, filename } });
}
}
};
@@ -231,7 +233,7 @@ document.addEventListener('DOMContentLoaded', () => {
} else {
const baseUrl = window.location.origin + window.location.pathname;
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.
return originalWindowOpen.call(window, url, name, specs);

View File

@@ -119,7 +119,8 @@ window.addEventListener('DOMContentLoaded', _event => {
display: none !important;
}
#react-root [data-testid="DMDrawer"] {
#react-root [data-testid="DMDrawer"],
#root > main > footer.justify-center.ease-in {
visibility: hidden !important;
}
@@ -333,6 +334,14 @@ window.addEventListener('DOMContentLoaded', _event => {
#__next>div>div>.flex.h-screen.w-full.flex-col.items-center {
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{
padding-top: 0px;
@@ -378,6 +387,10 @@ window.addEventListener('DOMContentLoaded', _event => {
.lark > .main-wrapper [data-testid="aside"] {
top: 15px;
}
#global > div.header-container > .mask-paper {
padding-top: 20px;
}
#background.ytd-masthead {
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"
)]
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() {
run_app()
app_lib::run()
}

View File

@@ -1,7 +1,7 @@
use crate::app::config::PakeConfig;
use std::env;
use std::path::PathBuf;
use tauri::{api, Config, Window};
use tauri::{AppHandle, Config, Manager, WebviewWindow};
pub fn get_pake_config() -> (PakeConfig, Config) {
#[cfg(feature = "cli-build")]
@@ -23,10 +23,12 @@ pub fn get_pake_config() -> (PakeConfig, 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 data_dir = api::path::config_dir()
let package_name = _tauri_config.product_name.unwrap();
let data_dir = app
.path()
.config_dir()
.expect("Failed to get data dirname")
.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);
window.eval(&script).unwrap();
}

View File

@@ -1,39 +1,16 @@
{
"package": {
"productName": "WeRead",
"version": "1.0.0"
},
"tauri": {
"security": {
"csp": null,
"dangerousRemoteDomainIpcAccess": [
{
"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/*"]
}
"productName": "WeRead",
"identifier": "com.pake.weread",
"version": "1.0.0",
"app": {
"withGlobalTauri": true,
"trayIcon": {
"iconPath": "png/weread_512.png",
"iconAsTemplate": false,
"id": "pake-tray"
}
},
"build": {
"withGlobalTauri": true,
"devPath": "../dist",
"distDir": "../dist",
"beforeBuildCommand": "",
"beforeDevCommand": ""
"frontendDist": "../dist"
}
}

View File

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

View File

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

View File

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