├── .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 | ![screenshot](./asset/app.png) 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 | [![Star History Chart](https://api.star-history.com/svg?repos=estepona/wx-read-desktop&type=Date)](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 | ![screenshot](./asset/app.png) 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 | [![Star History Chart](https://api.star-history.com/svg?repos=estepona/wx-read-desktop&type=Date)](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 | } --------------------------------------------------------------------------------