add font customization

This commit is contained in:
Bruce Liu 2021-12-16 15:00:48 +08:00
parent cf38cc00c8
commit bba895a95e
21 changed files with 426 additions and 671 deletions

View File

@ -1,10 +1,3 @@
# Build the MAS app
CSC_IDENTITY_AUTO_DISCOVERY=false npx electron-builder -c electron-builder-mas.yml --mac mas:universal
# Add ElectronTeamID to Info.plist
sed -i '' -e 's/<\/dict>/<key>ElectronTeamID<\/key><string>EM8VE646TZ<\/string><\/dict>/g' "bin/darwin/universal/mas-universal/Fluent Reader.app/Contents/Info.plist"
printf "......................\nresignAndPackage start\n\n"
# Name of your app.
APP="Fluent Reader"
# Your Certificate name.
@ -21,6 +14,17 @@ PARENT_PLIST="build/entitlements.mas.plist"
CHILD_PLIST="build/entitlements.mas.inherit.plist"
LOGINHELPER_PLIST="build/entitlements.mas.loginhelper.plist"
FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks"
# Build universal binary for font-list
# FONTLIST_PATH="node_modules/font-list/libs/darwin/fontlist.m"
# clang -arch arm64 -arch x86_64 "$FONTLIST_PATH" -fmodules -o "dist/fontlist"
# Build the MAS app
CSC_IDENTITY_AUTO_DISCOVERY=false npx electron-builder -c electron-builder-mas.yml --mac mas:universal
# Add ElectronTeamID to Info.plist
sed -i '' -e 's/<\/dict>/<key>ElectronTeamID<\/key><string>EM8VE646TZ<\/string><\/dict>/g' "bin/darwin/universal/mas-universal/Fluent Reader.app/Contents/Info.plist"
printf "......................\nresignAndPackage start\n\n"
codesign --deep --force --verify --verbose=4 --timestamp --options runtime --entitlements "$CHILD_PLIST" -s "$APP_KEY" "$APP_PATH/Contents/Resources/app.asar.unpacked/dist/fontlist"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libEGL.dylib"
codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libGLESv2.dylib"
@ -44,4 +48,4 @@ codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacO
codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH"
productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH"
printf "\nresignAndPackage end\n......................\n"
printf "\nresignAndPackage end\n......................\n"

View File

