@@ -10,7 +10,7 @@ trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
# Use 4 spaces for Python, Rust and Bash files
|
||||
[*.{py,rs,sh,md}]
|
||||
[*.{py,rs,sh}]
|
||||
indent_size = 4
|
||||
|
||||
# Makefiles always use tabs for indentation
|
||||
@@ -22,3 +22,6 @@ indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.ts]
|
||||
quote_type= "single"
|
||||
|
||||
21
.github/workflows/pake_build.yaml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
# Sequence of patterns matched against refs/tags
|
||||
tags:
|
||||
- "V*"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -48,7 +49,7 @@ jobs:
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf
|
||||
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libappindicator3-dev librsvg2-dev patchelf gnome-video-effects gnome-video-effects-extra
|
||||
|
||||
- name: build for Ubuntu
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
@@ -77,9 +78,15 @@ jobs:
|
||||
# files: |
|
||||
# output/*/*.*
|
||||
|
||||
- uses: ncipollo/release-action@v1
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
with:
|
||||
allowUpdates: true
|
||||
artifacts: "output/*/*.*"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# - uses: ncipollo/release-action@v1
|
||||
# if: startsWith(github.ref, 'refs/tags/v')
|
||||
# with:
|
||||
# allowUpdates: true
|
||||
# artifacts: "output/*/*.*"
|
||||
# token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload files
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
curl -L https://github.com/probonopd/uploadtool/raw/master/upload.sh --output upload.sh
|
||||
bash upload.sh output/*/*.*
|
||||
|
||||
9
.gitignore
vendored
@@ -9,13 +9,10 @@ lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist-ssr
|
||||
dist/cli.js
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
!.vscode/settings.json
|
||||
.vscode
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
@@ -25,6 +22,10 @@ dist/cli.js
|
||||
*.sw?
|
||||
.npmrc
|
||||
output
|
||||
*.msi
|
||||
*.deb
|
||||
*.AppImage
|
||||
*.dmg
|
||||
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
|
||||
4
.vscode/settings.json
vendored
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"cSpell.words": ["loglevel", "Pake", "tauri"],
|
||||
"typescript.preferences.importModuleSpecifierEnding": "js"
|
||||
}
|
||||
@@ -11,11 +11,11 @@ graph LR
|
||||
```
|
||||
|
||||
- `dev` branch
|
||||
- `dev` is the developing branch.
|
||||
- It's **RECOMMENDED** to commit feature PR to `dev`.
|
||||
- `dev` is the developing branch.
|
||||
- It's **RECOMMENDED** to commit feature PR to `dev`.
|
||||
- `master` branch
|
||||
- `master` is the release branch, we will make tag and publish version on this branch.
|
||||
- If it is a document modification, it can be submitted to this branch.
|
||||
- `master` is the release branch, we will make tag and publish version on this branch.
|
||||
- If it is a document modification, it can be submitted to this branch.
|
||||
|
||||
## Commit Log
|
||||
|
||||
|
||||
244
README.md
@@ -1,6 +1,7 @@
|
||||
<p align="left"><strong>中文</strong> | <a href="https://github.com/tw93/Pake/blob/master/README_EN.md">English</a></p>
|
||||
<p align="center">
|
||||
<img src=https://gw.alipayobjects.com/zos/k/fa/logo-modified.png width=138/>
|
||||
</p>
|
||||
<h1 align="center">Pake</h1>
|
||||
<div align="center">
|
||||
<a href="https://twitter.com/HiTw93" target="_blank">
|
||||
@@ -14,29 +15,28 @@
|
||||
<a href="https://github.com/tw93/Pake/issues?q=is%3Aissue+is%3Aclosed" target="_blank">
|
||||
<img alt="GitHub closed issues" src="https://img.shields.io/github/issues-closed/tw93/Pake.svg?style=flat-square"></a>
|
||||
</div>
|
||||
<div align="left">很简单的用 Rust 打包网页生成很小的桌面 App,支持 Mac / Windows / Linux 系统,常用包下载、<a href="#命令行打包">命令行一键打包</a>、<a href="#开发">定制开发</a> 可见下面文档,也欢迎去 <a href=https://github.com/tw93/Pake/discussions>讨论区</a> 交流。</div>
|
||||
</p>
|
||||
<div align="left">很简单的用 Rust 打包网页生成很小的桌面 App,支持 Mac / Windows / Linux 系统,常用包下载、<a href="#命令行一键打包">命令行一键打包</a>、<a href="#定制开发">定制开发</a> 可见下面文档,也欢迎去 <a href=https://github.com/tw93/Pake/discussions>讨论区</a> 交流。</div>
|
||||
|
||||
## 特征
|
||||
|
||||
🏂 **小**:相比传统的 Electron 套壳打包,要小将近 40 倍,不到 3M
|
||||
😂 **快**:Pake 的底层使用的 Rust Tauri 框架,性能体验较 JS 框架要轻快不少,内存小很多
|
||||
🩴 **特**:不是单纯打包,实现了快捷键的透传、沉浸式的窗口、拖动、样式改写、去广告、产品的极简风格定制
|
||||
🐶 **玩**:只是一个很简单的小玩具,用 Rust 替代之前套壳网页打包的老思路,其实 PWA 也很好
|
||||
🏂 **小**:相比传统的 Electron 套壳打包,要小将近 40 倍,不到 3M。
|
||||
😂 **快**:Pake 的底层使用的 Rust Tauri 框架,性能体验较 JS 框架要轻快不少,内存小很多。
|
||||
🩴 **特**:不是单纯打包,实现了快捷键的透传、沉浸式的窗口、拖动、样式改写、去广告、产品的极简风格定制。
|
||||
🐶 **玩**:只是一个很简单的小玩具,用 Rust 替代之前套壳网页打包的老思路,其实 PWA 也很好。
|
||||
|
||||
## 下载
|
||||
## 常用包下载
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>WeRead
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/WeRead.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/WeRead_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/WeRead_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/WeRead_amd64.deb">Linux</a>
|
||||
</td>
|
||||
<td>Twitter
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Twitter.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Twitter_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Twitter_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Twitter_amd64.deb">Linux</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -44,79 +44,60 @@
|
||||
<td><img src=https://cdn.fliggy.com/upic/mc41xq.jpg width=600/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>YouTube
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube_x64.msi">Windows</a>
|
||||
<td>LiZhi
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/LiZhi.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/LiZhi_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/LiZhi_amd64.deb">Linux</a>
|
||||
</td>
|
||||
<td>Reference
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference_x64.msi">Windows</a>
|
||||
<td>YouTube
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube_amd64.deb">Linux</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src=https://cdn.fliggy.com/upic/DX3dfG.png width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/Ea5ZRw.png width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/KFsZIY.png width=600/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Code
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code_amd64.deb">Linux</a>
|
||||
</td>
|
||||
<td>Google Translate
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/GoogleTranslate.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/GoogleTranslate_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/GoogleTranslate_x64.msi">Windows</a>
|
||||
<td>Reference
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference_amd64.deb">Linux</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src=https://cdn.fliggy.com/upic/EB1OYP.jpg width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/EmjUGy.png width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/KFsZIY.png 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_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Flomo_x64.msi">Windows</a>
|
||||
<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_amd64.deb">Linux</a>
|
||||
</td>
|
||||
<td>YuQue
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YuQue.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YuQue_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YuQue_x64.msi">Windows</a>
|
||||
<td>ChatGPT
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT.dmg">Mac</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_amd64.deb">Linux</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src=https://cdn.fliggy.com/upic/jg9Eeu.jpg width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/02SZQl.png width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/CJjagn.jpg width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/sfnTXf.png width=600/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<details>
|
||||
|
||||
注意:Windows 下不能安装到 `C:\Program File`,会直接闪退,建议安装到其他非管理员权限目录,比如 `D:\Program Files (x86)` 。
|
||||
<summary>🏂 更多应用如 Flomo / 语雀可去 <a href="https://github.com/tw93/Pake/releases">Release</a>下载,<b>此外点击可展开快捷键说明</b></summary>
|
||||
|
||||
## 命令行打包
|
||||
|
||||
<kbd>
|
||||
<img src="https://cdn.fliggy.com/upic/cOC1lF.gif" width="100%">
|
||||
</kbd>
|
||||
<br/><br/>
|
||||
|
||||
**Pake 提供了命令行工具,可以更快捷方便地一键自定义打你需要的包,详细可见 [文档](./bin/README.md)。**
|
||||
|
||||
```bash
|
||||
// 使用 npm 进行安装
|
||||
npm install -g pake-cli
|
||||
|
||||
// 命令使用
|
||||
pake url [options]
|
||||
|
||||
// 随便玩玩,首次由于安装环境会有些慢,后面就快了
|
||||
pake https://weekly.tw93.fun --name Weekly --transparent
|
||||
```
|
||||
|
||||
## 快捷键
|
||||
<br/>
|
||||
|
||||
| Mac | Windows/Linux | 功能 |
|
||||
| --------------------------- | ------------------------------ | ------------------ |
|
||||
@@ -131,49 +112,63 @@ pake https://weekly.tw93.fun --name Weekly --transparent
|
||||
| <kbd>⌘</kbd> + <kbd>=</kbd> | <kbd>Ctrl</kbd> + <kbd>=</kbd> | 放大页面 |
|
||||
| <kbd>⌘</kbd> + <kbd>0</kbd> | <kbd>Ctrl</kbd> + <kbd>0</kbd> | 重置页面缩放 |
|
||||
|
||||
此外还支持双击头部进行全屏切换,拖拽头部进行移动窗口,还有其他需求,欢迎提过来。
|
||||
此外还支持双击头部进行全屏切换,拖拽头部进行移动窗口,Mac 用户支持手势方式返回和去下一页,还有其他需求,欢迎提过来。
|
||||
|
||||
## 开发
|
||||
</details>
|
||||
|
||||
开始前参考 [Tauri](https://tauri.app/v1/guides/getting-started/prerequisites#setting-up-macos) 快速配置好环境。
|
||||
## 开始之前
|
||||
|
||||
1. **小白用户**:使用 「常用包下载」 方式来把玩 Pake 的能力,可去 [讨论群](https://github.com/tw93/Pake/discussions) 寻求帮助,也可试试 [Action](https://github.com/tw93/Pake/wiki/GitHub-Actions-%E5%9C%A8%E7%BA%BF%E7%BC%96%E8%AF%91%E5%A4%9A%E7%B3%BB%E7%BB%9F%E7%89%88%E6%9C%AC) 方式。
|
||||
2. **开发用户**:使用 「命令行一键打包」,对 Mac 比较友好,Windows / Linux 需折腾下 [环境配置](https://tauri.app/v1/guides/getting-started/prerequisites)。
|
||||
3. **折腾用户**:假如你前端和 Rust 都会,那可试试下面的 「[定制开发](#定制开发)」,可深度二次开发定制你的功能。
|
||||
|
||||
## 命令行一键打包
|
||||
|
||||
<kbd>
|
||||
<img src="https://gw.alipayobjects.com/zos/k/zd/pake.gif" width="100%">
|
||||
</kbd>
|
||||
<br/><br/>
|
||||
|
||||
**Pake 提供了命令行工具,可以更快捷方便地一键自定义打你需要的包,详细可见 [文档](./bin/README.md)。**
|
||||
|
||||
```bash
|
||||
// 使用 npm 进行安装
|
||||
npm install -g pake-cli
|
||||
|
||||
// 命令使用
|
||||
pake url [options]
|
||||
|
||||
// 随便玩玩,首次由于安装环境会有些慢,后面就快了
|
||||
pake https://weekly.tw93.fun --name Weekly --transparent
|
||||
```
|
||||
|
||||
假如你不太会使用命令行,或许使用 **GitHub Actions 在线编译多系统版本** 是一个不错的选择,可查看 [文档](https://github.com/tw93/Pake/wiki/GitHub-Actions-%E5%9C%A8%E7%BA%BF%E7%BC%96%E8%AF%91%E5%A4%9A%E7%B3%BB%E7%BB%9F%E7%89%88%E6%9C%AC)。
|
||||
|
||||
## 定制开发
|
||||
|
||||
开始前请确保电脑已经安装了 Rust 和 Node 的环境,此外需参考 [Tauri 文档](https://tauri.app/v1/guides/getting-started/prerequisites) 快速配置好环境才可以开始使用,假如你太不懂,使用上面的命令行打包会更加合适。
|
||||
|
||||
```sh
|
||||
// 安装依赖
|
||||
npm i
|
||||
|
||||
// 调试
|
||||
// 本地开发
|
||||
npm run dev
|
||||
|
||||
// 打包 Mac 应用
|
||||
// 本地调试
|
||||
npm run dev:debug
|
||||
|
||||
// 打包应用
|
||||
npm run build
|
||||
|
||||
// 打包 Windows 应用
|
||||
npm run build:windows
|
||||
|
||||
// 打包 Linux 应用
|
||||
npm run build:linux
|
||||
```
|
||||
|
||||
## 打新包
|
||||
## 高级使用
|
||||
|
||||
1. 修改 `src-tauri` 目录下的 `tauri.conf.json` 中的 `url、productName、icon、identifier` 这 4 个字段,其中 icon 可以从 icons 目录选择一个,也可以去 [macOSicons](https://macosicons.com/#/) 下载符合产品名称的
|
||||
2. 关于窗口属性设置,可以在 `tauri.conf.json` 修改 `windows` 属性对应的 `width/height`,是否全屏 `fullscreen`,是否可以调整大小 `resizable`,假如想适配 Mac 沉浸式头部,可以将 `transparent` 设置成 `true`,找到 Header 元素加一个 `padding-top` 样式即可,不想适配改成 `false` 也行
|
||||
3. `npm run dev` 本地调试看看效果,此外可以使用 `npm run dev:debug` 进行容器调试
|
||||
4. `npm run build` 运行即可打生产包
|
||||
|
||||
## 高级用法
|
||||
|
||||
#### 1. 如何改写样式,如去掉原站广告、不想要的模块、甚至重新设计?
|
||||
|
||||
首先需要使用 `npm run dev:debug` 打开 devtools 调试模式,找到你需要修改的样式名称,先在 devtools 里面验证效果;找到 `pake.js` 中样式位置 `style.innerHTML` ,将需要覆盖的样式加上即可,有一些案例你可以模仿。
|
||||
|
||||
#### 2. 如何注入 JS 的逻辑,比如实现事件监听,比如说键盘快捷键?
|
||||
|
||||
参考 `pake.js` 中事件监听 `document.addEventListener`,直接编写即可,这里更多是基础前端的技术。
|
||||
|
||||
#### 3. 如何进行容器内的事件和 Pake 通信,比如说 Web 的拖拽、滚动、特殊点击传递啥的?
|
||||
|
||||
参考 `pake.js` 中通信代码 `postMessage`,写好事件监听,然后用 `window.ipc.postMessage` 将事件以及参数传递出来,然后参考容器接收事件 `window.drag_window`,自己处理即可,更多可以参考 tauri 以及 wry 的官方文档。
|
||||
1. 代码结构可参考 [文档](https://github.com/tw93/Pake/wiki/Pake-%E7%9A%84%E4%BB%A3%E7%A0%81%E7%BB%93%E6%9E%84%E8%AF%B4%E6%98%8E),便于你在开发前了解更多。
|
||||
2. 修改 src-tauri 目录下的 `tauri.conf.json`以及 `tauri.xxx.conf.json` 中的 url、productName、icon、identifier 这 4 个字段,其中 icon 可以从 icons 目录选择一个,也可以去 [macOSicons](https://macosicons.com/#/) 下载符合效果的。
|
||||
3. 关于窗口属性设置,可以在 `tauri.conf.json` 修改 windows 属性对应的 `width/height`,fullscreen 是否全屏,resizable 是否可以调整大小,假如想适配 Mac 沉浸式头部,可以将 transparent 设置成 `true`,找到 Header 元素加一个 padding-top 样式即可,不想适配改成 `false` 也行。
|
||||
4. 此外样式改写、屏蔽广告、逻辑代码注入、容器消息通信、自定义快捷键可见 [高级用法](https://github.com/tw93/Pake/wiki/Pake-%E7%9A%84%E9%AB%98%E7%BA%A7%E7%94%A8%E6%B3%95)。
|
||||
|
||||
## 开发者
|
||||
|
||||
@@ -203,6 +198,13 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
|
||||
<sub><b>Pan93412</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/wanghanzhen">
|
||||
<img src="https://avatars.githubusercontent.com/u/25301012?v=4" width="90;" alt="wanghanzhen"/>
|
||||
<br />
|
||||
<sub><b>Volare</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/liby">
|
||||
<img src="https://avatars.githubusercontent.com/u/38807139?v=4" width="90;" alt="liby"/>
|
||||
@@ -211,10 +213,10 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/wanghanzhen">
|
||||
<img src="https://avatars.githubusercontent.com/u/25301012?v=4" width="90;" alt="wanghanzhen"/>
|
||||
<a href="https://github.com/essesoul">
|
||||
<img src="https://avatars.githubusercontent.com/u/58624474?v=4" width="90;" alt="essesoul"/>
|
||||
<br />
|
||||
<sub><b>Volare</b></sub>
|
||||
<sub><b>Essesoul</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@@ -223,22 +225,8 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
|
||||
<br />
|
||||
<sub><b>Horus</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/QingZ11">
|
||||
<img src="https://avatars.githubusercontent.com/u/38887077?v=4" width="90;" alt="QingZ11"/>
|
||||
<br />
|
||||
<sub><b>Steam</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/2nthony">
|
||||
<img src="https://avatars.githubusercontent.com/u/19513289?v=4" width="90;" alt="2nthony"/>
|
||||
<br />
|
||||
<sub><b>2nthony</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AielloChan">
|
||||
<img src="https://avatars.githubusercontent.com/u/7900765?v=4" width="90;" alt="AielloChan"/>
|
||||
@@ -246,13 +234,49 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
|
||||
<sub><b>Aiello</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/QingZ11">
|
||||
<img src="https://avatars.githubusercontent.com/u/38887077?v=4" width="90;" alt="QingZ11"/>
|
||||
<br />
|
||||
<sub><b>Steam</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/2nthony">
|
||||
<img src="https://avatars.githubusercontent.com/u/19513289?v=4" width="90;" alt="2nthony"/>
|
||||
<br />
|
||||
<sub><b>2nthony</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/nekomeowww">
|
||||
<img src="https://avatars.githubusercontent.com/u/11081491?v=4" width="90;" alt="nekomeowww"/>
|
||||
<br />
|
||||
<sub><b>Ayaka Neko</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/turkyden">
|
||||
<img src="https://avatars.githubusercontent.com/u/24560160?v=4" width="90;" alt="turkyden"/>
|
||||
<br />
|
||||
<sub><b>Dengju Deng</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/princemaple">
|
||||
<img src="https://avatars.githubusercontent.com/u/1329716?v=4" width="90;" alt="princemaple"/>
|
||||
<br />
|
||||
<sub><b>Po Chen</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/houhoz">
|
||||
<img src="https://avatars.githubusercontent.com/u/19684376?v=4" width="90;" alt="houhoz"/>
|
||||
<br />
|
||||
<sub><b>Hyzhao</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/liusishan">
|
||||
<img src="https://avatars.githubusercontent.com/u/33129823?v=4" width="90;" alt="liusishan"/>
|
||||
@@ -272,11 +296,7 @@ Pake 的发展离不开这些 Hacker 们,一起贡献了大量能力,也欢
|
||||
|
||||
## 支持
|
||||
|
||||
- 我有两只猫,一只叫汤圆,一只叫可乐,假如觉得 Pake 让你生活更美好,可以给汤圆可乐 <a href="https://miaoyan.app/cats.html?name=Pake" target="_blank">喂罐头 🥩🍤</a>。
|
||||
- 如果你喜欢 Pake,可以在 Github Star,更欢迎 [推荐](https://twitter.com/intent/tweet?url=https://github.com/tw93/Pake&text=Pake%20%E4%B8%80%E4%B8%AA%E5%BE%88%E7%AE%80%E5%8D%95%E7%9A%84%E7%94%A8%20Rust%20%E6%89%93%E5%8C%85%E7%BD%91%E9%A1%B5%E7%94%9F%E6%88%90%20Mac%20App%20%E7%9A%84%E5%B7%A5%E5%85%B7%EF%BC%8C%E7%9B%B8%E6%AF%94%E4%BC%A0%E7%BB%9F%E7%9A%84%20Electron%20%E5%A5%97%E5%A3%B3%E6%89%93%E5%8C%85%EF%BC%8C%E5%A4%A7%E5%B0%8F%E8%A6%81%E5%B0%8F%E5%B0%86%E8%BF%91%2040%20%E5%80%8D%EF%BC%8C%E4%B8%80%E8%88%AC%202M%20%E5%B7%A6%E5%8F%B3%EF%BC%8C%E5%BA%95%E5%B1%82%E4%BD%BF%E7%94%A8Tauri%20%EF%BC%8C%E6%80%A7%E8%83%BD%E4%BD%93%E9%AA%8C%E8%BE%83%20JS%20%E6%A1%86%E6%9E%B6%E8%A6%81%E8%BD%BB%E5%BF%AB%E4%B8%8D%E5%B0%91%EF%BC%8C%E5%86%85%E5%AD%98%E5%B0%8F%E5%BE%88%E5%A4%9A%EF%BC%8C%E6%94%AF%E6%8C%81%E5%BE%AE%E4%BF%A1%E8%AF%BB%E4%B9%A6%E3%80%81Twitter%E3%80%81Youtube%E3%80%81RunCode%E3%80%81Flomo%E3%80%81%E8%AF%AD%E9%9B%80%E7%AD%89%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%BE%88%E6%96%B9%E4%BE%BF%E4%BA%8C%E6%AC%A1%E5%BC%80%E5%8F%91~) 给你志同道合的朋友使用。
|
||||
- 可以关注我的 [Twitter](https://twitter.com/HiTw93) 获取到最新的 Pake 更新消息,也欢迎加入 [Telegram](https://t.me/miaoyan) 聊天群。
|
||||
|
||||
## 最后
|
||||
|
||||
1. 希望大伙玩的过程中有一种学习新技术的喜悦感,如果有新点子欢迎告诉我
|
||||
2. 假如你发现有很适合做成桌面 App 的网页也很欢迎告诉我,我给加到里面来
|
||||
1. 我有两只猫,一只叫汤圆,一只叫可乐,假如觉得 Pake 让你生活更美好,可以给汤圆可乐 <a href="https://miaoyan.app/cats.html?name=Pake" target="_blank">喂罐头 🥩🍤</a>。
|
||||
2. 如果你喜欢 Pake,可以在 Github Star,更欢迎 [推荐](https://twitter.com/intent/tweet?url=https://github.com/tw93/Pake&text=%23Pake%20%E4%B8%80%E4%B8%AA%E5%BE%88%E7%AE%80%E5%8D%95%E7%9A%84%E7%94%A8%20Rust%20%E6%89%93%E5%8C%85%E7%BD%91%E9%A1%B5%E7%94%9F%E6%88%90%20Mac%20App%20%E7%9A%84%E5%B7%A5%E5%85%B7%EF%BC%8C%E7%9B%B8%E6%AF%94%E4%BC%A0%E7%BB%9F%E7%9A%84%20Electron%20%E5%A5%97%E5%A3%B3%E6%89%93%E5%8C%85%EF%BC%8C%E5%A4%A7%E5%B0%8F%E8%A6%81%E5%B0%8F%E5%B0%86%E8%BF%91%2040%20%E5%80%8D%EF%BC%8C%E4%B8%80%E8%88%AC%202M%20%E5%B7%A6%E5%8F%B3%EF%BC%8C%E5%BA%95%E5%B1%82%E4%BD%BF%E7%94%A8Tauri%20%EF%BC%8C%E6%80%A7%E8%83%BD%E4%BD%93%E9%AA%8C%E8%BE%83%20JS%20%E6%A1%86%E6%9E%B6%E8%A6%81%E8%BD%BB%E5%BF%AB%E4%B8%8D%E5%B0%91%EF%BC%8C%E5%86%85%E5%AD%98%E5%B0%8F%E5%BE%88%E5%A4%9A%EF%BC%8C%E6%94%AF%E6%8C%81%E5%BE%AE%E4%BF%A1%E8%AF%BB%E4%B9%A6%E3%80%81Twitter%E3%80%81Youtube%E3%80%81RunCode%E3%80%81Flomo%E3%80%81%E8%AF%AD%E9%9B%80%E7%AD%89%EF%BC%8C%E5%8F%AF%E4%BB%A5%E5%BE%88%E6%96%B9%E4%BE%BF%E4%BA%8C%E6%AC%A1%E5%BC%80%E5%8F%91~) 给你志同道合的朋友使用。
|
||||
3. 可以关注我的 [Twitter](https://twitter.com/HiTw93) 获取到最新的 Pake 更新消息,也欢迎加入 [Telegram](https://t.me/miaoyan) 聊天群。
|
||||
4. 希望大伙玩的过程中有一种学习新技术的喜悦感,假如你发现有很适合做成桌面 App 的网页也很欢迎告诉我。
|
||||
|
||||
166
README_EN.md
@@ -1,6 +1,7 @@
|
||||
<p align="left"><a href="https://github.com/tw93/Pake">中文</a> | <strong>English</strong></p>
|
||||
<p align="center">
|
||||
<img src=https://gw.alipayobjects.com/zos/k/fa/logo-modified.png width=138/>
|
||||
</p>
|
||||
<h1 align="center">Pake</h1>
|
||||
<div align="center">
|
||||
<a href="https://twitter.com/HiTw93" target="_blank">
|
||||
@@ -14,8 +15,7 @@
|
||||
<a href="https://github.com/tw93/Pake/issues?q=is%3Aissue+is%3Aclosed" target="_blank">
|
||||
<img alt="GitHub closed issues" src="https://img.shields.io/github/issues-closed/tw93/Pake.svg?style=flat-square"></a>
|
||||
</div>
|
||||
<div align="left">A simple way to package a web page to desktop application, supporting Mac / Windows / Linux, app download、command line one-click packaging、custom development can be found in the following documents, welcome to <a href=https://github.com/tw93/Pake/discussions>Discussions</a> to see if there have anything you interesting.</div>
|
||||
</p>
|
||||
<div align="left">A simple way to package a web page to desktop application, supporting Mac / Windows / Linux, app download、command line one-click packaging、custom development can be found in the following documents, welcome to <a href=https://github.com/tw93/Pake/discussions>Discussions</a> to see if there have anything you're interesting.</div>
|
||||
|
||||
## Features
|
||||
|
||||
@@ -30,13 +30,13 @@
|
||||
<tr>
|
||||
<td>WeRead
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/WeRead.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/WeRead_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/WeRead_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/WeRead_amd64.deb">Linux</a>
|
||||
</td>
|
||||
<td>Twitter
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Twitter.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Twitter_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Twitter_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Twitter_amd64.deb">Linux</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -44,58 +44,59 @@
|
||||
<td><img src=https://cdn.fliggy.com/upic/mc41xq.jpg width=600/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>YouTube
|
||||
<td>LiZhi
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/LiZhi.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/LiZhi_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/LiZhi_amd64.deb">Linux</a>
|
||||
</td>
|
||||
<td>YouTube
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube_x64.msi">Windows</a>
|
||||
</td>
|
||||
<td>Reference
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YouTube_amd64.deb">Linux</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src=https://cdn.fliggy.com/upic/DX3dfG.png width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/Ea5ZRw.png width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/KFsZIY.png width=600/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Code
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code_x64.msi">Windows</a>
|
||||
</td>
|
||||
<td>Google Translate
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/GoogleTranslate.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/GoogleTranslate_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/GoogleTranslate_x64.msi">Windows</a>
|
||||
</td>
|
||||
<td>Code
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Code_amd64.deb">Linux</a>
|
||||
</td>
|
||||
<td>Reference
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference_x64.msi">Windows</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Reference_amd64.deb">Linux</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src=https://cdn.fliggy.com/upic/EB1OYP.jpg width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/EmjUGy.png width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/EB1OYP.jpg width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/KFsZIY.png 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_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/Flomo_x64.msi">Windows</a>
|
||||
</td>
|
||||
<td>YuQue
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YuQue.dmg">Mac</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YuQue_amd64.deb">Linux</a>
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/YuQue_x64.msi">Windows</a>
|
||||
</td>
|
||||
<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_amd64.deb">Linux</a>
|
||||
</td>
|
||||
<td>ChatGPT
|
||||
<a href="https://github.com/tw93/Pake/releases/latest/download/ChatGPT.dmg">Mac</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_amd64.deb">Linux</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src=https://cdn.fliggy.com/upic/jg9Eeu.jpg width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/02SZQl.png width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/CJjagn.jpg width=600/></td>
|
||||
<td><img src=https://cdn.fliggy.com/upic/sfnTXf.png width=600/></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
Note: it cannot be installed to C:\Program File under Windows, and it will crash directly. It is recommended to install to other non-administrator directories, such as D:\Program Files (x86).
|
||||
<details>
|
||||
<summary>🏂 <b>Expand the shortcut key</b></summary>
|
||||
|
||||
## Shortcuts
|
||||
<br/>
|
||||
|
||||
| Mac | Windows/Linux | Function |
|
||||
| --------------------------- | ------------------------------ | ----------------------------- |
|
||||
@@ -110,11 +111,41 @@ Note: it cannot be installed to C:\Program File under Windows, and it will crash
|
||||
| <kbd>⌘</kbd> + <kbd>=</kbd> | <kbd>Ctrl</kbd> + <kbd>=</kbd> | Zoom in the Page |
|
||||
| <kbd>⌘</kbd> + <kbd>0</kbd> | <kbd>Ctrl</kbd> + <kbd>0</kbd> | Reset the page zoom |
|
||||
|
||||
In addition, it supports double clicking the head to switch to full screen, and dragging the head to move the window
|
||||
In addition, it supports double-clicking the head to switch to full screen, Mac users support gesture mode to return and go to the next page, and dragging the head to move the window.
|
||||
|
||||
</details>
|
||||
|
||||
## Before you start
|
||||
|
||||
1. **Beginner users**: Use the 「Download」 method to play with Pake's capabilities, go to discussion groups for help, or try the [Action](https://github.com/tw93/Pake/wiki/GitHub-Actions-Online-Compilation-Multi-system-Version) method.
|
||||
2. **Development users**: Use 「command line packing」, Mac friendly, Windows/Linux requires a bit of tinkering, but both require environment [configuration](https://tauri.app/v1/guides/getting-started/prerequisites).
|
||||
3. **Hacker users**: If you know both front-end and rust, try the following custom development, which allows you to customize your features with deep secondary development.
|
||||
|
||||
## Command line packing
|
||||
|
||||
<kbd>
|
||||
<img src="https://gw.alipayobjects.com/zos/k/zd/pake.gif" width="100%">
|
||||
</kbd>
|
||||
<br/><br/>
|
||||
|
||||
**Pake provides a command line tool that makes it quicker and easier to customize the packages you need, as detailed in [documentation](./.github/workflows/docs/README_EN.md).**
|
||||
|
||||
```bash
|
||||
// Install with npm
|
||||
npm install -g pake-cli
|
||||
|
||||
// Command usage
|
||||
pake url [options]
|
||||
|
||||
// Play casually, first time due to the installation environment will be a little slow
|
||||
pake https://weekly.tw93.fun --name Weekly --transparent
|
||||
```
|
||||
|
||||
If you are a little white who doesn't know how to use the command line, a good option is to use **GitHub Actions online compilation**, see the [tutorial](https://github.com/tw93/Pake/wiki/GitHub-Actions-Online-Compilation-Multi-system-Version).
|
||||
|
||||
## Development
|
||||
|
||||
Refer to the [Tauri documentation](https://tauri.app/v1/guides/getting-started/prerequisites#setting-up-macos) to quickly configure your environment before you start.
|
||||
Before starting, make sure that the computer has installed the Rust and Node environment,refer to the [Tauri documentation](https://tauri.app/v1/guides/getting-started/prerequisites) to quickly configure your environment before you start. If you don't understand, it will be more appropriate to use the above command line to pack with one click.
|
||||
|
||||
```sh
|
||||
// Install Dependencies
|
||||
@@ -123,53 +154,24 @@ npm i
|
||||
// Local development
|
||||
npm run dev
|
||||
|
||||
// Pack Mac application
|
||||
// Local debug
|
||||
npm run dev:debug
|
||||
|
||||
// Pack application
|
||||
npm run build
|
||||
|
||||
// Pack Windows application
|
||||
npm run build:windows
|
||||
|
||||
// Pack Linux application
|
||||
npm run build:linux
|
||||
|
||||
// One-click packaging of all Linux/Mac projects
|
||||
chmod +x build.sh && ./build.sh
|
||||
|
||||
// One-click packaging of all Windows projects
|
||||
.\build.bat
|
||||
```
|
||||
|
||||
// Package all your projects in one click
|
||||
chmod +x build.sh && ./build.sh
|
||||
## Advanced use
|
||||
|
||||
## New pack
|
||||
|
||||
1. Modify the `tauri.conf.json` in the `src-tauri` directory to include 4 fields `url, productName, icon, identifier`, icon can be selected from the `icons` directory or downloaded from [macOSicons](https://macosicons.com/#/) to match the product.
|
||||
2. For window property settings, you can modify the `width/height` of the `windows` property in `tauri.conf.json`, whether it is `fullscreen`, whether it is `resizable`, If you want to adapt the immersive header under Mac, you can set `transparent` to `true` and then find header element and add the `padding-top` style.
|
||||
3. `npm run dev` for local debugging; `npm run dev:debug` to open the devtools for container debugging.
|
||||
4. `npm run build` can be run to package for production.
|
||||
|
||||
## Advanced
|
||||
|
||||
#### 1. How do I rewrite the style, e.g. to remove ads from the original site, or even redesign it?
|
||||
|
||||
First, open devtools debug mode with `npm run dev:debug`. After that, find the name of the style you want to change and verify the effect in devtools, and find the location of the style in `pake.js` with `style.innerHTML`. Finally, add the style you need to override, there are some examples you can copy.
|
||||
|
||||
#### 2. How to inject js code, e.g. to implement event listeners, e.g. keyboard shortcuts?
|
||||
|
||||
Refer to the event listener in `pake.js` with `document.addEventListener`, and write it directly, it's more of a basic front-end technique here.
|
||||
|
||||
#### 3. How to communicate with Pake about events in containers, such as dragging and dropping, scrolling, special clicks on the Web, etc.?
|
||||
|
||||
Refer to the communication code in `pake.js` with `postMessage`, write the event listener and then use `window.ipc.postMessage` to pass the event and its parameters, then refer to the container to receive events `window.drag_window` and handle them yourself, for more information, refer to tauri and wry's official documentation.
|
||||
1. The code structure can be referred to [Here](https://github.com/tw93/Pake/wiki/Description-of-Pake's-code-structure), it is convenient for you to learn more before development.
|
||||
2. Modify the `tauri.conf.json` and `tauri.xxx.conf.json` in the `src-tauri` directory to include 4 fields `url, productName, icon, identifier`, icon can be selected from the `icons` directory or downloaded from [macOSicons](https://macosicons.com/#/) to match the product.
|
||||
3. For window property settings, you can modify the `width/height` of the `windows` property in `tauri.conf.json`, whether it is `fullscreen`, whether it is `resizable`, If you want to adapt the immersive header under Mac, you can set `transparent` to `true` and then find header element and add the `padding-top` style.
|
||||
4. About style rewriting, advertising shielding, js injection, container message communication, and user-defined shortcut keys, you can see [Advanced Usage of Make](https://github.com/tw93/Pake/wiki/Advanced-Usage-of-Make).
|
||||
|
||||
## Support
|
||||
|
||||
- I have two cats, one is called TangYuan, and one is called Coke, If you think Pake makes your life better, you can give my cats <a href="https://miaoyan.app/cats.html?name=Pake" target="_blank">feed canned food 🥩🍤</a>.
|
||||
- If you like Pake, you can star it in Github. We are more welcome to [recommend Pake](https://twitter.com/intent/tweet?url=https://github.com/tw93/Pake&text=Pake%20-%20A%20simple%20Rust%20packaged%20web%20pages%20to%20generate%20Mac%20App%20tool,%20compared%20to%20traditional%20Electron%20package,%20the%20size%20of%20nearly%2040%20times%20smaller,%20generally%20about%202M,%20the%20underlying%20use%20of%20Tauri,%20performance%20experience%20than%20the%20JS%20framework%20is%20much%20lighter~) to your like-minded friends.
|
||||
- You can follow my [Twitter](https://twitter.com/HiTw93) to get the latest news of Pake, or join [Telegram](https://t.me/miaoyan) chat group.
|
||||
|
||||
## Finally
|
||||
|
||||
1. I hope that you will enjoy playing with it and let me know if you have any new ideas.
|
||||
2. If you find a page that would be great for a Mac App, please let me know and I'll add it to the list.
|
||||
1. I have two cats, one is called TangYuan, and one is called Coke, If you think Pake makes your life better, you can give my cats <a href="https://miaoyan.app/cats.html?name=Pake" target="_blank">feed canned food 🥩🍤</a>.
|
||||
2. If you like Pake, you can star it in Github. Also welcome to [recommend Pake](https://twitter.com/intent/tweet?url=https://github.com/tw93/Pake&text=%23Pake%20-%20A%20simple%20Rust%20packaged%20web%20pages%20to%20generate%20Mac%20App%20tool,%20compared%20to%20traditional%20Electron%20package,%20the%20size%20of%20nearly%2040%20times%20smaller,%20generally%20about%202M,%20the%20underlying%20use%20of%20Tauri,%20performance%20experience%20than%20the%20JS%20framework%20is%20much%20lighter~) to your friends.
|
||||
3. You can follow my [Twitter](https://twitter.com/HiTw93) to get the latest news of Pake, or join [Telegram](https://t.me/miaoyan) chat group.
|
||||
4. I hope that you will enjoy playing with it. If you find a page that would be great for a Mac App, please let me know.
|
||||
|
||||
6
app.csv
@@ -1,9 +1,11 @@
|
||||
name(Linux),name(Mac/Windows),name_zh,url
|
||||
twitter,Twitter,推特,https://twitter.com/
|
||||
translate,GoogleTranslate,谷歌翻译,https://translate.google.com/
|
||||
youtube,YouTube,YouTube,https://youtube.com
|
||||
reference,Reference,Reference,https://wangchujiang.com/reference/index.html
|
||||
code,Code,Code,https://riju.codes/
|
||||
yuque,YuQue,语雀,https://www.yuque.com/
|
||||
flomo,Flomo,浮墨,https://flomoapp.com/mine
|
||||
chatgpt,ChatGPT,ChatGPT,https://chat.openai.com/chat
|
||||
flomo,Flomo,浮墨,https://v.flomoapp.com/mine
|
||||
qwerty,Qwerty,Qwerty,https://qwerty.kaiyi.cool/
|
||||
lizhi,LiZhi,李志,https://lizhi.turkyden.com/?from=pake
|
||||
weread,WeRead,微信阅读,https://weread.qq.com/
|
||||
|
||||
|
21
bin/README.md
vendored
@@ -4,20 +4,23 @@
|
||||
npm install -g pake-cli
|
||||
```
|
||||
|
||||
如果安装失败提示没有权限,请使用 `sudo` 运行。
|
||||
如果安装失败提示没有权限,请参考该贴解决:[链接](https://gist.github.com/Giancarlos/d087f8a9e6516716da98ad0c0f5a8f58)。
|
||||
|
||||
此外,请确保你使用的是正确的 Node.js 版本(`^14.13 || >=16.0.0`)。如果你在使用 [nvm](https://github.com/nvm-sh/nvm) 进行 Node.js 版本管理,可以尝试在项目的目录下运行 `nvm use`,就会拿到正确的版本;其他一众 Node.js 版本工具,比如 [fnm](https://github.com/Schniz/fnm)、[tj/n](https://github.com/tj/n) 应该也有类似的功能。
|
||||
|
||||
**尽量不要使用 `sudo` 权限**。 如果实在要用 sudo,请手动安装 rust 到系统环境。Mac 可以用 brew 命令安装,Linux 如 Ubuntu 可以用 apt 命令安装。
|
||||
|
||||
|
||||
## 用法
|
||||
|
||||
```bash
|
||||
pake url [options]
|
||||
pake url [options]
|
||||
```
|
||||
|
||||
打包完成后的应用程序默认为当前工作目录,首次打包由于需配置好环境,需要一些时间,请耐心等待即可。
|
||||
|
||||
Note: 打包需要用 `Rust` 环境,如果没有 `Rust`,会提示确认安装。如遇安装失败或超时,可[自行安装](https://www.rust-lang.org/tools/install)。
|
||||
|
||||
Note: 目前仅支持 MacOs,后续会支持其他平台。
|
||||
|
||||
### url
|
||||
|
||||
url 为你需要打包的网页链接 🔗,必须提供。
|
||||
@@ -28,7 +31,7 @@ url 为你需要打包的网页链接 🔗,必须提供。
|
||||
|
||||
#### [name]
|
||||
|
||||
应用名称,如输入时未指定,会提示你输入。
|
||||
应用名称,如输入时未指定,会提示你输入,尽量使用英语。
|
||||
|
||||
```shell
|
||||
--name <value>
|
||||
@@ -36,9 +39,11 @@ url 为你需要打包的网页链接 🔗,必须提供。
|
||||
|
||||
#### [icon]
|
||||
|
||||
应用 icon,支持本地/远程文件,默认为 Pake 自带图标。
|
||||
应用 icon,支持本地/远程文件,默认为 Pake 自带图标,定制的可以去 [icon-icons](https://icon-icons.com) 或 [macOSicons](https://macosicons.com/#/) 搜索下载。
|
||||
|
||||
- MacOS 下必须为 `.icns`
|
||||
- Windows 下必须为 `.ico`
|
||||
- Linux 下必须为 `.png`
|
||||
|
||||
```shell
|
||||
--icon <path>
|
||||
@@ -46,7 +51,7 @@ url 为你需要打包的网页链接 🔗,必须提供。
|
||||
|
||||
#### [height]
|
||||
|
||||
打包后的应用窗口高度,默认 `800px`。
|
||||
打包后的应用窗口高度,默认 `780px`。
|
||||
|
||||
```shell
|
||||
--height <number>
|
||||
@@ -54,7 +59,7 @@ url 为你需要打包的网页链接 🔗,必须提供。
|
||||
|
||||
#### [width]
|
||||
|
||||
打包后的应用窗口宽度,默认 `1280px`。
|
||||
打包后的应用窗口宽度,默认 `1200px`。
|
||||
|
||||
```shell
|
||||
--width <number>
|
||||
|
||||
89
bin/README_EN.md
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install -g pake-cli
|
||||
```
|
||||
|
||||
If the installation fails and you are prompted that you do not have permission, please see this [website](https://gist.github.com/Giancarlos/d087f8a9e6516716da98ad0c0f5a8f58) .
|
||||
|
||||
Also make sure that you're using a correct Node.js version (`^14.13 || >=16.0.0`). If you're using [nvm](https://github.com/nvm-sh/nvm) for Node.js version management you may run `nvm use` from the root folder of the project and the correct version will be picked up. Other Node.js version management tools, such as [fnm](https://github.com/Schniz/fnm) and [tj/n](https://github.com/tj/n), should also have similar feature.
|
||||
|
||||
**try not to use `sudo` permissions**, If you must use sudo, you need install rust in you system environment. For Mac, you can use brew to install it. For Linux like Ubuntu, you need apt to install it.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
pake url [options]
|
||||
```
|
||||
|
||||
After the packaging, the application defaults to the current working directory. Since the environment needs to be configured for the first packaging, it will take some time. Please wait patiently.
|
||||
|
||||
Note: The Rust environment is required for packaging. If you do not have Rust, you will be prompted to confirm the installation. If the installation fails or times out, you can [install](https://www.rust-lang.org/tools/install) it yourself.
|
||||
|
||||
### url
|
||||
|
||||
The url🔗 is the webpage link you need to package, Must be provided.
|
||||
|
||||
### [options]
|
||||
|
||||
Some specific options are provided. When packaging, corresponding parameters can be passed to achieve customized effects.
|
||||
|
||||
#### [name]
|
||||
|
||||
The application name, if not specified when entering, will prompt you to enter, input must be English.
|
||||
|
||||
```shell
|
||||
--name <value>
|
||||
```
|
||||
|
||||
#### [icon]
|
||||
|
||||
The application icon, support local and remote files, the default is brand icon of Pake. Customized product icon can go to [icon icons](https://icon-icons.com) Or [macOSicons](https://macosicons.com/#/) download it.
|
||||
|
||||
- MacOS must be `.icns`
|
||||
- Windows must be `.ico`
|
||||
- Linux must be `.png`
|
||||
|
||||
```shell
|
||||
--icon <path>
|
||||
```
|
||||
|
||||
#### [height]
|
||||
|
||||
The height of the packaged application window. The default is `780px`.
|
||||
|
||||
```shell
|
||||
--height <number>
|
||||
```
|
||||
|
||||
#### [width]
|
||||
|
||||
The width of the packaged application window. The default is `1200px`.
|
||||
|
||||
```shell
|
||||
--width <number>
|
||||
```
|
||||
|
||||
#### [transparent]
|
||||
|
||||
Whether to enable the immersive header. The default is `false`.
|
||||
|
||||
```shell
|
||||
--transparent
|
||||
```
|
||||
|
||||
#### [resize]
|
||||
|
||||
Whether the size can be dragged. The default value is `true`.
|
||||
|
||||
```shell
|
||||
--no-resizable
|
||||
```
|
||||
|
||||
#### [fullscreen]
|
||||
|
||||
Whether to open the full screen after opening the application. The default is `false`.
|
||||
|
||||
```shell
|
||||
--fullscreen <value>
|
||||
```
|
||||
12
bin/builders/BuilderFactory.ts
vendored
@@ -1,12 +1,20 @@
|
||||
import { IS_MAC } from '@/utils/platform.js';
|
||||
import { IS_MAC, IS_WIN, IS_LINUX } from '@/utils/platform.js';
|
||||
import { IBuilder } from './base.js';
|
||||
import MacBuilder from './MacBuilder.js';
|
||||
import WinBuilder from './WinBulider.js';
|
||||
import LinuxBuilder from './LinuxBuilder.js';
|
||||
|
||||
export default class BuilderFactory {
|
||||
static create(): IBuilder {
|
||||
if (IS_MAC) {
|
||||
return new MacBuilder();
|
||||
}
|
||||
throw new Error('The current system does not support');
|
||||
if (IS_WIN) {
|
||||
return new WinBuilder();
|
||||
}
|
||||
if (IS_LINUX) {
|
||||
return new LinuxBuilder();
|
||||
}
|
||||
throw new Error('The current system does not support!!');
|
||||
}
|
||||
}
|
||||
|
||||
81
bin/builders/LinuxBuilder.ts
vendored
@@ -0,0 +1,81 @@
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import prompts from 'prompts';
|
||||
import { checkRustInstalled, installRust } from '@/helpers/rust.js';
|
||||
import { PakeAppOptions } from '@/types.js';
|
||||
import { IBuilder } from './base.js';
|
||||
import { shellExec } from '@/utils/shell.js';
|
||||
// @ts-expect-error 加上resolveJsonModule rollup会打包报错
|
||||
// import tauriConf from '../../src-tauri/tauri.windows.conf.json';
|
||||
import tauriConf from './tauriConf.js';
|
||||
|
||||
import { fileURLToPath } from 'url';
|
||||
import logger from '@/options/logger.js';
|
||||
import { mergeTauriConfig } from './common.js';
|
||||
import { npmDirectory } from '@/utils/dir.js';
|
||||
|
||||
export default class LinuxBuilder implements IBuilder {
|
||||
async prepare() {
|
||||
logger.info(
|
||||
'To build the Linux app, you need to install Rust and Linux package'
|
||||
);
|
||||
logger.info(
|
||||
'See more in https://tauri.app/v1/guides/getting-started/prerequisites#installing\n'
|
||||
);
|
||||
if (checkRustInstalled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await prompts({
|
||||
type: 'confirm',
|
||||
message: 'We detected that you have not installed Rust. Install it now?',
|
||||
name: 'value',
|
||||
});
|
||||
|
||||
if (res.value) {
|
||||
// TODO 国内有可能会超时
|
||||
await installRust();
|
||||
} else {
|
||||
logger.error('Error: Pake needs Rust to package your webapp!!!');
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
async build(url: string, options: PakeAppOptions) {
|
||||
logger.debug('PakeAppOptions', options);
|
||||
const { name } = options;
|
||||
|
||||
await mergeTauriConfig(url, options, tauriConf);
|
||||
const _ = await shellExec(`cd ${npmDirectory} && npm install && npm run build`);
|
||||
let arch = "";
|
||||
if (process.arch === "x64") {
|
||||
arch = "amd64";
|
||||
} else {
|
||||
arch = process.arch;
|
||||
}
|
||||
const debName = `${name}_${tauriConf.package.version}_${arch}.deb`;
|
||||
const appPath = this.getBuildedAppPath(npmDirectory, "deb", debName);
|
||||
const distPath = path.resolve(`${name}.deb`);
|
||||
await fs.copyFile(appPath, distPath);
|
||||
await fs.unlink(appPath);
|
||||
|
||||
|
||||
const appImageName = `${name}_${tauriConf.package.version}_${arch}.AppImage`;
|
||||
const appImagePath = this.getBuildedAppPath(npmDirectory, "appimage", appImageName);
|
||||
const distAppPath = path.resolve(`${name}.AppImage`);
|
||||
await fs.copyFile(appImagePath, distAppPath);
|
||||
await fs.unlink(appImagePath);
|
||||
logger.success('Build success!');
|
||||
logger.success('You can find the deb app installer in', distPath);
|
||||
logger.success('You can find the Appimage app installer in', distAppPath);
|
||||
}
|
||||
|
||||
getBuildedAppPath(npmDirectory: string,packageType: string, packageName: string) {
|
||||
return path.join(
|
||||
npmDirectory,
|
||||
'src-tauri/target/release/bundle/',
|
||||
packageType,
|
||||
packageName
|
||||
);
|
||||
}
|
||||
}
|
||||
51
bin/builders/MacBuilder.ts
vendored
@@ -6,9 +6,12 @@ import { PakeAppOptions } from '@/types.js';
|
||||
import { IBuilder } from './base.js';
|
||||
import { shellExec } from '@/utils/shell.js';
|
||||
// @ts-expect-error 加上resolveJsonModule rollup会打包报错
|
||||
import tauriConf from '../../src-tauri/tauri.conf.json';
|
||||
import { fileURLToPath } from 'url';
|
||||
// import tauriConf from '../../src-tauri/tauri.macos.conf.json';
|
||||
import tauriConf from './tauriConf.js';
|
||||
import log from 'loglevel';
|
||||
import { mergeTauriConfig } from './common.js';
|
||||
import { npmDirectory } from '@/utils/dir.js';
|
||||
import logger from '@/options/logger.js';
|
||||
|
||||
export default class MacBuilder implements IBuilder {
|
||||
async prepare() {
|
||||
@@ -33,34 +36,32 @@ export default class MacBuilder implements IBuilder {
|
||||
|
||||
async build(url: string, options: PakeAppOptions) {
|
||||
log.debug('PakeAppOptions', options);
|
||||
const { name } = options;
|
||||
|
||||
const { width, height, fullscreen, transparent, resizable, identifier, name } = options;
|
||||
await mergeTauriConfig(url, options, tauriConf);
|
||||
|
||||
const tauriConfWindowOptions = {
|
||||
width,
|
||||
height,
|
||||
fullscreen,
|
||||
transparent,
|
||||
resizable,
|
||||
};
|
||||
|
||||
// TODO 下面这块逻辑还可以再拆 目前比较简单
|
||||
Object.assign(tauriConf.tauri.windows[0], { url, ...tauriConfWindowOptions });
|
||||
tauriConf.package.productName = name;
|
||||
tauriConf.tauri.bundle.identifier = identifier;
|
||||
tauriConf.tauri.bundle.icon = [options.icon];
|
||||
|
||||
const npmDirectory = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
const configJsonPath = path.join(npmDirectory, 'src-tauri/tauri.conf.json');
|
||||
await fs.writeFile(configJsonPath, Buffer.from(JSON.stringify(tauriConf), 'utf-8'));
|
||||
|
||||
const code = await shellExec(`cd ${npmDirectory} && npm run build`);
|
||||
const dmgName = `${name}_${tauriConf.package.version}_universal.dmg`;
|
||||
const _ = await shellExec(`cd ${npmDirectory} && npm install && npm run build`);
|
||||
let arch = "x64";
|
||||
if (process.arch === "arm64") {
|
||||
arch = "aarch64";
|
||||
} else {
|
||||
arch = process.arch;
|
||||
}
|
||||
const dmgName = `${name}_${tauriConf.package.version}_${arch}.dmg`;
|
||||
const appPath = this.getBuildedAppPath(npmDirectory, dmgName);
|
||||
await fs.copyFile(appPath, path.resolve(`${name}_universal.dmg`));
|
||||
const distPath = path.resolve(`${name}.dmg`);
|
||||
await fs.copyFile(appPath, distPath);
|
||||
await fs.unlink(appPath);
|
||||
|
||||
logger.success('Build success!');
|
||||
logger.success('You can find the app installer in', distPath);
|
||||
}
|
||||
|
||||
getBuildedAppPath(npmDirectory: string, dmgName: string) {
|
||||
return path.join(npmDirectory, 'src-tauri/target/universal-apple-darwin/release/bundle/dmg', dmgName);
|
||||
return path.join(
|
||||
npmDirectory,
|
||||
'src-tauri/target/release/bundle/dmg',
|
||||
dmgName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
69
bin/builders/WinBulider.ts
vendored
@@ -0,0 +1,69 @@
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import prompts from 'prompts';
|
||||
import { checkRustInstalled, installRust } from '@/helpers/rust.js';
|
||||
import { PakeAppOptions } from '@/types.js';
|
||||
import { IBuilder } from './base.js';
|
||||
import { shellExec } from '@/utils/shell.js';
|
||||
// @ts-expect-error 加上resolveJsonModule rollup会打包报错
|
||||
// import tauriConf from '../../src-tauri/tauri.windows.conf.json';
|
||||
import tauriConf from './tauriConf.js';
|
||||
|
||||
import { fileURLToPath } from 'url';
|
||||
import logger from '@/options/logger.js';
|
||||
import { mergeTauriConfig } from './common.js';
|
||||
import { npmDirectory } from '@/utils/dir.js';
|
||||
|
||||
export default class WinBuilder implements IBuilder {
|
||||
async prepare() {
|
||||
logger.info(
|
||||
'To build the Windows app, you need to install Rust and VS Build Tools.'
|
||||
);
|
||||
logger.info(
|
||||
'See more in https://tauri.app/v1/guides/getting-started/prerequisites#installing\n'
|
||||
);
|
||||
if (checkRustInstalled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await prompts({
|
||||
type: 'confirm',
|
||||
message: 'We detected that you have not installed Rust. Install it now?',
|
||||
name: 'value',
|
||||
});
|
||||
|
||||
if (res.value) {
|
||||
// TODO 国内有可能会超时
|
||||
await installRust();
|
||||
} else {
|
||||
logger.error('Error: Pake needs Rust to package your webapp!!!');
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
async build(url: string, options: PakeAppOptions) {
|
||||
logger.debug('PakeAppOptions', options);
|
||||
const { name } = options;
|
||||
|
||||
await mergeTauriConfig(url, options, tauriConf);
|
||||
|
||||
const _ = await shellExec(`cd ${npmDirectory} && npm install && npm run build`);
|
||||
const language = tauriConf.tauri.bundle.windows.wix.language[0];
|
||||
const arch = process.arch;
|
||||
const msiName = `${name}_${tauriConf.package.version}_${arch}_${language}.msi`;
|
||||
const appPath = this.getBuildedAppPath(npmDirectory, msiName);
|
||||
const distPath = path.resolve(`${name}.msi`);
|
||||
await fs.copyFile(appPath, distPath);
|
||||
await fs.unlink(appPath);
|
||||
logger.success('Build success!');
|
||||
logger.success('You can find the app installer in', distPath);
|
||||
}
|
||||
|
||||
getBuildedAppPath(npmDirectory: string, dmgName: string) {
|
||||
return path.join(
|
||||
npmDirectory,
|
||||
'src-tauri/target/release/bundle/msi',
|
||||
dmgName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
99
bin/builders/common.ts
vendored
@@ -1,4 +1,9 @@
|
||||
import { PakeAppOptions } from '@/types.js';
|
||||
import prompts from 'prompts';
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
import { npmDirectory } from '@/utils/dir.js';
|
||||
import logger from '@/options/logger.js';
|
||||
|
||||
export async function promptText(message: string, initial?: string) {
|
||||
const response = await prompts({
|
||||
@@ -9,3 +14,97 @@ export async function promptText(message: string, initial?: string) {
|
||||
});
|
||||
return response.content;
|
||||
}
|
||||
|
||||
export async function mergeTauriConfig(
|
||||
url: string,
|
||||
options: PakeAppOptions,
|
||||
tauriConf: any
|
||||
) {
|
||||
const {
|
||||
width,
|
||||
height,
|
||||
fullscreen,
|
||||
transparent,
|
||||
resizable,
|
||||
identifier,
|
||||
name,
|
||||
} = options;
|
||||
|
||||
const tauriConfWindowOptions = {
|
||||
width,
|
||||
height,
|
||||
fullscreen,
|
||||
transparent,
|
||||
resizable,
|
||||
};
|
||||
|
||||
Object.assign(tauriConf.tauri.windows[0], { url, ...tauriConfWindowOptions });
|
||||
tauriConf.package.productName = name;
|
||||
tauriConf.tauri.bundle.identifier = identifier;
|
||||
const exists = await fs.stat(options.icon)
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
if (exists) {
|
||||
let updateIconPath = true;
|
||||
let customIconExt = path.extname(options.icon).toLowerCase();
|
||||
if (process.platform === "win32") {
|
||||
if (customIconExt === ".ico") {
|
||||
const ico_path = path.join(npmDirectory, `src-tauri/png/${name.toLowerCase()}_32.ico`);
|
||||
tauriConf.tauri.bundle.resources = [`png/${name.toLowerCase()}_32.ico`];
|
||||
await fs.copyFile(options.icon, ico_path);
|
||||
} else {
|
||||
updateIconPath = false;
|
||||
logger.warn(`icon file in Windows must be 256 * 256 pix with .ico type, but you give ${customIconExt}`);
|
||||
}
|
||||
}
|
||||
if (process.platform === "linux") {
|
||||
delete tauriConf.tauri.bundle.deb.files;
|
||||
if (customIconExt != ".png") {
|
||||
updateIconPath = false;
|
||||
logger.warn(`icon file in Linux must be 512 * 512 pix with .png type, but you give ${customIconExt}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform === "darwin" && customIconExt !== ".icns") {
|
||||
updateIconPath = false;
|
||||
logger.warn(`icon file in MacOS must be .icns type, but you give ${customIconExt}`);
|
||||
}
|
||||
if (updateIconPath) {
|
||||
tauriConf.tauri.bundle.icon = [options.icon];
|
||||
} else {
|
||||
logger.warn(`icon file will not change with default.`);
|
||||
}
|
||||
} else {
|
||||
logger.warn("the custom icon path may not exists. we will use default icon to replace it");
|
||||
}
|
||||
|
||||
|
||||
let configPath = "";
|
||||
switch (process.platform) {
|
||||
case "win32": {
|
||||
configPath = path.join(npmDirectory, 'src-tauri/tauri.windows.conf.json');
|
||||
break;
|
||||
}
|
||||
case "darwin": {
|
||||
configPath = path.join(npmDirectory, 'src-tauri/tauri.macos.conf.json');
|
||||
break;
|
||||
}
|
||||
case "linux": {
|
||||
configPath = path.join(npmDirectory, 'src-tauri/tauri.linux.conf.json');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let bundleConf = {tauri: {bundle: tauriConf.tauri.bundle}};
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
Buffer.from(JSON.stringify(bundleConf), 'utf-8')
|
||||
);
|
||||
|
||||
|
||||
const configJsonPath = path.join(npmDirectory, 'src-tauri/tauri.conf.json')
|
||||
await fs.writeFile(
|
||||
configJsonPath,
|
||||
Buffer.from(JSON.stringify(tauriConf), 'utf-8')
|
||||
);
|
||||
}
|
||||
|
||||
27
bin/builders/tauriConf.js
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import CommonConf from '../../src-tauri/tauri.conf.json';
|
||||
import WinConf from '../../src-tauri/tauri.windows.conf.json';
|
||||
import MacConf from '../../src-tauri/tauri.macos.conf.json';
|
||||
import LinuxConf from '../../src-tauri/tauri.linux.conf.json';
|
||||
|
||||
let tauriConf = {
|
||||
package: CommonConf.package,
|
||||
tauri: CommonConf.tauri
|
||||
}
|
||||
switch (process.platform) {
|
||||
case "win32": {
|
||||
tauriConf.tauri.bundle = WinConf.tauri.bundle;
|
||||
break;
|
||||
}
|
||||
case "darwin": {
|
||||
tauriConf.tauri.bundle = MacConf.tauri.bundle;
|
||||
break;
|
||||
}
|
||||
case "linux": {
|
||||
tauriConf.tauri.bundle = LinuxConf.tauri.bundle;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export default tauriConf;
|
||||
|
||||
|
||||
20
bin/cli.ts
vendored
@@ -1,16 +1,21 @@
|
||||
import { program } from 'commander';
|
||||
import log from 'loglevel';
|
||||
import chalk from 'chalk';
|
||||
import { DEFAULT_PAKE_OPTIONS } from './defaults.js';
|
||||
import { PakeCliOptions } from './types.js';
|
||||
import { validateNumberInput, validateUrlInput } from './utils/validate.js';
|
||||
import handleInputOptions from './options/index.js';
|
||||
import BuilderFactory from './builders/BuilderFactory.js';
|
||||
import log from 'loglevel';
|
||||
import { checkUpdateTips } from './helpers/updater.js';
|
||||
// @ts-expect-error
|
||||
import packageJson from '../package.json';
|
||||
import logger from './options/logger.js';
|
||||
|
||||
program.version('0.0.1').description('A cli application can package a web page to desktop application');
|
||||
program.version(packageJson.version).description('A cli application can package a web page to desktop application.');
|
||||
|
||||
program
|
||||
.showHelpAfterError()
|
||||
.argument('<url>', 'the web url you want to package', validateUrlInput)
|
||||
.argument('[url]', 'the web url you want to package', validateUrlInput)
|
||||
.option('--name <string>', 'application name')
|
||||
.option('--icon <string>', 'application icon', DEFAULT_PAKE_OPTIONS.icon)
|
||||
.option('--height <number>', 'window height', validateNumberInput, DEFAULT_PAKE_OPTIONS.height)
|
||||
@@ -20,7 +25,14 @@ program
|
||||
.option('--transparent', 'transparent title bar', DEFAULT_PAKE_OPTIONS.transparent)
|
||||
.option('--debug', 'debug', DEFAULT_PAKE_OPTIONS.transparent)
|
||||
.action(async (url: string, options: PakeCliOptions) => {
|
||||
log.setDefaultLevel('info')
|
||||
checkUpdateTips();
|
||||
|
||||
if (!url) {
|
||||
// 直接 pake 不需要出现url提示
|
||||
program.help();
|
||||
}
|
||||
|
||||
log.setDefaultLevel('info');
|
||||
if (options.debug) {
|
||||
log.setLevel('debug');
|
||||
}
|
||||
|
||||
4
bin/defaults.ts
vendored
@@ -2,8 +2,8 @@ import { PakeCliOptions } from './types.js';
|
||||
|
||||
export const DEFAULT_PAKE_OPTIONS: PakeCliOptions = {
|
||||
icon: '',
|
||||
height: 800,
|
||||
width: 1280,
|
||||
height: 780,
|
||||
width: 1200,
|
||||
fullscreen: false,
|
||||
resizable: true,
|
||||
transparent: false,
|
||||
|
||||
8
bin/helpers/rust.ts
vendored
@@ -1,12 +1,16 @@
|
||||
import { IS_WIN } from '@/utils/platform.js';
|
||||
import ora from 'ora';
|
||||
import shelljs from 'shelljs';
|
||||
import { shellExec } from '../utils/shell.js';
|
||||
|
||||
const InstallRustScript = "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y";
|
||||
const RustInstallScriptFocMac =
|
||||
"curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y";
|
||||
const RustInstallScriptForWin = 'winget install --id Rustlang.Rustup';
|
||||
|
||||
export async function installRust() {
|
||||
const spinner = ora('Downloading Rust').start();
|
||||
try {
|
||||
await shellExec(InstallRustScript);
|
||||
await shellExec(IS_WIN ? RustInstallScriptForWin : RustInstallScriptFocMac);
|
||||
spinner.succeed();
|
||||
} catch (error) {
|
||||
console.error('install rust return code', error.message);
|
||||
|
||||
7
bin/helpers/updater.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
import updateNotifier from 'update-notifier';
|
||||
// @ts-expect-error
|
||||
import packageJson from '../../package.json';
|
||||
|
||||
export async function checkUpdateTips() {
|
||||
updateNotifier({ pkg: packageJson }).notify();
|
||||
}
|
||||
21
bin/options/icon.ts
vendored
@@ -4,8 +4,9 @@ import { PakeAppOptions } from '../types.js';
|
||||
import { dir } from 'tmp-promise';
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
import { fileURLToPath } from 'url';
|
||||
import log from 'loglevel';
|
||||
import logger from './logger.js';
|
||||
import { npmDirectory } from '@/utils/dir.js';
|
||||
import { IS_LINUX, IS_WIN } from '@/utils/platform.js';
|
||||
|
||||
export async function handleIcon(options: PakeAppOptions, url: string) {
|
||||
if (options.icon) {
|
||||
@@ -16,14 +17,20 @@ export async function handleIcon(options: PakeAppOptions, url: string) {
|
||||
}
|
||||
}
|
||||
if (!options.icon) {
|
||||
return inferIcon(options.name, url);
|
||||
return getDefaultIcon();
|
||||
}
|
||||
}
|
||||
|
||||
export async function inferIcon(name: string, url: string) {
|
||||
log.info('You have not provided an app icon, use the default icon(can use --icon option to assign an icon)')
|
||||
const npmDirectory = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
||||
return path.join(npmDirectory, 'pake-default.icns');
|
||||
export async function getDefaultIcon() {
|
||||
logger.info('You have not provided an app icon, use the default icon.(use --icon option to assign an icon)')
|
||||
let iconPath = 'src-tauri/icons/icon.icns';
|
||||
if (IS_WIN) {
|
||||
iconPath = 'src-tauri/png/icon_256.ico';
|
||||
} else if (IS_LINUX) {
|
||||
iconPath = 'src-tauri/png/icon_512.png';
|
||||
}
|
||||
|
||||
return path.join(npmDirectory, iconPath);
|
||||
}
|
||||
|
||||
// export async function getIconFromPageUrl(url: string) {
|
||||
|
||||
22
bin/options/logger.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
import log from 'loglevel';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const logger = {
|
||||
info(...msg: any[]) {
|
||||
log.info(...msg.map((m) => chalk.blue.bold(m)));
|
||||
},
|
||||
debug(...msg: any[]) {
|
||||
log.debug(...msg);
|
||||
},
|
||||
error(...msg: any[]) {
|
||||
log.error(...msg.map((m) => chalk.red.bold(m)));
|
||||
},
|
||||
warn(...msg: any[]) {
|
||||
log.info(...msg.map((m) => chalk.yellow.bold(m)));
|
||||
},
|
||||
success(...msg: any[]) {
|
||||
log.info(...msg.map((m) => chalk.green.bold(m)));
|
||||
}
|
||||
};
|
||||
|
||||
export default logger;
|
||||
4
bin/types.ts
vendored
@@ -5,10 +5,10 @@ export interface PakeCliOptions {
|
||||
/** 应用icon */
|
||||
icon: string;
|
||||
|
||||
/** 应用窗口宽度,默认 1280px */
|
||||
/** 应用窗口宽度,默认 1200px */
|
||||
width: number;
|
||||
|
||||
/** 应用窗口高度,默认 800px */
|
||||
/** 应用窗口高度,默认 780px */
|
||||
height: number;
|
||||
|
||||
/** 是否可以拖动,默认true */
|
||||
|
||||
8
bin/utils/dir.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
|
||||
export const npmDirectory = path.join(
|
||||
path.dirname(fileURLToPath(import.meta.url)),
|
||||
'..'
|
||||
);
|
||||
16
dist/about_pake.html
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Document</title>
|
||||
</head>
|
||||
<body>
|
||||
<h5>Welcome from Pake!</h5>
|
||||
<p>version: 1.0.1</p>
|
||||
<a href="https://github.com/tw93/Pake" target="_blank">Project link</a><br>
|
||||
<a href="https://github.com/tw93/Pake/discussions" target="_blank">Discussions</a><br>
|
||||
<a href="https://github.com/tw93/Pake/issues" target="_blank">Issues</a><br>
|
||||
<p>LICENSE: MIT</p>
|
||||
</body>
|
||||
</html>
|
||||
2302
dist/cli.js
vendored
Normal file
34
package.json
@@ -1,7 +1,10 @@
|
||||
{
|
||||
"name": "pake-cli",
|
||||
"version": "0.0.6",
|
||||
"version": "1.0.1",
|
||||
"description": "🤱🏻 很简单的用 Rust 打包网页生成很小的桌面 App 🤱🏻 A simple way to make any web page a desktop application using Rust.",
|
||||
"engines": {
|
||||
"node": "^14.13 || >=16.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"pake": "./cli.js"
|
||||
},
|
||||
@@ -13,33 +16,40 @@
|
||||
"name": "Tw93",
|
||||
"email": "tw93@qq.com"
|
||||
},
|
||||
"keywords": [
|
||||
"pake",
|
||||
"pake-cli",
|
||||
"rust",
|
||||
"tauri",
|
||||
"no-electron",
|
||||
"productivity"
|
||||
],
|
||||
"files": [
|
||||
"dist",
|
||||
"src-tauri",
|
||||
"cli.js",
|
||||
"pake-default.icns"
|
||||
"cli.js"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "npm run dev",
|
||||
"dev": "npm run tauri dev",
|
||||
"dev:debug": "npm run tauri dev -- --features devtools",
|
||||
"build": "npm run tauri build -- --target universal-apple-darwin",
|
||||
"build:windows": "npm run tauri build -- --target x86_64-pc-windows-msvc",
|
||||
"build:linux": "npm run tauri build --release",
|
||||
"build:all-unix":"chmod +x ./script/build.sh && ./script/build.sh",
|
||||
"build": "npm run tauri build --release",
|
||||
"build:mac": "npm run tauri build -- --target universal-apple-darwin",
|
||||
"build:all-unix": "chmod +x ./script/build.sh && ./script/build.sh",
|
||||
"build:all-windows": ".\\script\\build.bat",
|
||||
"tauri": "tauri",
|
||||
"cli": "rollup -c rollup.config.js --watch",
|
||||
"cli:build": "cross-env NODE_ENV=production rollup -c rollup.config.js",
|
||||
"cli:publish": "npm run cli:build && npm publish"
|
||||
"prepublishOnly": "npm run cli:build"
|
||||
},
|
||||
"type": "module",
|
||||
"exports": "./dist/pake.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^1.2.0",
|
||||
"@tauri-apps/cli": "^1.2.1",
|
||||
"@tauri-apps/cli": "^1.2.2",
|
||||
"axios": "^1.1.3",
|
||||
"chalk": "^5.1.2",
|
||||
"commander": "^9.4.1",
|
||||
"file-type": "^18.0.0",
|
||||
"is-url": "^1.2.4",
|
||||
@@ -47,7 +57,8 @@
|
||||
"ora": "^6.1.2",
|
||||
"prompts": "^2.4.2",
|
||||
"shelljs": "^0.8.5",
|
||||
"tmp-promise": "^3.0.3"
|
||||
"tmp-promise": "^3.0.3",
|
||||
"update-notifier": "^6.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-alias": "^4.0.2",
|
||||
@@ -60,11 +71,12 @@
|
||||
"@types/prompts": "^2.4.1",
|
||||
"@types/shelljs": "^0.8.11",
|
||||
"@types/tmp": "^0.2.3",
|
||||
"@types/update-notifier": "^6.0.1",
|
||||
"app-root-path": "^3.1.0",
|
||||
"concurrently": "^7.5.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"rollup": "^3.3.0",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^4.8.4"
|
||||
"typescript": "^4.9.3"
|
||||
}
|
||||
}
|
||||
|
||||
4
rollup.config.js
vendored
@@ -4,9 +4,6 @@ import typescript from '@rollup/plugin-typescript';
|
||||
import alias from '@rollup/plugin-alias';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import json from '@rollup/plugin-json';
|
||||
import terser from '@rollup/plugin-terser';
|
||||
|
||||
const isDev = process.env.NODE_ENV !== "production";
|
||||
|
||||
export default {
|
||||
input: 'bin/cli.ts',
|
||||
@@ -23,6 +20,5 @@ export default {
|
||||
alias({
|
||||
entries: [{ find: '@', replacement: path.join(appRootPath.path, 'bin') }],
|
||||
}),
|
||||
!isDev && terser(),
|
||||
],
|
||||
};
|
||||
|
||||
21
script/build.bat
vendored
@@ -31,8 +31,14 @@ set old_title=WeRead
|
||||
set old_zh_name=微信阅读
|
||||
set old_url=https://weread.qq.com/
|
||||
|
||||
:: set init name, we will recovery code to init when build finish.
|
||||
set init_name=%old_name%
|
||||
set init_title=%old_title%
|
||||
set init_zh_name=%old_zh_name%
|
||||
set init_url=%old_url%
|
||||
|
||||
:: for windows, we need replace package name to title
|
||||
.\script\sd.exe "\"productName\": \"weread\"" "\"productName\": \"WeRead\"" src-tauri\tauri.conf.json
|
||||
:: .\script\sd.exe "\"productName\": \"weread\"" "\"productName\": \"WeRead\"" src-tauri\tauri.conf.json
|
||||
|
||||
for /f "skip=1 tokens=1-4 delims=," %%i in (app.csv) do (
|
||||
setlocal enabledelayedexpansion
|
||||
@@ -44,13 +50,11 @@ for /f "skip=1 tokens=1-4 delims=," %%i in (app.csv) do (
|
||||
|
||||
::echo name is !name! !name_zh! !url!
|
||||
:: replace url
|
||||
.\script\sd.exe !old_url! !url! src-tauri\tauri.conf.json
|
||||
.\script\sd.exe -s !old_url! !url! src-tauri\tauri.conf.json
|
||||
::replace pacakge name
|
||||
.\script\sd.exe !old_title! !title! src-tauri\tauri.conf.json
|
||||
.\script\sd.exe !old_name! !name! src-tauri\tauri.conf.json
|
||||
echo update ico with 32x32 pictue
|
||||
.\script\sd.exe !old_name! !name! src-tauri\src\main.rs
|
||||
::copy src-tauri\png\!name!_32.ico src-tauri\icons\icon.ico
|
||||
.\script\sd.exe !old_name! !name! src-tauri\tauri.windows.conf.json
|
||||
|
||||
echo.
|
||||
::update package info
|
||||
set old_zh_name=!name_zh!
|
||||
@@ -86,3 +90,8 @@ for /f "skip=1 tokens=1-4 delims=," %%i in (app.csv) do (
|
||||
:: for windows, we need replace package name to lower again
|
||||
:: .\script\sd.exe "\"productName\": \"WeRead\"" "\"productName\": \"weread\"" src-tauri\tauri.conf.json
|
||||
echo "output dir is output\windows"
|
||||
|
||||
::recovery code
|
||||
.\script\sd.exe %url% %init_url% src-tauri\tauri.conf.json
|
||||
.\script\sd.exe %title% %init_title% src-tauri\tauri.conf.json
|
||||
.\script\sd.exe %name% %init_name% src-tauri\tauri.windows.conf.json
|
||||
36
script/build.sh
vendored
@@ -28,11 +28,13 @@ total=$(sed -n '$=' app.csv)
|
||||
export total=$((total-1))
|
||||
export index=1
|
||||
|
||||
old_name="weread"
|
||||
old_title="WeRead"
|
||||
old_zh_name="微信阅读"
|
||||
old_url="https://weread.qq.com/"
|
||||
package_prefix="com-tw93"
|
||||
export old_name="weread"
|
||||
export old_title="WeRead"
|
||||
export old_zh_name="微信阅读"
|
||||
export old_url="https://weread.qq.com/"
|
||||
export package_prefix="com-tw93"
|
||||
|
||||
|
||||
|
||||
if [[ "$OSTYPE" =~ ^linux ]]; then
|
||||
echo "==============="
|
||||
@@ -64,15 +66,15 @@ do
|
||||
package_title=${arr[1]}
|
||||
package_zh_name=${arr[2]}
|
||||
url=${arr[3]}
|
||||
echo "update package name and url"
|
||||
# replace package info
|
||||
$sd "${old_url}" "${url}" src-tauri/tauri.conf.json
|
||||
$sd -s "${old_url}" "${url}" src-tauri/tauri.conf.json
|
||||
$sd "${old_name}" "${package_name}" src-tauri/tauri.conf.json
|
||||
echo "update ico with 32x32 pictue"
|
||||
$sd "${old_name}" "${package_name}" src-tauri/src/main.rs
|
||||
# echo "update ico with 32x32 pictue"
|
||||
# $sd "${old_name}" "${package_name}" src-tauri/src/main.rs
|
||||
|
||||
# for apple, need replace title
|
||||
if [[ "$OSTYPE" =~ ^darwin ]]; then
|
||||
$sd "${old_name}" "${package_name}" src-tauri/tauri.macos.conf.json
|
||||
$sd "${old_title}" "${package_title}" src-tauri/tauri.conf.json
|
||||
fi
|
||||
|
||||
@@ -80,6 +82,7 @@ do
|
||||
# cp "src-tauri/png/${package_name}_32.ico" "src-tauri/icons/icon.ico"
|
||||
|
||||
if [[ "$OSTYPE" =~ ^linux ]]; then
|
||||
$sd "${old_name}" "${package_name}" src-tauri/tauri.linux.conf.json
|
||||
echo "update desktop"
|
||||
old_desktop="src-tauri/assets/${package_prefix}-${old_name}.desktop"
|
||||
new_desktop="src-tauri/assets/${package_prefix}-${package_name}.desktop"
|
||||
@@ -99,7 +102,8 @@ do
|
||||
|
||||
if [[ "$OSTYPE" =~ ^linux ]]; then
|
||||
npm run tauri build
|
||||
mv src-tauri/target/release/bundle/deb/*.deb output/linux/${package_title}_amd64.deb
|
||||
mv src-tauri/target/release/bundle/deb/${package_prefix}-${package_name}*.deb output/linux/${package_title}_amd64.deb
|
||||
mv src-tauri/target/release/bundle/appimage/${package_prefix}-${package_name}*.AppImage output/linux/${package_title}_amd64.AppImage
|
||||
fi
|
||||
|
||||
if [[ "$OSTYPE" =~ ^darwin ]]; then
|
||||
@@ -114,13 +118,5 @@ do
|
||||
done
|
||||
|
||||
echo "build all package success!"
|
||||
if [[ "$OSTYPE" =~ ^linux ]]; then
|
||||
$sd "\"productName\": \"com-tw93-weread\"" "\"productName\": \"WeRead\"" src-tauri/tauri.conf.json
|
||||
echo "result file in output/linux"
|
||||
fi
|
||||
|
||||
if [[ "$OSTYPE" =~ ^darwin ]]; then
|
||||
# replace again
|
||||
$sd "\"productName\": \"weread\"" "\"productName\": \"WeRead\"" src-tauri/tauri.conf.json
|
||||
echo "result file in output/macos"
|
||||
fi
|
||||
echo "you run 'rm src-tauri/assets/*.desktop && git checkout src-tauri' to recovery code"
|
||||
# rm src-tauri/assets/*.desktop && git checkout src-tauri
|
||||
|
||||
735
src-tauri/Cargo.lock
generated
@@ -15,13 +15,16 @@ rust-version = "1.61.0"
|
||||
tauri-build = { version = "1.2.1", features = [] }
|
||||
|
||||
[dependencies]
|
||||
serde_json = "1.0.88"
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
tauri = { version = "1.2.1", features = ["api-all"] }
|
||||
serde_json = "1.0.89"
|
||||
serde = { version = "1.0.150", features = ["derive"] }
|
||||
tauri = { version = "1.2.2", features = ["system-tray"] }
|
||||
image = "0.24.5"
|
||||
home = "0.5"
|
||||
tauri-utils = "1.2.1"
|
||||
webbrowser = "0.8.2"
|
||||
wry = "0.21.1"
|
||||
tauri-plugin-window-state = { git = "https://github.com/tauri-apps/tauri-plugin-window-state", branch = "dev"}
|
||||
webkit2gtk = "0.18.0"
|
||||
# webbrowser = "0.8.2"
|
||||
# wry = "0.23.4"
|
||||
|
||||
[features]
|
||||
# by default Tauri runs in production mode
|
||||
|
||||
310
src-tauri/assets/main.wxs
Normal file
@@ -0,0 +1,310 @@
|
||||
<?if $(sys.BUILDARCH)="x86"?>
|
||||
<?define Win64 = "no" ?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
|
||||
<?elseif $(sys.BUILDARCH)="x64"?>
|
||||
<?define Win64 = "yes" ?>
|
||||
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
|
||||
<?else?>
|
||||
<?error Unsupported value of sys.BUILDARCH=$(sys.BUILDARCH)?>
|
||||
<?endif?>
|
||||
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||
<Product
|
||||
Id="*"
|
||||
Name="{{{product_name}}}"
|
||||
UpgradeCode="{{{upgrade_code}}}"
|
||||
Language="!(loc.TauriLanguage)"
|
||||
Manufacturer="{{{manufacturer}}}"
|
||||
Version="{{{version}}}">
|
||||
|
||||
<Package Id="*"
|
||||
Keywords="Installer"
|
||||
InstallerVersion="450"
|
||||
Languages="0"
|
||||
Compressed="yes"
|
||||
InstallScope="perMachine"
|
||||
SummaryCodepage="!(loc.TauriCodepage)"/>
|
||||
|
||||
<!-- https://docs.microsoft.com/en-us/windows/win32/msi/reinstallmode -->
|
||||
<!-- reinstall all files; rewrite all registry entries; reinstall all shortcuts -->
|
||||
<Property Id="REINSTALLMODE" Value="amus" />
|
||||
|
||||
{{#if allow_downgrades}}
|
||||
<MajorUpgrade Schedule="afterInstallInitialize" AllowDowngrades="yes" />
|
||||
{{else}}
|
||||
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="!(loc.DowngradeErrorMessage)" AllowSameVersionUpgrades="yes" />
|
||||
{{/if}}
|
||||
|
||||
<InstallExecuteSequence>
|
||||
<RemoveShortcuts>Installed AND NOT UPGRADINGPRODUCTCODE</RemoveShortcuts>
|
||||
</InstallExecuteSequence>
|
||||
|
||||
<Media Id="1" Cabinet="app.cab" EmbedCab="yes" />
|
||||
|
||||
{{#if banner_path}}
|
||||
<WixVariable Id="WixUIBannerBmp" Value="{{{banner_path}}}" />
|
||||
{{/if}}
|
||||
{{#if dialog_image_path}}
|
||||
<WixVariable Id="WixUIDialogBmp" Value="{{{dialog_image_path}}}" />
|
||||
{{/if}}
|
||||
{{#if license}}
|
||||
<WixVariable Id="WixUILicenseRtf" Value="{{{license}}}" />
|
||||
{{/if}}
|
||||
|
||||
<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"/>
|
||||
|
||||
<!-- initialize with previous InstallDir -->
|
||||
<Property Id="INSTALLDIR">
|
||||
<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" />
|
||||
|
||||
<UI>
|
||||
<!-- launch app checkbox -->
|
||||
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
|
||||
|
||||
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
|
||||
|
||||
{{#unless license}}
|
||||
<!-- Skip license dialog -->
|
||||
<Publish Dialog="WelcomeDlg"
|
||||
Control="Next"
|
||||
Event="NewDialog"
|
||||
Value="InstallDirDlg"
|
||||
Order="2">1</Publish>
|
||||
<Publish Dialog="InstallDirDlg"
|
||||
Control="Back"
|
||||
Event="NewDialog"
|
||||
Value="WelcomeDlg"
|
||||
Order="2">1</Publish>
|
||||
{{/unless}}
|
||||
</UI>
|
||||
|
||||
<UIRef Id="WixUI_InstallDir" />
|
||||
|
||||
<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" />
|
||||
<RemoveFolder Id="DesktopFolder" On="uninstall" />
|
||||
<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>
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="{{{product_name}}}"/>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<DirectoryRef Id="INSTALLDIR">
|
||||
<Component Id="RegistryEntries" Guid="*">
|
||||
<RegistryKey Root="HKCU" Key="Software\\{{{manufacturer}}}\\{{{product_name}}}">
|
||||
<RegistryValue Name="InstallDir" Type="string" Value="[INSTALLDIR]" KeyPath="yes" />
|
||||
</RegistryKey>
|
||||
</Component>
|
||||
<Component Id="Path" Guid="{{{path_component_guid}}}" Win64="$(var.Win64)">
|
||||
<File Id="Path" Source="{{{app_exe_source}}}" KeyPath="yes" Checksum="yes"/>
|
||||
</Component>
|
||||
{{#each binaries as |bin| ~}}
|
||||
<Component Id="{{ bin.id }}" Guid="{{bin.guid}}" Win64="$(var.Win64)">
|
||||
<File Id="Bin_{{ bin.id }}" Source="{{bin.path}}" KeyPath="yes"/>
|
||||
</Component>
|
||||
{{/each~}}
|
||||
{{#if enable_elevated_update_task}}
|
||||
<Component Id="UpdateTask" Guid="C492327D-9720-4CD5-8DB8-F09082AF44BE" Win64="$(var.Win64)">
|
||||
<File Id="UpdateTask" Source="update.xml" KeyPath="yes" Checksum="yes"/>
|
||||
</Component>
|
||||
<Component Id="UpdateTaskInstaller" Guid="011F25ED-9BE3-50A7-9E9B-3519ED2B9932" Win64="$(var.Win64)">
|
||||
<File Id="UpdateTaskInstaller" Source="install-task.ps1" KeyPath="yes" Checksum="yes"/>
|
||||
</Component>
|
||||
<Component Id="UpdateTaskUninstaller" Guid="D4F6CC3F-32DC-5FD0-95E8-782FFD7BBCE1" Win64="$(var.Win64)">
|
||||
<File Id="UpdateTaskUninstaller" Source="uninstall-task.ps1" KeyPath="yes" Checksum="yes"/>
|
||||
</Component>
|
||||
{{/if}}
|
||||
{{{resources}}}
|
||||
<Component Id="CMP_UninstallShortcut" Guid="*">
|
||||
|
||||
<Shortcut Id="UninstallShortcut"
|
||||
Name="Uninstall {{{product_name}}}"
|
||||
Description="Uninstalls {{{product_name}}}"
|
||||
Target="[System64Folder]msiexec.exe"
|
||||
Arguments="/x [ProductCode]" />
|
||||
|
||||
<RemoveFolder Id="INSTALLDIR"
|
||||
On="uninstall" />
|
||||
|
||||
<RegistryValue Root="HKCU"
|
||||
Key="Software\\{{{manufacturer}}}\\{{{product_name}}}"
|
||||
Name="Uninstaller Shortcut"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||
<Component Id="ApplicationShortcut" Guid="*">
|
||||
<Shortcut Id="ApplicationStartMenuShortcut"
|
||||
Name="{{{product_name}}}"
|
||||
Description="Runs {{{product_name}}}"
|
||||
Target="[!Path]"
|
||||
Icon="ProductIcon"
|
||||
WorkingDirectory="INSTALLDIR">
|
||||
<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"/>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
{{#each merge_modules as |msm| ~}}
|
||||
<DirectoryRef Id="TARGETDIR">
|
||||
<Merge Id="{{ msm.name }}" SourceFile="{{ msm.path }}" DiskId="1" Language="!(loc.TauriLanguage)" />
|
||||
</DirectoryRef>
|
||||
|
||||
<Feature Id="{{ msm.name }}" Title="{{ msm.name }}" AllowAdvertise="no" Display="hidden" Level="1">
|
||||
<MergeRef Id="{{ msm.name }}"/>
|
||||
</Feature>
|
||||
{{/each~}}
|
||||
|
||||
<Feature
|
||||
Id="MainProgram"
|
||||
Title="Application"
|
||||
Description="!(loc.InstallAppFeature)"
|
||||
Level="1"
|
||||
ConfigurableDirectory="INSTALLDIR"
|
||||
AllowAdvertise="no"
|
||||
Display="expand"
|
||||
Absent="disallow">
|
||||
|
||||
<ComponentRef Id="RegistryEntries"/>
|
||||
|
||||
{{#each resource_file_ids as |resource_file_id| ~}}
|
||||
<ComponentRef Id="{{ resource_file_id }}"/>
|
||||
{{/each~}}
|
||||
|
||||
{{#if enable_elevated_update_task}}
|
||||
<ComponentRef Id="UpdateTask" />
|
||||
<ComponentRef Id="UpdateTaskInstaller" />
|
||||
<ComponentRef Id="UpdateTaskUninstaller" />
|
||||
{{/if}}
|
||||
|
||||
<Feature Id="ShortcutsFeature"
|
||||
Title="Shortcuts"
|
||||
Level="1">
|
||||
<ComponentRef Id="Path"/>
|
||||
<ComponentRef Id="CMP_UninstallShortcut" />
|
||||
<ComponentRef Id="ApplicationShortcut" />
|
||||
<ComponentRef Id="ApplicationShortcutDesktop" />
|
||||
</Feature>
|
||||
|
||||
<Feature
|
||||
Id="Environment"
|
||||
Title="PATH Environment Variable"
|
||||
Description="!(loc.PathEnvVarFeature)"
|
||||
Level="1"
|
||||
Absent="allow">
|
||||
<ComponentRef Id="Path"/>
|
||||
{{#each binaries as |bin| ~}}
|
||||
<ComponentRef Id="{{ bin.id }}"/>
|
||||
{{/each~}}
|
||||
</Feature>
|
||||
</Feature>
|
||||
|
||||
<Feature Id="External" AllowAdvertise="no" Absent="disallow">
|
||||
{{#each component_group_refs as |id| ~}}
|
||||
<ComponentGroupRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
{{#each component_refs as |id| ~}}
|
||||
<ComponentRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
{{#each feature_group_refs as |id| ~}}
|
||||
<FeatureGroupRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
{{#each feature_refs as |id| ~}}
|
||||
<FeatureRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
{{#each merge_refs as |id| ~}}
|
||||
<MergeRef Id="{{ id }}"/>
|
||||
{{/each~}}
|
||||
</Feature>
|
||||
|
||||
{{#if install_webview}}
|
||||
<!-- WebView2 -->
|
||||
<Property Id="WVRTINSTALLED">
|
||||
<RegistrySearch Id="WVRTInstalledSystem" Root="HKLM" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw" Win64="no" />
|
||||
<RegistrySearch Id="WVRTInstalledUser" Root="HKCU" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw"/>
|
||||
</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}}} '/install') -Wait' Return='check'/>
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='DownloadAndInvokeBootstrapper' Before='InstallFinalize'>
|
||||
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
{{/if}}
|
||||
|
||||
<!-- 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' />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='InvokeBootstrapper' Before='InstallFinalize'>
|
||||
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
{{/if}}
|
||||
|
||||
<!-- 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' />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='InvokeStandalone' Before='InstallFinalize'>
|
||||
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
{{/if}}
|
||||
|
||||
{{/if}}
|
||||
|
||||
{{#if enable_elevated_update_task}}
|
||||
<!-- Install an elevated update task within Windows Task Scheduler -->
|
||||
<CustomAction
|
||||
Id="CreateUpdateTask"
|
||||
Return="check"
|
||||
Directory="INSTALLDIR"
|
||||
Execute="commit"
|
||||
Impersonate="yes"
|
||||
ExeCommand="powershell.exe -WindowStyle hidden .\install-task.ps1" />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action='CreateUpdateTask' Before='InstallFinalize'>
|
||||
NOT(REMOVE)
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
<!-- Remove elevated update task during uninstall -->
|
||||
<CustomAction
|
||||
Id="DeleteUpdateTask"
|
||||
Return="check"
|
||||
Directory="INSTALLDIR"
|
||||
ExeCommand="powershell.exe -WindowStyle hidden .\uninstall-task.ps1" />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="DeleteUpdateTask" Before='InstallFinalize'>
|
||||
(REMOVE = "ALL") AND NOT UPGRADINGPRODUCTCODE
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
{{/if}}
|
||||
|
||||
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize"/>
|
||||
</Product>
|
||||
</Wix>
|
||||
BIN
src-tauri/icons/chatgpt.icns
Normal file
BIN
src-tauri/icons/lizhi.icns
Normal file
BIN
src-tauri/icons/qwerty.icns
Normal file
18
src-tauri/pake.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"windows": [
|
||||
{
|
||||
"url": "https://weread.qq.com/",
|
||||
"transparent": true,
|
||||
"fullscreen": false,
|
||||
"width": 1200,
|
||||
"height": 780,
|
||||
"resizable": true,
|
||||
"url_type": "web"
|
||||
}
|
||||
],
|
||||
"user_agent": {
|
||||
"macos": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15",
|
||||
"linux": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36",
|
||||
"windows": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
|
||||
}
|
||||
}
|
||||
BIN
src-tauri/png/chatgpt_256.ico
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
src-tauri/png/chatgpt_32.ico
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src-tauri/png/chatgpt_512.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
src-tauri/png/icon_256.ico
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
src-tauri/png/icon_32.ico
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src-tauri/png/icon_512.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
src-tauri/png/lizhi_256.ico
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
src-tauri/png/lizhi_32.ico
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
src-tauri/png/lizhi_512.png
Normal file
|
After Width: | Height: | Size: 287 KiB |
BIN
src-tauri/png/qwerty_256.ico
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
src-tauri/png/qwerty_32.ico
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
src-tauri/png/qwerty_512.png
Normal file
|
After Width: | Height: | Size: 149 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 91 KiB |
0
src-tauri/src/lib.rs
Normal file
@@ -1,258 +1,349 @@
|
||||
// at the top of main.rs - that will prevent the console from showing
|
||||
#![windows_subsystem = "windows"]
|
||||
extern crate image;
|
||||
use tauri_utils::config::{Config, WindowConfig};
|
||||
#![cfg_attr(
|
||||
all(not(debug_assertions), target_os = "windows"),
|
||||
windows_subsystem = "windows"
|
||||
)]
|
||||
#[cfg(target_os = "macos")]
|
||||
use wry::application::platform::macos::WindowBuilderExtMacOS;
|
||||
use tauri::MenuItem;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use wry::{
|
||||
application::{
|
||||
accelerator::{Accelerator, SysMods},
|
||||
event::{Event, StartCause, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
keyboard::KeyCode,
|
||||
menu::{MenuBar as Menu, MenuItem, MenuItemAttributes, MenuType},
|
||||
window::{Fullscreen, Window, WindowBuilder},
|
||||
},
|
||||
webview::WebViewBuilder,
|
||||
use tauri::{
|
||||
CustomMenuItem, Menu, Submenu, WindowBuilder, App, Config,
|
||||
Window, WindowUrl, WindowMenuEvent, window::PlatformWebview,
|
||||
SystemTrayMenu, SystemTray, SystemTrayEvent, Manager
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use wry::{
|
||||
application::{
|
||||
event::{Event, StartCause, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
menu::MenuType,
|
||||
window::{Fullscreen, Icon, Window, WindowBuilder},
|
||||
},
|
||||
webview::WebViewBuilder,
|
||||
};
|
||||
// use tauri::Config;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use wry::{
|
||||
application::{
|
||||
event::{Event, StartCause, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
menu::MenuType,
|
||||
window::{Fullscreen, Window, WindowBuilder},
|
||||
},
|
||||
webview::{WebContext, WebViewBuilder},
|
||||
};
|
||||
pub mod pake {
|
||||
use serde::Deserialize;
|
||||
|
||||
fn main() -> wry::Result<()> {
|
||||
#[cfg(target_os = "macos")]
|
||||
let mut menu_bar_menu = Menu::new();
|
||||
#[cfg(target_os = "macos")]
|
||||
let mut first_menu = Menu::new();
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Hide);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::EnterFullScreen);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Minimize);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Separator);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Copy);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Cut);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Paste);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Undo);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Redo);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::SelectAll);
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Separator);
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct WindowConfig {
|
||||
pub url: String,
|
||||
pub transparent: bool,
|
||||
pub fullscreen: bool,
|
||||
pub width: f64,
|
||||
pub height: f64,
|
||||
pub resizable: bool,
|
||||
pub url_type: String
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let close_item = first_menu.add_item(
|
||||
MenuItemAttributes::new("CloseWindow")
|
||||
.with_accelerators(&Accelerator::new(SysMods::Cmd, KeyCode::KeyW)),
|
||||
);
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
first_menu.add_native_item(MenuItem::Quit);
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct UserAgent {
|
||||
pub macos: String,
|
||||
pub linux: String,
|
||||
pub windows: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct PakeConfig {
|
||||
pub windows: Vec<WindowConfig>,
|
||||
pub user_agent: UserAgent,
|
||||
}
|
||||
}
|
||||
|
||||
use pake::PakeConfig;
|
||||
|
||||
pub fn get_pake_config() -> (PakeConfig, Config){
|
||||
let pake_config_path = include_str!("../pake.json");
|
||||
let pake_config: PakeConfig = serde_json::from_str(pake_config_path)
|
||||
.expect("failed to parse pake config");
|
||||
// println!("{:#?}", config);
|
||||
let tauri_config_path = include_str!("../tauri.conf.json");
|
||||
let tauri_config: Config = serde_json::from_str(tauri_config_path)
|
||||
.expect("failed to parse tauri config");
|
||||
(pake_config, tauri_config)
|
||||
}
|
||||
|
||||
|
||||
pub fn get_menu() -> Menu {
|
||||
// first menu
|
||||
let hide = CustomMenuItem::new("hide", "Hide");
|
||||
let close = CustomMenuItem::new("close", "Close");
|
||||
let quit = CustomMenuItem::new("quit", "Quit");
|
||||
#[cfg(target_os = "macos")]
|
||||
menu_bar_menu.add_submenu("App", true, first_menu);
|
||||
let first_menu = Menu::new()
|
||||
.add_native_item(MenuItem::EnterFullScreen)
|
||||
.add_native_item(MenuItem::Minimize)
|
||||
.add_native_item(MenuItem::Separator)
|
||||
.add_native_item(MenuItem::Copy)
|
||||
.add_native_item(MenuItem::Cut)
|
||||
.add_native_item(MenuItem::Paste)
|
||||
.add_native_item(MenuItem::Undo)
|
||||
.add_native_item(MenuItem::Redo)
|
||||
.add_native_item(MenuItem::SelectAll)
|
||||
.add_native_item(MenuItem::Separator)
|
||||
.add_item(debug)
|
||||
.add_item(hide)
|
||||
.add_item(close)
|
||||
.add_item(quit);
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
let first_menu = Menu::new()
|
||||
.add_item(hide)
|
||||
.add_item(close)
|
||||
.add_item(quit);
|
||||
let first_menu = Submenu::new("File", first_menu);
|
||||
// Hot Key
|
||||
// let top = CustomMenuItem::new("top", "Top (↑)");
|
||||
// let buttom = CustomMenuItem::new("buttom", "Bottom (↓)");
|
||||
// let previous = CustomMenuItem::new("previous", "Previous (←)");
|
||||
// let next = CustomMenuItem::new("next", "next (→)");
|
||||
// let refresh = CustomMenuItem::new("refresh", "Refresh");
|
||||
let zoom_out = CustomMenuItem::new("zoom_out", "Zoom Out (125%)");
|
||||
let zoom_in = CustomMenuItem::new("zoom_in", "Zoom In (75%)");
|
||||
let zoom_reset = CustomMenuItem::new("reset", "Zoom Reset");
|
||||
let hot_key = Menu::new()
|
||||
// .add_item(top)
|
||||
// .add_item(buttom)
|
||||
// .add_item(previous)
|
||||
// .add_item(next)
|
||||
// .add_item(refresh)
|
||||
.add_item(zoom_in)
|
||||
.add_item(zoom_out)
|
||||
.add_item(zoom_reset);
|
||||
let hot_key_menu = Submenu::new("Hot Key", hot_key);
|
||||
|
||||
// Help
|
||||
// let instructions = CustomMenuItem::new("instruction", "Instruction");
|
||||
// let about = CustomMenuItem::new("about", "About");
|
||||
// let help = Menu::new()
|
||||
// .add_item(instructions)
|
||||
// .add_item(about);
|
||||
// let help_menu = Submenu::new("Help", help);
|
||||
let menu = Menu::new()
|
||||
.add_submenu(first_menu)
|
||||
.add_submenu(hot_key_menu);
|
||||
// .add_submenu(help_menu);
|
||||
menu
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
pub fn get_data_dir(tauri_config: Config) -> std::path::PathBuf {
|
||||
let package_name = tauri_config.package.product_name.unwrap();
|
||||
let home_dir = match home::home_dir() {
|
||||
Some(path1) => path1,
|
||||
None => panic!("Error, can't found you home dir!!"),
|
||||
};
|
||||
#[cfg(target_os = "windows")]
|
||||
let data_dir = home_dir.join("AppData").join("Roaming").join(package_name);
|
||||
#[cfg(target_os = "linux")]
|
||||
let WindowConfig {
|
||||
url,
|
||||
width,
|
||||
height,
|
||||
resizable,
|
||||
fullscreen,
|
||||
..
|
||||
} = get_windows_config().unwrap_or_default();
|
||||
#[cfg(target_os = "windows")]
|
||||
let WindowConfig {
|
||||
url,
|
||||
width,
|
||||
height,
|
||||
resizable,
|
||||
fullscreen,
|
||||
..
|
||||
} = get_windows_config().unwrap_or_default();
|
||||
let data_dir = home_dir.join(".config").join(package_name);
|
||||
if !data_dir.exists() {
|
||||
std::fs::create_dir(&data_dir)
|
||||
.unwrap_or_else(|_| panic!("can't create dir {}", data_dir.display()));
|
||||
}
|
||||
data_dir
|
||||
}
|
||||
|
||||
|
||||
pub fn get_window(app: & mut App, config: PakeConfig, data_dir: std::path::PathBuf) -> Window {
|
||||
let window_config = config.windows.first().unwrap();
|
||||
let user_agent = config.user_agent;
|
||||
let url = match window_config.url_type.as_str() {
|
||||
"web" => WindowUrl::External(window_config.url.parse().unwrap()),
|
||||
"local" => WindowUrl::App(std::path::PathBuf::from(&window_config.url)),
|
||||
_ => panic!("url type only can be web or local"),
|
||||
};
|
||||
#[cfg(target_os = "macos")]
|
||||
let WindowConfig {
|
||||
url,
|
||||
width,
|
||||
height,
|
||||
resizable,
|
||||
transparent,
|
||||
fullscreen,
|
||||
..
|
||||
} = get_windows_config().unwrap_or_default();
|
||||
let event_loop = EventLoop::new();
|
||||
let window = WindowBuilder::new(
|
||||
app,
|
||||
"pake",
|
||||
url
|
||||
)
|
||||
.title("")
|
||||
.user_agent(user_agent.macos.as_str())
|
||||
.resizable(window_config.resizable)
|
||||
.fullscreen(window_config.fullscreen)
|
||||
.transparent(window_config.transparent)
|
||||
.inner_size(window_config.width, window_config.height)
|
||||
.initialization_script(include_str!("pake.js"));
|
||||
|
||||
let common_window = WindowBuilder::new()
|
||||
.with_title("")
|
||||
.with_resizable(resizable)
|
||||
.with_fullscreen(if fullscreen {
|
||||
Some(Fullscreen::Borderless(None))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.with_inner_size(wry::application::dpi::LogicalSize::new(width, height));
|
||||
#[cfg(target_os = "windows")]
|
||||
let icon = load_icon(std::path::Path::new("png/weread_32.ico"));
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let window = common_window
|
||||
.with_decorations(true)
|
||||
.with_window_icon(Some(icon))
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
let window = {
|
||||
#[cfg(target_os = "linux")]
|
||||
let user_agent = user_agent.linux.as_str();
|
||||
#[cfg(target_os = "windows")]
|
||||
let user_agent = user_agent.windows.as_str();
|
||||
WindowBuilder::new(
|
||||
app,
|
||||
"pake",
|
||||
url
|
||||
)
|
||||
.title("")
|
||||
.data_directory(data_dir)
|
||||
.resizable(window_config.resizable)
|
||||
.fullscreen(window_config.fullscreen)
|
||||
.user_agent(user_agent)
|
||||
.inner_size(window_config.width, window_config.height)
|
||||
.initialization_script(include_str!("pake.js"))
|
||||
};
|
||||
window.build().unwrap()
|
||||
|
||||
}
|
||||
|
||||
pub fn set_zoom(webview: PlatformWebview, zoom_value: f64) {
|
||||
#[cfg(target_os = "linux")]
|
||||
let window = common_window.build(&event_loop).unwrap();
|
||||
{
|
||||
// see https://docs.rs/webkit2gtk/0.18.2/webkit2gtk/struct.WebView.html
|
||||
// and https://docs.rs/webkit2gtk/0.18.2/webkit2gtk/trait.WebViewExt.html
|
||||
use webkit2gtk::traits::WebViewExt;
|
||||
webview.inner().set_zoom_level(zoom_value);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let window = common_window
|
||||
.with_fullsize_content_view(true)
|
||||
.with_titlebar_buttons_hidden(false)
|
||||
.with_titlebar_transparent(transparent)
|
||||
.with_title_hidden(true)
|
||||
.with_menu(menu_bar_menu)
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
#[cfg(windows)]
|
||||
unsafe {
|
||||
// see https://docs.rs/webview2-com/0.19.1/webview2_com/Microsoft/Web/WebView2/Win32/struct.ICoreWebView2Controller.html
|
||||
webview.controller().SetZoomFactor(zoom_value).unwrap();
|
||||
}
|
||||
|
||||
let handler = move |window: &Window, req: String| {
|
||||
if req == "drag_window" {
|
||||
let _ = window.drag_window();
|
||||
} else if req == "fullscreen" {
|
||||
if window.fullscreen().is_some() {
|
||||
window.set_fullscreen(None);
|
||||
} else {
|
||||
window.set_fullscreen(Some(Fullscreen::Borderless(None)));
|
||||
#[cfg(target_os = "macos")]
|
||||
unsafe {
|
||||
let () = msg_send![webview.inner(), setPageZoom: zoom_value];
|
||||
let () = msg_send![webview.controller(), removeAllUserScripts];
|
||||
let bg_color: cocoa::base::id = msg_send![class!(NSColor), colorWithDeviceRed:0.5 green:0.2 blue:0.4 alpha:1.];
|
||||
let () = msg_send![webview.ns_window(), setBackgroundColor: bg_color];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_zoom_out(webview: PlatformWebview) {
|
||||
set_zoom(webview, 1.25);
|
||||
}
|
||||
|
||||
|
||||
pub fn set_zoom_in(webview: PlatformWebview) {
|
||||
set_zoom(webview, 0.75);
|
||||
}
|
||||
|
||||
|
||||
pub fn zoom_reset(webview: PlatformWebview) {
|
||||
set_zoom(webview, 1.0);
|
||||
}
|
||||
|
||||
pub fn menu_event_handle(event: WindowMenuEvent) {
|
||||
match event.menu_item_id() {
|
||||
"hide" => event.window().hide().expect("can't hide window"),
|
||||
"close" => event.window().close().expect("can't close window"),
|
||||
"quit" => std::process::exit(0),
|
||||
"zoom_out" => {
|
||||
event.window()
|
||||
.with_webview(set_zoom_out)
|
||||
.expect("can't set zoom out");
|
||||
},
|
||||
"zoom_in" => {
|
||||
event.window()
|
||||
.with_webview(set_zoom_in)
|
||||
.expect("can't set zoom in");
|
||||
},
|
||||
"reset" => {
|
||||
event.window()
|
||||
.with_webview(zoom_reset)
|
||||
.expect("can't reset zoom");
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn get_system_tray() -> SystemTray {
|
||||
let hide = CustomMenuItem::new("hide".to_string(), "Hide");
|
||||
let show = CustomMenuItem::new("show".to_string(), "Show");
|
||||
let quit = CustomMenuItem::new("quit".to_string(), "Quit");
|
||||
let about = CustomMenuItem::new("about".to_string(), "About");
|
||||
let tray_menu = SystemTrayMenu::new()
|
||||
.add_item(hide)
|
||||
.add_item(show)
|
||||
.add_item(quit)
|
||||
.add_item(about);
|
||||
SystemTray::new().with_menu(tray_menu)
|
||||
}
|
||||
|
||||
|
||||
pub fn system_tray_handle(app: &tauri::AppHandle, event: tauri::SystemTrayEvent) {
|
||||
if let SystemTrayEvent::MenuItemClick { tray_id: _, id, .. } = event {
|
||||
match id.as_str() {
|
||||
"hide" => {
|
||||
app.get_window("pake").unwrap().hide().unwrap();
|
||||
},
|
||||
"show" => {
|
||||
app.get_window("pake").unwrap().show().unwrap();
|
||||
},
|
||||
"quit" => {
|
||||
std::process::exit(0);
|
||||
},
|
||||
"about" => {
|
||||
let _about_window = WindowBuilder::new(
|
||||
app,
|
||||
"about",
|
||||
WindowUrl::App(std::path::PathBuf::from("about_pake.html"))
|
||||
)
|
||||
.resizable(true)
|
||||
.title("About")
|
||||
.inner_size(100.0, 100.0)
|
||||
.build()
|
||||
.expect("can't open about!")
|
||||
;
|
||||
}
|
||||
} else if req.starts_with("open_browser") {
|
||||
let href = req.replace("open_browser:", "");
|
||||
webbrowser::open(&href).expect("no browser");
|
||||
_ => {},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 用于欺骗部分页面对于浏览器的强检测
|
||||
|
||||
// #[cfg(target_os = "macos")]
|
||||
// let user_agent_string = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15";
|
||||
|
||||
pub fn run_app() {
|
||||
let system_tray = get_system_tray();
|
||||
#[cfg(target_os = "macos")]
|
||||
let webview = WebViewBuilder::new(window)?
|
||||
// .with_user_agent(user_agent_string)
|
||||
// .with_accept_first_mouse(true)
|
||||
.with_url(&url.to_string())?
|
||||
.with_devtools(cfg!(feature = "devtools"))
|
||||
.with_initialization_script(include_str!("pake.js"))
|
||||
.with_ipc_handler(handler)
|
||||
// .with_back_forward_navigation_gestures(true)
|
||||
.build()?;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let webview = WebViewBuilder::new(window)?
|
||||
// .with_user_agent(user_agent_string)
|
||||
// .with_accept_first_mouse(true)
|
||||
.with_url(&url.to_string())?
|
||||
.with_devtools(cfg!(feature = "devtools"))
|
||||
.with_initialization_script(include_str!("pake.js"))
|
||||
.with_ipc_handler(handler)
|
||||
// .with_back_forward_navigation_gestures(true)
|
||||
.build()?;
|
||||
// 自定义cookie文件夹,仅用于Linux
|
||||
// Custom Cookie folder, only for Linux
|
||||
#[cfg(target_os = "linux")]
|
||||
let data_path =
|
||||
std::path::PathBuf::from(concat!("/home/", env!("USER"), "/.config/com-tw93-weread/"));
|
||||
#[cfg(target_os = "linux")]
|
||||
if !std::path::Path::new(&data_path).exists() {
|
||||
std::fs::create_dir(&data_path)?;
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
let mut web_content = WebContext::new(Some(data_path));
|
||||
#[cfg(target_os = "linux")]
|
||||
let webview = WebViewBuilder::new(window)?
|
||||
// .with_user_agent(user_agent_string)
|
||||
// .with_accept_first_mouse(true)
|
||||
.with_url(&url.to_string())?
|
||||
.with_devtools(cfg!(feature = "devtools"))
|
||||
.with_initialization_script(include_str!("pake.js"))
|
||||
.with_ipc_handler(handler)
|
||||
.with_web_context(&mut web_content)
|
||||
// .with_back_forward_navigation_gestures(true)
|
||||
.build()?;
|
||||
|
||||
#[cfg(feature = "devtools")]
|
||||
{
|
||||
webview.open_devtools();
|
||||
let (pake_config, _) = get_pake_config();
|
||||
let menu = get_menu();
|
||||
tauri::Builder::default()
|
||||
.menu(menu)
|
||||
.on_menu_event(menu_event_handle)
|
||||
.system_tray(system_tray)
|
||||
.on_system_tray_event(system_tray_handle)
|
||||
.plugin(tauri_plugin_window_state::Builder::default().build())
|
||||
.invoke_handler(tauri::generate_handler![])
|
||||
.setup(|app| {
|
||||
let _window = get_window(app, pake_config, std::path::PathBuf::new());
|
||||
#[cfg(feature = "devtools")]
|
||||
{
|
||||
app.get_window("pake").unwrap().open_devtools();
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
{
|
||||
let (pake_config, tauri_config) = get_pake_config();
|
||||
let data_dir = get_data_dir(tauri_config);
|
||||
// let menu = get_menu();
|
||||
tauri::Builder::default()
|
||||
// .menu(menu)
|
||||
// .on_menu_event(menu_event_handle)
|
||||
.system_tray(system_tray)
|
||||
.on_system_tray_event(system_tray_handle)
|
||||
.plugin(tauri_plugin_window_state::Builder::default().build())
|
||||
.invoke_handler(tauri::generate_handler![])
|
||||
.setup(|app| {
|
||||
let _window = get_window(app, pake_config, data_dir);
|
||||
#[cfg(feature = "devtools")]
|
||||
{
|
||||
app.get_window("pake").unwrap().open_devtools();
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
*control_flow = ControlFlow::Wait;
|
||||
|
||||
match event {
|
||||
Event::NewEvents(StartCause::Init) => println!("Wry has started!"),
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => *control_flow = ControlFlow::Exit,
|
||||
Event::MenuEvent {
|
||||
menu_id,
|
||||
origin: MenuType::MenuBar,
|
||||
..
|
||||
} => {
|
||||
#[cfg(target_os = "macos")]
|
||||
if menu_id == close_item.clone().id() {
|
||||
webview.window().set_minimized(true);
|
||||
}
|
||||
println!("Clicked on {:?}", menu_id);
|
||||
println!("Clicked on {:?}", webview.window().is_visible());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn get_windows_config() -> Option<WindowConfig> {
|
||||
let config_file = include_str!("../tauri.conf.json");
|
||||
let config: Config = serde_json::from_str(config_file).expect("failed to parse windows config");
|
||||
|
||||
config.tauri.windows.first().cloned()
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn load_icon(path: &std::path::Path) -> Icon {
|
||||
let (icon_rgba, icon_width, icon_height) = {
|
||||
// alternatively, you can embed the icon in the binary through `include_bytes!` macro and use `image::load_from_memory`
|
||||
let image = image::open(path)
|
||||
.expect("Failed to open icon path")
|
||||
.into_rgba8();
|
||||
let (width, height) = image.dimensions();
|
||||
let rgba = image.into_raw();
|
||||
(rgba, width, height)
|
||||
};
|
||||
Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon")
|
||||
fn main() {
|
||||
run_app()
|
||||
|
||||
}
|
||||
|
||||
229
src-tauri/src/main.rs.bak
Normal file
@@ -0,0 +1,229 @@
|
||||
// at the top of main.rs - that will prevent the console from showing
|
||||
#![windows_subsystem = "windows"]
|
||||
extern crate image;
|
||||
use tauri_utils::config::{Config, WindowConfig};
|
||||
use wry::{
|
||||
application::{
|
||||
event::{Event, StartCause, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
menu::MenuType,
|
||||
window::{Fullscreen, Window, WindowBuilder},
|
||||
},
|
||||
webview::WebViewBuilder,
|
||||
};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use wry::application::{
|
||||
accelerator::{Accelerator, SysMods},
|
||||
keyboard::KeyCode,
|
||||
menu::{MenuBar as Menu, MenuItem, MenuItemAttributes},
|
||||
platform::macos::WindowBuilderExtMacOS,
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use wry::application::window::Icon;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
use wry::webview::WebContext;
|
||||
|
||||
fn main() -> wry::Result<()> {
|
||||
#[cfg(target_os = "macos")]
|
||||
let (menu_bar_menu, close_item) = {
|
||||
let mut menu_bar_menu = Menu::new();
|
||||
let mut first_menu = Menu::new();
|
||||
first_menu.add_native_item(MenuItem::Hide);
|
||||
first_menu.add_native_item(MenuItem::EnterFullScreen);
|
||||
first_menu.add_native_item(MenuItem::Minimize);
|
||||
first_menu.add_native_item(MenuItem::Separator);
|
||||
first_menu.add_native_item(MenuItem::Copy);
|
||||
first_menu.add_native_item(MenuItem::Cut);
|
||||
first_menu.add_native_item(MenuItem::Paste);
|
||||
first_menu.add_native_item(MenuItem::Undo);
|
||||
first_menu.add_native_item(MenuItem::Redo);
|
||||
first_menu.add_native_item(MenuItem::SelectAll);
|
||||
first_menu.add_native_item(MenuItem::Separator);
|
||||
let close_item = first_menu.add_item(
|
||||
MenuItemAttributes::new("CloseWindow")
|
||||
.with_accelerators(&Accelerator::new(SysMods::Cmd, KeyCode::KeyW)),
|
||||
);
|
||||
first_menu.add_native_item(MenuItem::Quit);
|
||||
menu_bar_menu.add_submenu("App", true, first_menu);
|
||||
(menu_bar_menu, close_item)
|
||||
};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
let (
|
||||
package_name,
|
||||
WindowConfig {
|
||||
url,
|
||||
width,
|
||||
height,
|
||||
resizable,
|
||||
fullscreen,
|
||||
..
|
||||
},
|
||||
) = {
|
||||
let (package_name, windows_config) = get_windows_config();
|
||||
(
|
||||
package_name
|
||||
.expect("can't get package name in config file")
|
||||
.to_lowercase(),
|
||||
windows_config.unwrap_or_default(),
|
||||
)
|
||||
};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let WindowConfig {
|
||||
url,
|
||||
width,
|
||||
height,
|
||||
resizable,
|
||||
transparent,
|
||||
fullscreen,
|
||||
..
|
||||
} = get_windows_config().1.unwrap_or_default();
|
||||
let event_loop = EventLoop::new();
|
||||
|
||||
let common_window = WindowBuilder::new()
|
||||
.with_title("")
|
||||
.with_resizable(resizable)
|
||||
.with_fullscreen(if fullscreen {
|
||||
Some(Fullscreen::Borderless(None))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.with_inner_size(wry::application::dpi::LogicalSize::new(width, height));
|
||||
#[cfg(target_os = "windows")]
|
||||
let window = {
|
||||
let icon_path = format!("png/{}_32.ico", package_name);
|
||||
let icon = load_icon(std::path::Path::new(&icon_path));
|
||||
common_window
|
||||
.with_decorations(true)
|
||||
.with_window_icon(Some(icon))
|
||||
.build(&event_loop)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
let window = common_window.build(&event_loop).unwrap();
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let window = common_window
|
||||
.with_fullsize_content_view(true)
|
||||
.with_titlebar_buttons_hidden(false)
|
||||
.with_titlebar_transparent(transparent)
|
||||
.with_title_hidden(true)
|
||||
.with_menu(menu_bar_menu)
|
||||
.build(&event_loop)
|
||||
.unwrap();
|
||||
|
||||
let handler = move |window: &Window, req: String| {
|
||||
if req == "drag_window" {
|
||||
let _ = window.drag_window();
|
||||
} else if req == "fullscreen" {
|
||||
if window.fullscreen().is_some() {
|
||||
window.set_fullscreen(None);
|
||||
} else {
|
||||
window.set_fullscreen(Some(Fullscreen::Borderless(None)));
|
||||
}
|
||||
} else if req.starts_with("open_browser") {
|
||||
let href = req.replace("open_browser:", "");
|
||||
webbrowser::open(&href).expect("no browser");
|
||||
}
|
||||
};
|
||||
|
||||
// 用于欺骗部分页面对于浏览器的强检测
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
let webview = {
|
||||
let user_agent_string = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15";
|
||||
WebViewBuilder::new(window)?
|
||||
.with_user_agent(user_agent_string)
|
||||
.with_url(&url.to_string())?
|
||||
.with_devtools(cfg!(feature = "devtools"))
|
||||
.with_initialization_script(include_str!("pake.js"))
|
||||
.with_ipc_handler(handler)
|
||||
.with_back_forward_navigation_gestures(true)
|
||||
.build()?
|
||||
};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
let webview = {
|
||||
let home_dir = match home::home_dir() {
|
||||
Some(path1) => path1,
|
||||
None => panic!("Error, can't found you home dir!!"),
|
||||
};
|
||||
#[cfg(target_os = "windows")]
|
||||
let data_dir = home_dir.join("AppData").join("Roaming").join(package_name);
|
||||
#[cfg(target_os = "linux")]
|
||||
let data_dir = home_dir.join(".config").join(package_name);
|
||||
if !data_dir.exists() {
|
||||
std::fs::create_dir(&data_dir)
|
||||
.unwrap_or_else(|_| panic!("can't create dir {}", data_dir.display()));
|
||||
}
|
||||
let mut web_content = WebContext::new(Some(data_dir));
|
||||
#[cfg(target_os = "windows")]
|
||||
let user_agent_string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36";
|
||||
#[cfg(target_os = "linux")]
|
||||
let user_agent_string = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36";
|
||||
WebViewBuilder::new(window)?
|
||||
.with_user_agent(user_agent_string)
|
||||
.with_url(&url.to_string())?
|
||||
.with_devtools(cfg!(feature = "devtools"))
|
||||
.with_initialization_script(include_str!("pake.js"))
|
||||
.with_ipc_handler(handler)
|
||||
.with_web_context(&mut web_content)
|
||||
.build()?
|
||||
};
|
||||
#[cfg(feature = "devtools")]
|
||||
{
|
||||
webview.open_devtools();
|
||||
}
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
*control_flow = ControlFlow::Wait;
|
||||
match event {
|
||||
Event::NewEvents(StartCause::Init) => println!("Wry has started!"),
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => *control_flow = ControlFlow::Exit,
|
||||
Event::MenuEvent {
|
||||
menu_id,
|
||||
origin: MenuType::MenuBar,
|
||||
..
|
||||
} => {
|
||||
#[cfg(target_os = "macos")]
|
||||
if menu_id == close_item.clone().id() {
|
||||
webview.window().set_minimized(true);
|
||||
}
|
||||
println!("Clicked on {:?}", menu_id);
|
||||
println!("Clicked on {:?}", webview.window().is_visible());
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn get_windows_config() -> (Option<String>, Option<WindowConfig>) {
|
||||
let config_file = include_str!("../tauri.conf.json");
|
||||
let config: Config = serde_json::from_str(config_file).expect("failed to parse windows config");
|
||||
(
|
||||
config.package.product_name.clone(),
|
||||
config.tauri.windows.first().cloned(),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn load_icon(path: &std::path::Path) -> Icon {
|
||||
let (icon_rgba, icon_width, icon_height) = {
|
||||
// alternatively, you can embed the icon in the binary through `include_bytes!` macro and use `image::load_from_memory`
|
||||
let image = image::open(path)
|
||||
.expect("Failed to open icon path")
|
||||
.into_rgba8();
|
||||
let (width, height) = image.dimensions();
|
||||
let rgba = image.into_raw();
|
||||
(rgba, width, height)
|
||||
};
|
||||
Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon")
|
||||
}
|
||||
28
src-tauri/src/pake.js
vendored
@@ -55,6 +55,18 @@ window.addEventListener("DOMContentLoaded", (_event) => {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
#__next .overflow-hidden .flex.flex-1.flex-col {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#__next .overflow-hidden>.hidden.bg-gray-900 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#__next .overflow-hidden main .absolute .text-xs{
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.lark > .dashboard-sidebar, .lark > .dashboard-sidebar > .sidebar-user-info , .lark > .dashboard-sidebar .index-module_wrapper_F-Wbq{
|
||||
padding-top:15px;
|
||||
}
|
||||
@@ -200,10 +212,8 @@ window.addEventListener("DOMContentLoaded", (_event) => {
|
||||
left: 1px !important;
|
||||
}
|
||||
|
||||
#react-root [data-testid="SideNav_NewTweet_Button"] {
|
||||
position: fixed !important;
|
||||
right: 16px !important;
|
||||
bottom: 24px !important;
|
||||
#react-root [data-testid="SideNav_NewTweet_Button"], #react-root [aria-label="Twitter Blue"]{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,16 +316,16 @@ window.addEventListener("DOMContentLoaded", (_event) => {
|
||||
document.addEventListener("click", (e) => {
|
||||
const origin = e.target.closest("a");
|
||||
if (origin && origin.href) {
|
||||
const target = origin.target
|
||||
origin.target = "_self";
|
||||
const hrefUrl = new URL(origin.href)
|
||||
|
||||
//额外处理下 twitter 的外跳,对于其他需要外跳的可以改这里成对应域名
|
||||
const href = origin.href;
|
||||
if (
|
||||
location.host === "twitter.com" &&
|
||||
href.indexOf("twitter.com") === -1
|
||||
window.location.host !== hrefUrl.host && // 如果 a 标签内链接的域名和当前页面的域名不一致 且
|
||||
target === '_blank' // a 标签内链接的 target 属性为 _blank 时
|
||||
) {
|
||||
e.preventDefault();
|
||||
window.ipc.postMessage(`open_browser:${href}`);
|
||||
window.ipc.postMessage(`open_browser:${origin.href}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,71 +4,15 @@
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"tauri": {
|
||||
"windows": [
|
||||
{
|
||||
"url": "https://weread.qq.com/",
|
||||
"transparent": true,
|
||||
"fullscreen": false,
|
||||
"width": 1200,
|
||||
"height": 728,
|
||||
"resizable": true
|
||||
}
|
||||
],
|
||||
"allowlist": {
|
||||
"all": true
|
||||
},
|
||||
"bundle": {
|
||||
"icon": [
|
||||
"icons/weread.icns",
|
||||
"png/weread_256.ico",
|
||||
"png/weread_32.ico",
|
||||
"png/weread_512.png"
|
||||
],
|
||||
"identifier": "com.tw93.weread",
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"copyright": "",
|
||||
"deb": {
|
||||
"depends": [
|
||||
"libwebkit2gtk-4.0-dev",
|
||||
"build-essential",
|
||||
"curl",
|
||||
"wget",
|
||||
"libssl-dev",
|
||||
"libgtk-3-dev",
|
||||
"libayatana-appindicator3-dev",
|
||||
"librsvg2-dev"
|
||||
],
|
||||
"files": {
|
||||
"/usr/share/applications/com-tw93-weread.desktop": "assets/com-tw93-weread.desktop"
|
||||
}
|
||||
},
|
||||
"externalBin": [],
|
||||
"longDescription": "",
|
||||
"macOS": {
|
||||
"entitlements": null,
|
||||
"exceptionDomain": "",
|
||||
"frameworks": [],
|
||||
"providerShortName": null,
|
||||
"signingIdentity": null
|
||||
},
|
||||
"resources": ["png/weread_32.ico"],
|
||||
"shortDescription": "",
|
||||
"targets": ["deb", "msi", "dmg"],
|
||||
"windows": {
|
||||
"certificateThumbprint": null,
|
||||
"digestAlgorithm": "sha256",
|
||||
"timestampUrl": "",
|
||||
"wix": {
|
||||
"language": ["en-US"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": {
|
||||
"csp": null
|
||||
},
|
||||
"updater": {
|
||||
"active": false
|
||||
},
|
||||
"systemTray": {
|
||||
"iconPath": "png/weread_512.png",
|
||||
"iconAsTemplate": true
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
|
||||
36
src-tauri/tauri.linux.conf.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"icon": [
|
||||
"png/weread_256.ico",
|
||||
"png/weread_512.png"
|
||||
],
|
||||
"identifier": "com.tw93.weread",
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"copyright": "",
|
||||
"deb": {
|
||||
"depends": [
|
||||
"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"
|
||||
],
|
||||
"files": {
|
||||
"/usr/share/applications/com-tw93-weread.desktop": "assets/com-tw93-weread.desktop"
|
||||
}
|
||||
},
|
||||
"externalBin": [],
|
||||
"longDescription": "",
|
||||
"resources": [],
|
||||
"shortDescription": "",
|
||||
"targets": ["deb", "appimage"]
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src-tauri/tauri.macos.conf.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"icon": [
|
||||
"icons/weread.icns"
|
||||
],
|
||||
"identifier": "com.tw93.weread",
|
||||
"active": true,
|
||||
"category": "DeveloperTool",
|
||||
"copyright": "",
|
||||
"externalBin": [],
|
||||
"longDescription": "",
|
||||
"macOS": {
|
||||
"entitlements": null,
|
||||
"exceptionDomain": "",
|
||||
"frameworks": [],
|
||||
"providerShortName": null,
|
||||
"signingIdentity": null
|
||||
},
|
||||
"resources": [],
|
||||
"shortDescription": "",
|
||||
"targets": ["dmg"]
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src-tauri/tauri.windows.conf.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"tauri": {
|
||||
"bundle": {
|
||||
"icon": [
|
||||
"png/weread_256.ico",
|
||||
"png/weread_32.ico"
|
||||
],
|
||||
"identifier": "com.tw93.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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||