diff --git a/src/main/config.js b/src/main/config.js index e310a51f..a71ecd33 100644 --- a/src/main/config.js +++ b/src/main/config.js @@ -12,7 +12,8 @@ export const editorWinOptions = { useContentSize: true, show: true, frame: false, - titleBarStyle: 'hiddenInset' + titleBarStyle: 'hiddenInset', + zoomFactor: 1.0 } export const defaultPreferenceWinOptions = { @@ -31,7 +32,8 @@ export const defaultPreferenceWinOptions = { show: false, frame: false, thickFrame: !isOsx, - titleBarStyle: 'hiddenInset' + titleBarStyle: 'hiddenInset', + zoomFactor: 1.0 } export const PANDOC_EXTENSIONS = [ diff --git a/src/main/index.js b/src/main/index.js index a23a6c91..5c3aa695 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -1,6 +1,6 @@ import './globalSetting' import path from 'path' -import { app } from 'electron' +import { app, dialog } from 'electron' import cli from './cli' import setupExceptionHandler, { initExceptionLogger } from './exceptionHandler' import log from 'electron-log' @@ -14,7 +14,7 @@ const initializeLogger = appEnvironment => { log.transports.rendererConsole = null log.transports.file.file = path.join(appEnvironment.paths.logPath, 'main.log') log.transports.file.level = getLogLevel() - log.transports.file.sync = false + log.transports.file.sync = true log.transports.file.init() initExceptionLogger() } @@ -48,7 +48,30 @@ if (!process.mas && process.env.NODE_ENV !== 'development') { // Mark Text environment is configured successfully. You can now access paths, use the logger etc. // Create other instances that need access to the modules from above. -const accessor = new Accessor(appEnvironment) +let accessor = null +try { + accessor = new Accessor(appEnvironment) +} catch (err) { + // Catch errors that may come from invalid configuration files like settings. + const msgHint = err.message.includes('Config schema violation') + ? 'This seems to be an issue with your configuration file(s). ' : '' + + log.error(`Loading Mark Text failed during initialization! ${msgHint}`) + log.error(err) + + const EXIT_ON_ERROR = !!process.env.MARKTEXT_EXIT_ON_ERROR + const SHOW_ERROR_DIALOG = !process.env.MARKTEXT_ERROR_INTERACTION + if (!EXIT_ON_ERROR && SHOW_ERROR_DIALOG) { + dialog.showErrorBox( + 'There was an error during loading', + `${msgHint}${err.message}\n\n${err.stack}` + ) + } + process.exit(1) +} + +// Use synchronous only to report errors in early stage of startup. +log.transports.file.sync = false // ----------------------------------------------- // Be careful when changing code before this line! diff --git a/src/main/menu/actions/window.js b/src/main/menu/actions/window.js index 1dbf6531..4874f605 100644 --- a/src/main/menu/actions/window.js +++ b/src/main/menu/actions/window.js @@ -5,3 +5,17 @@ export const toggleAlwaysOnTop = win => { ipcMain.emit('window-toggle-always-on-top', win) } } + +export const zoomIn = win => { + const { webContents } = win + const zoom = webContents.getZoomFactor() + // WORKAROUND: Electron#16018 + webContents.send('mt::window-zoom', Math.min(2.0, zoom + 0.125)) +} + +export const zoomOut = win => { + const { webContents } = win + const zoom = webContents.getZoomFactor() + // WORKAROUND: Electron#16018 + webContents.send('mt::window-zoom', Math.max(1.0, zoom - 0.125)) +} diff --git a/src/main/menu/templates/window.js b/src/main/menu/templates/window.js index eecf0740..93497b45 100755 --- a/src/main/menu/templates/window.js +++ b/src/main/menu/templates/window.js @@ -1,4 +1,4 @@ -import { toggleAlwaysOnTop } from '../actions/window' +import { toggleAlwaysOnTop, zoomIn, zoomOut } from '../actions/window' import { isOsx } from '../../config' export default function (keybindings) { @@ -18,6 +18,18 @@ export default function (keybindings) { } }, { type: 'separator' + }, { + label: 'Zoom In', + click (menuItem, browserWindow) { + zoomIn(browserWindow) + } + }, { + label: 'Zoom Out', + click (menuItem, browserWindow) { + zoomOut(browserWindow) + } + }, { + type: 'separator' }, { label: 'Toggle Full Screen', accelerator: keybindings.getAccelerator('viewToggleFullScreen'), diff --git a/src/main/preferences/index.js b/src/main/preferences/index.js index 7b08b6a6..df7ab1b9 100644 --- a/src/main/preferences/index.js +++ b/src/main/preferences/index.js @@ -27,6 +27,9 @@ class Preference extends EventEmitter { /** * @param {AppPaths} userDataPath The path instance. + * + * NOTE: This throws an exception when validation fails. + * */ constructor (paths) { super() diff --git a/src/main/preferences/schema.json b/src/main/preferences/schema.json index 7419daf3..31bf5ecf 100644 --- a/src/main/preferences/schema.json +++ b/src/main/preferences/schema.json @@ -4,7 +4,7 @@ "type": "boolean" }, "autoSaveDelay": { - "description": "General--How long do you want to save your document(ms)?", + "description": "General--The time in ms after a change that the file is saved.", "type": "number", "minimum": 1000 }, @@ -23,6 +23,11 @@ "description": "General--Open folder via menu in a new window.", "type": "boolean" }, + "hideScrollbar": { + "description": "General--Whether to hide scrollbars.", + "type": "boolean", + "default": false + }, "aidou": { "description": "General--Enable aidou", "type": "boolean" @@ -76,6 +81,11 @@ "minimum": 1.2, "default": 1.6 }, + "editorLineWidth": { + "description": "Editor--Defines the maximum editor area width. An empty string or suffixes of ch (characters), px (pixels) or % (percentage) are allowed.", + "type": "string", + "pattern": "^(?:$|[0-9]+(?:ch|px|%)$)" + }, "codeFontSize": { "description": "Editor--Font size in code Block, the range is 12 ~ 18", "type": "number", @@ -92,6 +102,7 @@ "monospace" ] }, + "autoPairBracket": { "description": "Editor--Automatically brackets when editing", "type": "boolean" diff --git a/src/main/windows/base.js b/src/main/windows/base.js index 52224d1e..377c36b1 100644 --- a/src/main/windows/base.js +++ b/src/main/windows/base.js @@ -72,7 +72,13 @@ class BaseWindow extends EventEmitter { // NOTE: Only send absolutely necessary values. Full settings are delay loaded. const { type } = this const { debug, paths } = env - const { codeFontFamily, codeFontSize, theme, titleBarStyle } = userPreference.getAll() + const { + codeFontFamily, + codeFontSize, + hideScrollbar, + theme, + titleBarStyle + } = userPreference.getAll() const baseUrl = process.env.NODE_ENV === 'development' ? `http://localhost:9091` @@ -87,6 +93,7 @@ class BaseWindow extends EventEmitter { // Settings url.searchParams.set('cff', codeFontFamily) url.searchParams.set('cfs', codeFontSize) + url.searchParams.set('hsb', hideScrollbar ? '1' : '0') url.searchParams.set('theme', theme) url.searchParams.set('tbs', titleBarStyle) diff --git a/src/main/windows/setting.js b/src/main/windows/setting.js index 2c0763b3..6d6a4b5a 100644 --- a/src/main/windows/setting.js +++ b/src/main/windows/setting.js @@ -1,5 +1,6 @@ import path from 'path' import { BrowserWindow, ipcMain } from 'electron' +import electronLocalshortcut from '@hfelix/electron-localshortcut' import BaseWindow, { WindowLifecycle, WindowType } from './base' import { centerWindowOptions } from './utils' import { TITLE_BAR_HEIGHT, defaultPreferenceWinOptions, isLinux, isOsx } from '../config' @@ -20,7 +21,7 @@ class SettingWindow extends BaseWindow { * @param {*} [options] BrowserWindow options. */ createWindow (options = {}) { - const { menu: appMenu, env, preferences } = this._accessor + const { menu: appMenu, env, keybindings, preferences } = this._accessor const winOptions = Object.assign({}, defaultPreferenceWinOptions, options) centerWindowOptions(winOptions) if (isLinux) { @@ -78,6 +79,13 @@ class SettingWindow extends BaseWindow { win.loadURL(this._buildUrlString(this.id, env, preferences)) win.setSheetOffset(TITLE_BAR_HEIGHT) + electronLocalshortcut.register( + win, + keybindings.getAccelerator('viewDevToggleDeveloperTools'), + () => { + win.webContents.toggleDevTools() + } + ) return win } } diff --git a/src/muya/lib/index.js b/src/muya/lib/index.js index d6e5b141..bba79e73 100644 --- a/src/muya/lib/index.js +++ b/src/muya/lib/index.js @@ -311,6 +311,7 @@ class Muya { if (needRender) { this.contentState.render() } + // Set quick insert hint visibility const hideQuickInsertHint = options['hideQuickInsertHint'] if (typeof hideQuickInsertHint !== 'undefined') { @@ -321,6 +322,7 @@ class Muya { this.container.classList.add('ag-show-quick-insert-hint') } } + if (options.bulletListMarker) { this.contentState.turndownConfig.bulletListMarker = options.bulletListMarker } diff --git a/src/muya/themes/default.css b/src/muya/themes/default.css index 1b7b66b3..5422a102 100644 --- a/src/muya/themes/default.css +++ b/src/muya/themes/default.css @@ -126,6 +126,7 @@ kbd { #ag-editor-id { max-width: var(--editorAreaWidth); + min-width: 400px; min-height: 100%; margin: 0 auto; padding: 20px 50px 100px 50px; diff --git a/src/renderer/bootstrap.js b/src/renderer/bootstrap.js index 85eb099f..6ee5f9f4 100644 --- a/src/renderer/bootstrap.js +++ b/src/renderer/bootstrap.js @@ -21,6 +21,7 @@ const parseUrlArgs = () => { const codeFontFamily = params.get('cff') const codeFontSize = params.get('cfs') const debug = params.get('debug') === '1' + const hideScrollbar = params.get('hsb') === '1' const theme = params.get('theme') const titleBarStyle = params.get('tbs') const userDataPath = params.get('udp') @@ -34,6 +35,7 @@ const parseUrlArgs = () => { initialState: { codeFontFamily, codeFontSize, + hideScrollbar, theme, titleBarStyle } diff --git a/src/renderer/components/editorWithTabs/editor.vue b/src/renderer/components/editorWithTabs/editor.vue index 9dc5a4c7..fc98188c 100644 --- a/src/renderer/components/editorWithTabs/editor.vue +++ b/src/renderer/components/editorWithTabs/editor.vue @@ -9,6 +9,7 @@