@ -128,6 +128,11 @@ article code {
font-size: 0.875rem;
line-height: 1;
}
article pre {
word-break: normal;
overflow-wrap: normal;
white-space: pre-wrap;
}
article blockquote {
border-left: 2px solid var(--gray);
margin: 1em 0;

View File

@ -3,14 +3,14 @@
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy"
content="default-src 'none'; script-src-elem 'sha256-sLDWrq1tUAO8IyyqmUckFqxbXYfZ2/3TEUmtxH8Unf0=' 'sha256-OOzJH14UHiDzBx2LDF/KOAR+BVrHdNzZ2fZvPaqCMhY='; img-src http: https: data:; style-src 'self' 'unsafe-inline'; frame-src http: https:; media-src http: https:; connect-src https: http:">
content="default-src 'none'; script-src-elem 'sha256-sLDWrq1tUAO8IyyqmUckFqxbXYfZ2/3TEUmtxH8Unf0=' 'sha256-iOdZeo0zvgcSuiH/7/dXCOHo7s0cn2XtsidqVOcHBjo='; img-src http: https: data:; style-src 'self' 'unsafe-inline'; frame-src http: https:; media-src http: https:; connect-src https: http:">
<title>Article</title>
<link rel="stylesheet" href="article.css" />
<script integrity="sha256-sLDWrq1tUAO8IyyqmUckFqxbXYfZ2/3TEUmtxH8Unf0=" src="mercury.web.js"></script>
</head>
<body>
<div id="main"></div>
<script integrity="sha256-OOzJH14UHiDzBx2LDF/KOAR+BVrHdNzZ2fZvPaqCMhY=" src="article.js"></script>
<script integrity="sha256-iOdZeo0zvgcSuiH/7/dXCOHo7s0cn2XtsidqVOcHBjo=" src="article.js"></script>
<!-- Run "cat article.js | openssl dgst -sha256 -binary | openssl enc -base64 -A" for hash -->
</body>
</html>

View File

@ -20,6 +20,8 @@ async function getArticle(url) {
}
}
document.documentElement.style.fontSize = get("s") + "px"
let font = get("f")
if (font) document.body.style.fontFamily = `"${font}"`
let url = get("u")
getArticle(url).then(article => {
let domParser = new DOMParser()

BIN
dist/fontlist vendored Executable file

Binary file not shown.

29
dist/fonts.vbs vendored Normal file
View File

@ -0,0 +1,29 @@
Option Explicit
Dim objShell, objFSO, objFile, objFolder
Dim objFolderItem, colItems, objFont
Dim strFileName
Const FONTS = &H14& ' Fonts Folder
' Instantiate Objects
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(FONTS)
Set objFolderItem = objFolder.Self
Set colItems = objFolder.Items
Set objFSO = CreateObject("Scripting.FileSystemObject")
For Each objFont in colItems
WScript.StdOut.WriteLine(objFont.Path & vbtab & objFont.Name)
Next
Set objShell = nothing
Set objFile = nothing
Set objFolder = nothing
Set objFolderItem = nothing
Set colItems = nothing
Set objFont = nothing
Set objFSO = nothing
wscript.quit

View File

@ -4,7 +4,10 @@ productName: Fluent Reader
copyright: Copyright © 2020 Haoyuan Liu
files:
- "./dist/**/*"
- "!./dist/fonts.vbs"
- "!**/*.js.map"
asarUnpack:
- "./dist/fontlist"
directories:
output: "./bin/${platform}/${arch}/"
mac:

View File

@ -3,6 +3,7 @@ productName: Fluent Reader
copyright: Copyright © 2020 Haoyuan Liu
files:
- "./dist/**/*"
- "!./dist/fontlist"
- "!**/*.js.map"
directories:
output: "./bin/${platform}/${arch}/"

948
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@
"electron-react-devtools": "^0.5.3",
"electron-store": "^5.2.0",
"electron-window-state": "^5.0.3",
"font-list": "^1.4.2",
"hard-source-webpack-plugin": "^0.13.1",
"html-webpack-plugin": "^4.3.0",
"js-md5": "^0.7.3",

View File

@ -75,6 +75,13 @@ const settingsBridge = {
ipcRenderer.invoke("set-font-size", size)
},
getFont: (): string => {
return ipcRenderer.sendSync("get-font")
},
setFont: (font: string) => {
ipcRenderer.invoke("set-font", font)
},
getFetchInterval: (): number => {
return ipcRenderer.sendSync("get-fetch-interval")
},

View File

@ -170,11 +170,16 @@ const utilsBridge = {
destroyTouchBar: () => {
ipcRenderer.invoke("touchbar-destroy")
},
initFontList: (): Promise<Array<string>> => {
return ipcRenderer.invoke("init-font-list")
},
}
declare global {
interface Window {
utils: typeof utilsBridge
fontList: Array<string>
}
}

View File

@ -38,6 +38,7 @@ type ArticleProps = {
}
type ArticleState = {
fontFamily: string
fontSize: number
loadWebpage: boolean
loadFull: boolean
@ -53,7 +54,8 @@ class Article extends React.Component<ArticleProps, ArticleState> {
constructor(props: ArticleProps) {
super(props)
this.state = {
fontSize: this.getFontSize(),
fontFamily: window.settings.getFont(),
fontSize: window.settings.getFontSize(),
loadWebpage: props.source.openTarget === SourceOpenTarget.Webpage,
loadFull: props.source.openTarget === SourceOpenTarget.FullContent,
fullContent: "",
@ -68,15 +70,16 @@ class Article extends React.Component<ArticleProps, ArticleState> {
this.loadFull()
}
getFontSize = () => {
return window.settings.getFontSize()
}
setFontSize = (size: number) => {
window.settings.setFontSize(size)
this.setState({ fontSize: size })
}
setFont = (font: string) => {
window.settings.setFont(font)
this.setState({ fontFamily: font })
}
fontMenuProps = (): IContextualMenuProps => ({
fontSizeMenuProps = (): IContextualMenuProps => ({
items: FONT_SIZE_OPTIONS.map(size => ({
key: String(size),
text: String(size),
@ -86,6 +89,16 @@ class Article extends React.Component<ArticleProps, ArticleState> {
})),
})
fontFamilyMenuProps = (): IContextualMenuProps => ({
items: window.fontList.map((font, idx) => ({
key: String(idx),
text: font === "" ? intl.get("default") : font,
canCheck: true,
checked: this.state.fontFamily === font,
onClick: () => this.setFont(font)
}))
})
updateTextDirection = (direction: SourceTextDirection) => {
this.props.updateSourceTextDirection(this.props.source, direction)
}
@ -154,10 +167,17 @@ class Article extends React.Component<ArticleProps, ArticleState> {
},
{
key: "fontMenu",
text: intl.get("article.font"),
iconProps: { iconName: "Font" },
disabled: this.state.loadWebpage,
subMenuProps: this.fontFamilyMenuProps(),
},
{
key: "fontSizeMenu",
text: intl.get("article.fontSize"),
iconProps: { iconName: "FontSize" },
disabled: this.state.loadWebpage,
subMenuProps: this.fontMenuProps(),
subMenuProps: this.fontSizeMenuProps(),
},
{
key: "directionMenu",
@ -334,7 +354,9 @@ class Article extends React.Component<ArticleProps, ArticleState> {
</>
)
)
return `article/article.html?a=${a}&h=${h}&s=${
return `article/article.html?a=${a}&h=${h}&f=${
encodeURIComponent(this.state.fontFamily)
}&s=${
this.state.fontSize
}&d=${
this.props.source.textDir

View File

@ -26,6 +26,11 @@ window.utils.addMainContextListener((pos, text) => {
store.dispatch(openTextMenu(pos, text))
})
window.fontList = [""]
window.utils.initFontList().then((fonts) => {
window.fontList.push(...fonts)
})
ReactDOM.render(
<Provider store={store}>
<Root />

View File

@ -122,6 +122,14 @@ ipcMain.handle("set-font-size", (_, size: number) => {
store.set(FONT_SIZE_STORE_KEY, size)
})
const FONT_STORE_KEY = "fontFamily"
ipcMain.on("get-font", event => {
event.returnValue = store.get(FONT_STORE_KEY, "")
})
ipcMain.handle("set-font", (_, font: string) => {
store.set(FONT_STORE_KEY, font)
})
ipcMain.on("get-all-settings", event => {
let output = {}
for (let [key, value] of store) {

View File

@ -10,6 +10,7 @@ import { WindowManager } from "./window"
import fs = require("fs")
import { ImageCallbackTypes, TouchBarTexts } from "../schema-types"
import { initMainTouchBar } from "./touchbar"
import fontList = require('font-list')
export function setUtilsListeners(manager: WindowManager) {
async function openExternal(url: string, background = false) {
@ -283,4 +284,10 @@ export function setUtilsListeners(manager: WindowManager) {
ipcMain.handle("touchbar-destroy", () => {
if (manager.hasWindow()) manager.mainWindow.setTouchBar(null)
})
ipcMain.handle("init-font-list", () => {
return fontList.getFonts({
disableQuoting: true,
})
})
}

View File

@ -88,6 +88,7 @@ export type SchemaTypes = {
locale: string
sourceGroups: SourceGroup[]
fontSize: number
fontFamily: string
menuOn: boolean
fetchInterval: number
searchEngine: SearchEngines

View File

@ -18,6 +18,7 @@
"confirmMarkAll": "Do you really want to mark all articles on this page as read?",
"confirm": "Confirm",
"cancel": "Cancel",
"default": "Default",
"time": {
"now": "now",
"m": "m",
@ -70,7 +71,8 @@
"textDir": "Text direction",
"LTR": "Left-to-right",
"RTL": "Right-to-left",
"Vertical": "Vertical"
"Vertical": "Vertical",
"font": "Font"
},
"context": {
"share": "Share",

View File

@ -18,6 +18,7 @@
"confirmMarkAll": "确认将本页所有文章标为已读?",
"confirm": "确认",
"cancel": "取消",
"default": "默认",
"time": {
"now": "now",
"m": "m",
@ -70,7 +71,8 @@
"textDir": "文本方向",
"LTR": "从左到右",
"RTL": "从右到左",
"Vertical": "纵书"
"Vertical": "纵书",
"font": "字体"
},
"context": {
"share": "分享",

View File

@ -18,6 +18,7 @@
"confirmMarkAll": "確認將本頁所有文章標為已讀?",
"confirm": "確認",
"cancel": "取消",
"default": "預設",
"time": {
"now": "now",
"m": "m",
@ -70,7 +71,8 @@
"textDir": "文本方向",
"LTR": "從左到右",
"RTL": "從右到左",
"Vertical": "縱書"
"Vertical": "縱書",
"font": "字體"
},
"context": {
"share": "分享",

View File

@ -23,6 +23,9 @@ module.exports = [
path: __dirname + "/dist",
filename: "electron.js",
},
node: {
__dirname: false
},
plugins: [new HardSourceWebpackPlugin()],
},
{