├── .eslintrc.js
├── .github
└── workflows
│ └── test.yml
├── .gitignore
├── .prettierrc.js
├── .vscode
├── launch.json
└── settings.json
├── LICENSE.md
├── README.en.md
├── README.md
├── asset
└── app.png
├── build
└── icon.png
├── package-lock.json
├── package.json
├── src
├── main.ts
├── preload.ts
└── renderer.ts
└── tsconfig.json
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser', // Specifies the ESLint parser
3 | extends: [
4 | 'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
5 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
6 | 'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
7 | ],
8 | rules: {
9 | '@typescript-eslint/explicit-function-return-type': 0,
10 | '@typescript-eslint/explicit-member-accessibility': 0,
11 | '@typescript-eslint/no-var-requires': 0,
12 | '@typescript-eslint/camelcase': 0,
13 | },
14 | parserOptions: {
15 | ecmaVersion: 2019, // Allows for the parsing of modern ECMAScript features
16 | sourceType: 'module', // Allows for the use of imports
17 | ecmaFeatures: {
18 | jsx: true,
19 | },
20 | },
21 | plugins: ['@typescript-eslint', 'prettier'],
22 | settings: {
23 | react: {
24 | version: 'detect',
25 | },
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: lint
2 |
3 | on: push
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - uses: actions/setup-node@v1
11 | with:
12 | node-version: '12'
13 | - run: npm install
14 | - run: npm run lint
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependency
2 | node_modules
3 |
4 | # Out
5 | out
6 | tsout
7 |
8 | # Distribute
9 | dist
10 | release
11 |
12 | # credential
13 | .env
14 |
15 | # misc
16 | .DS_Store
--------------------------------------------------------------------------------
/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: true,
3 | trailingComma: 'all',
4 | singleQuote: true,
5 | printWidth: 120,
6 | tabWidth: 2,
7 | };
8 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Debug Main Process via electron",
6 | "type": "node",
7 | "request": "launch",
8 | "cwd": "${workspaceRoot}",
9 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
10 | "windows": {
11 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
12 | },
13 | "args": [
14 | "./dist/app.js"
15 | ],
16 | "outputCapture": "std"
17 | },
18 | {
19 | "name": "Debug Main Process via npm",
20 | "type": "node",
21 | "request": "launch",
22 | "cwd": "${workspaceFolder}",
23 | "runtimeExecutable": "npm",
24 | "runtimeArgs": ["run-script", "start"],
25 | // "windows": {
26 | // "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron.cmd"
27 | // },
28 | "outputCapture": "std",
29 | "port": 9229,
30 | }
31 | ]
32 | }
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.autoSave": "afterDelay",
3 | "editor.formatOnSave": true,
4 | "editor.codeActionsOnSave": {
5 | "source.fixAll.eslint": "explicit"
6 | },
7 | "editor.tabSize": 2,
8 | "eslint.validate": ["javascript", "typescript"],
9 | "[javascript]": {
10 | "editor.formatOnSave": true
11 | },
12 | "[typescript]": {
13 | "editor.formatOnSave": true
14 | },
15 | "[html]": {
16 | "editor.formatOnSave": true
17 | },
18 | "[css]": {
19 | "editor.formatOnSave": true
20 | },
21 | "cSpell.words": ["douban", "menu", "selected", "submenu"]
22 | }
23 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Binghuan Zhang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.en.md:
--------------------------------------------------------------------------------
1 |
2 |
Wechat Read Desktop
3 |
A minimal Weixin Read desktop client based on electron.js.
4 |

5 |

6 |

7 |
8 |
9 | 
10 |
11 | [中文](./README.md) | **English**
12 |
13 | Wechat Read Desktop is a minimal Wechat Read desktop client based on electron.js. All it does is wrapping the Wechat Read Web app in a simple desktop app, providing the same experience as Wechat Read Web app, which is good for quickly open this app when you have multiple browser tabs opened.
14 |
15 | ## Install
16 |
17 | Installers can be found at [Release Page](https://github.com/estepona/wx-read-desktop/releases). Currently supporting Mac and Windows.
18 |
19 | ## Credit
20 |
21 | Thanks to the Wechat Read Team for building such a great product. As a reader, I enjoyed the reading experience a lot on Mobile, Kindle, and Web. And as a developer, my goal is to give readers an opportunity to enjoy it on a desktop client. Since its web client is great enough for me, all I need to do is wrapping it with electron.
22 |
23 | ## Author
24 |
25 | [Binghuan Zhang](https://github.com/estepona) - esteponawondering@gmail.com
26 |
27 | ## Star History
28 |
29 | [](https://www.star-history.com/#estepona/wx-read-desktop&Date)
30 |
31 | ## LICENSE
32 |
33 | MIT
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
微信读书桌面版
3 |
一个极简版微信读书桌面客户端,基于electron.js
4 |

5 |

6 |

7 |
8 |
9 | 
10 |
11 | **中文** | [English](./README.en.md)
12 |
13 | 微信读书桌面版是一个基于 electron.js 的极简微信读书桌面客户端。它仅仅提供一个微信网页版的包装,与微信网页版功能全无二致,方便在多个浏览器页面开启时快速切换到微信读书。
14 |
15 | ## 安装
16 |
17 | 安装包可以在[Release 页面](https://github.com/estepona/wx-read-desktop/releases)找到,目前支持 Mac 以及 Windows 平台。
18 |
19 | ## 感谢
20 |
21 | 感谢微信读书团队做出这么优秀的一款读书产品,作为一名读者,我十分享受在手机端、kindle 端、以及普通网页端其使用体验。作为一名开发者,我的初衷是希望更多读者能有机会在电脑客户端中使用它,它的网页端对我而言已经很优秀了,我需要做的仅仅是用 electron 把它包装起来。
22 |
23 | ## 作者
24 |
25 | [张秉寰](https://github.com/estepona) - esteponawondering@gmail.com
26 |
27 | ## Star History
28 |
29 | [](https://www.star-history.com/#estepona/wx-read-desktop&Date)
30 |
31 | ## LICENSE
32 |
33 | MIT
34 |
--------------------------------------------------------------------------------
/asset/app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/estepona/wx-read-desktop/97154e10d0be1c9317ceb879a98977b83f496091/asset/app.png
--------------------------------------------------------------------------------
/build/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/estepona/wx-read-desktop/97154e10d0be1c9317ceb879a98977b83f496091/build/icon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "wx-read",
3 | "description": "A simple Electron application for Weixin Read",
4 | "version": "0.2.3",
5 | "author": "Binghuan Zhang ",
6 | "repository": "https://github.com/estepona/wx-read-desktop",
7 | "keywords": [
8 | "wechat",
9 | "weixin",
10 | "read",
11 | "electron",
12 | "typescript"
13 | ],
14 | "main": "./tsout/main.js",
15 | "build": {
16 | "appId": "com.electron.wx-read",
17 | "productName": "wx-read",
18 | "copyright": "Copyright © 2022 - ${author}",
19 | "directories": {
20 | "buildResources": "build",
21 | "output": "release",
22 | "app": "."
23 | },
24 | "mac": {
25 | "category": "public.app-category.entertainment",
26 | "target": "dmg"
27 | }
28 | },
29 | "scripts": {
30 | "build": "tsc",
31 | "watch": "tsc -w",
32 | "lint": "npx eslint src/",
33 | "start": "npm run build && electron ./tsout/main.js",
34 | "pack-win": "npm run build && npx electron-builder -w --x64",
35 | "pack-mac": "npm run build && npx electron-builder -m --x64",
36 | "pack-mas": "npm run build && npx electron-builder -m --arm64"
37 | },
38 | "devDependencies": {
39 | "@typescript-eslint/eslint-plugin": "^3.6.0",
40 | "@typescript-eslint/parser": "^3.6.0",
41 | "ansi-regex": ">=5.0.1",
42 | "electron": "^22.0.3",
43 | "electron-builder": "^25.0.5",
44 | "eslint": "^7.4.0",
45 | "eslint-config-prettier": "^6.11.0",
46 | "eslint-plugin-prettier": "^3.1.4",
47 | "ini": "^3.0.0",
48 | "prettier": "^2.0.5",
49 | "typescript": "^3.9.5"
50 | },
51 | "dependencies": {
52 | "dotenv": "^16.0.1"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import * as dotenv from 'dotenv';
2 | import { app, BrowserWindow, BrowserView } from 'electron';
3 |
4 | dotenv.config();
5 |
6 | const createWindow = () => {
7 | // Create the browser window.
8 | const mainWindow = new BrowserWindow({
9 | title: `wx-read-desktop ${process.env.npm_package_version}`,
10 |
11 | height: 800,
12 | width: 1280,
13 |
14 | autoHideMenuBar: process.env.NODE_ENV === 'dev' ? false : true,
15 |
16 | webPreferences: {
17 | nodeIntegration: true,
18 | },
19 | });
20 |
21 | mainWindow.loadURL('https://weread.qq.com/');
22 |
23 | // Open the DevTools.
24 | process.env.NODE_ENV === 'dev' && mainWindow.webContents.openDevTools();
25 | };
26 |
27 | // This method will be called when Electron has finished
28 | // initialization and is ready to create browser windows.
29 | // Some APIs can only be used after this event occurs.
30 | app.whenReady().then(() => {
31 | createWindow();
32 |
33 | app.on('activate', function () {
34 | // On macOS it's common to re-create a window in the app when the
35 | // dock icon is clicked and there are no other windows open.
36 | if (BrowserWindow.getAllWindows().length === 0) createWindow();
37 | });
38 | });
39 |
40 | // Quit when all windows are closed, except on macOS. There, it's common
41 | // for applications and their menu bar to stay active until the user quits
42 | // explicitly with Cmd + Q.
43 | app.on('window-all-closed', () => {
44 | if (process.platform !== 'darwin') {
45 | app.quit();
46 | }
47 | });
48 |
49 | // In this file you can include the rest of your app"s specific main process
50 | // code. You can also put them in separate files and require them here.
51 |
--------------------------------------------------------------------------------
/src/preload.ts:
--------------------------------------------------------------------------------
1 | // All of the Node.js APIs are available in the preload process.
2 | // It has the same sandbox as a Chrome extension.
3 | window.addEventListener('DOMContentLoaded', () => {
4 | return;
5 | });
6 |
--------------------------------------------------------------------------------
/src/renderer.ts:
--------------------------------------------------------------------------------
1 | // This file is required by the index.html file and will
2 | // be executed in the renderer process for that window.
3 | // No Node.js APIs are available in this process unless
4 | // nodeIntegration is set to true in webPreferences.
5 | // Use preload.js to selectively enable features
6 | // needed in the renderer process.
7 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "noImplicitAny": true,
5 | "sourceMap": true,
6 | "strict": true,
7 | "outDir": "tsout",
8 | "baseUrl": ".",
9 | "typeRoots": [
10 | "typing"
11 | ],
12 | "paths": {
13 | "*": [
14 | "node_modules/*"
15 | ]
16 | }
17 | },
18 | "include": [
19 | "src/**/*"
20 | ]
21 | }
--------------------------------------------------------------------------------