Skip to content

Commit

Permalink
Merge branch 'release/3.42.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
purocean committed Nov 4, 2022
2 parents 8f0e1b7 + 65f19dd commit 9f18a1b
Show file tree
Hide file tree
Showing 34 changed files with 983 additions and 316 deletions.
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,20 @@ For more information on how to use the following functions, please see [characte

## Changelogs

### [v3.41.0](https://github.com/purocean/yn/releases/tag/v3.41.0) 2022-10-23

1. feat: extended support for automatic update
2. feat: optimize the effect of mind map exporting to PDF and printing
3. upd: update mirror to remove `mirror.ghproxy.com`
4. fix: fix the problem that the background color of the preview "Print" and "Export" buttons is too transparent
5. feat(plugin): `ctx.utils.downloadContent` supports passing in `Blob` object
6. refactor(plugin): refactor the export function and add the `ctx.export` module
7. refactor(plugin): remove `ctx.doc.print` method, add `ctx.export.printCurrentDocument` method
8. refactor(plugin): remove `ctx.doc.showExport` method, add `ctx.export.toggleExportPanel` method
9. refactor(plugin): remove `VIEW_BEFORE_EXPORT` Hook, add `EXPORT_BEFORE_PREPARE` `EXPORT_AFTER_PREPARE` Hooks
10. refactor(plugin): remove `ctx.base.forceReload` method, add `ctx.base.reloadMainWindow` method
### [v3.42.0](https://github.com/purocean/yn/releases/tag/v3.42.0) 2022-11-04

[Windows](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-win-x64-3.42.0.exe) | [macOS arm64](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-mac-arm64-3.42.0.dmg) | [macOS x86](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-mac-x64-3.42.0.dmg) | [Linux AppImage](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-linux-x86_64-3.42.0.AppImage) | [Linux deb](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-linux-amd64-3.42.0.deb)

1. feat: add start page
2. feat: support to preview images directly in the editor
3. feat: add an extension management button to the status bar
4. upd: optimize multi-monitor recovery window position logic on Windows
5. fix: fixed the problem that the terminal cannot be used when the terminal configuration is empty
6. fix: fix "Convert to link with title" may incorrectly replace text
7. feat(plugin): support for registering custom editors
8. feat(plugin): `triggerHook` supports ignoring errors
9. feat(plugin): add `ctx.base.getServerTimestamp` method
10. feat(plugin): add `DOC_BEFORE_SWITCH` `DOC_SWITCHING` Hooks

[More release notes](https://github.com/purocean/yn/releases)

Expand Down
26 changes: 14 additions & 12 deletions README_ZH-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,20 @@

## 更新日志

### [v3.41.0](https://github.com/purocean/yn/releases/tag/v3.41.0) 2022-10-23

1. feat: 扩展支持自动更新
2. feat: 优化思维导图导出 PDF 和打印的效果
3. upd: 更新镜像移除 `mirror.ghproxy.com`
4. fix: 修复预览“打印”“导出”按钮背景色过于透明问题
5. feat(plugin): `ctx.utils.downloadContent` 支持传入 `Blob` 对象
6. refactor(plugin): 重构导出功能,增加 `ctx.export` 模块
7. refactor(plugin): 移除 `ctx.doc.print` 方法,增加 `ctx.export.printCurrentDocument` 方法
8. refactor(plugin): 移除 `ctx.doc.showExport` 方法,增加 `ctx.export.toggleExportPanel` 方法
9. refactor(plugin): 移除 `VIEW_BEFORE_EXPORT` Hook,增加 `EXPORT_BEFORE_PREPARE` `EXPORT_AFTER_PREPARE` Hooks
10. refactor(plugin): 移除 `ctx.base.forceReload` 方法,增加 `ctx.base.reloadMainWindow` 方法
### [v3.42.0](https://github.com/purocean/yn/releases/tag/v3.42.0) 2022-11-04

[Windows](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-win-x64-3.42.0.exe) | [macOS arm64](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-mac-arm64-3.42.0.dmg) | [macOS x86](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-mac-x64-3.42.0.dmg) | [Linux AppImage](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-linux-x86_64-3.42.0.AppImage) | [Linux deb](https://github.com/purocean/yn/releases/download/v3.42.0/Yank-Note-linux-amd64-3.42.0.deb)

1. feat: 增加开始页面
2. feat: 支持在编辑器中直接预览图片
3. feat: 状态栏增加扩展管理按钮
4. upd: 优化 Windows 上多显示器恢复窗口位置逻辑
5. fix: 修复终端配置为空时不能使用终端问题
6. fix: 修复“转换为带标题的链接”可能错误替换文本问题
7. feat(plugin): 支持注册自定义编辑器
8. feat(plugin): `triggerHook` 支持忽略错误
9. feat(plugin): 增加 `ctx.base.getServerTimestamp` 方法
10. feat(plugin): 增加 `DOC_BEFORE_SWITCH` `DOC_SWITCHING` Hooks

[更多发布说明](https://github.com/purocean/yn/releases)

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yank.note",
"version": "3.41.0",
"version": "3.42.0",
"description": "Yank Note: A hackable markdown note application for programmers",
"main": "dist/main/app.js",
"license": "AGPL-3.0",
Expand Down Expand Up @@ -132,7 +132,7 @@
"typedoc": "^0.22.7",
"typescript": "^4.3.2",
"utility-types": "^3.10.0",
"viewerjs": "^1.10.5",
"viewerjs": "^1.11.0",
"vite": "^2.9.13",
"vue": "^3.2.23",
"vue-router": "^4.0.0-0",
Expand Down
123 changes: 115 additions & 8 deletions src/main/app.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { protocol, app, Menu, Tray, powerMonitor, dialog, OpenDialogOptions, shell, BrowserWindow } from 'electron'
import { protocol, app, Menu, Tray, powerMonitor, dialog, OpenDialogOptions, screen, shell, BrowserWindow, Display, Rectangle } from 'electron'
import type TBrowserWindow from 'electron'
import * as path from 'path'
import * as os from 'os'
Expand All @@ -18,6 +18,8 @@ import config from './config'
import { initProxy } from './proxy'
import { initEnvs } from './envs'

type WindowState = { maximized: boolean } & Rectangle

initProxy()
initEnvs()

Expand Down Expand Up @@ -85,9 +87,114 @@ const hideWindow = () => {
}

const restoreWindowBounds = () => {
const bounds = store.get('window.bounds', null)
if (bounds) {
win!.setBounds(bounds)
const state: WindowState = store.get('window.state', null)
if (state) {
if (state.maximized) {
win!.maximize()
} else {
const validateWindowState = (state: WindowState, displays: Display[]): WindowState | undefined => {
if (state.width <= 0 || state.height <= 0) {
return undefined
}

const getWorkingArea = (display: Display): Rectangle | undefined => {
if (display.workArea.width > 0 && display.workArea.height > 0) {
return display.workArea
}

if (display.bounds.width > 0 && display.bounds.height > 0) {
return display.bounds
}

return undefined
}

if (displays.length === 1) {
const displayWorkingArea = getWorkingArea(displays[0])
if (displayWorkingArea) {
const ensureStateInDisplayWorkingArea = (): void => {
if (!state || typeof state.x !== 'number' || typeof state.y !== 'number' || !displayWorkingArea) {
return
}

if (state.x < displayWorkingArea.x) {
// prevent window from falling out of the screen to the left
state.x = displayWorkingArea.x
}

if (state.y < displayWorkingArea.y) {
// prevent window from falling out of the screen to the top
state.y = displayWorkingArea.y
}
}

// ensure state is not outside display working area (top, left)
ensureStateInDisplayWorkingArea()

if (state.width > displayWorkingArea.width) {
// prevent window from exceeding display bounds width
state.width = displayWorkingArea.width
}

if (state.height > displayWorkingArea.height) {
// prevent window from exceeding display bounds height
state.height = displayWorkingArea.height
}

if (state.x > (displayWorkingArea.x + displayWorkingArea.width - 128)) {
// prevent window from falling out of the screen to the right with
// 128px margin by positioning the window to the far right edge of
// the screen
state.x = displayWorkingArea.x + displayWorkingArea.width - state.width
}

if (state.y > (displayWorkingArea.y + displayWorkingArea.height - 128)) {
// prevent window from falling out of the screen to the bottom with
// 128px margin by positioning the window to the far bottom edge of
// the screen
state.y = displayWorkingArea.y + displayWorkingArea.height - state.height
}

// again ensure state is not outside display working area
// (it may have changed from the previous validation step)
ensureStateInDisplayWorkingArea()
}

return state
}

// Multi Monitor (non-fullscreen): ensure window is within display bounds
let display: Display | undefined
let displayWorkingArea: Rectangle | undefined
try {
display = screen.getDisplayMatching({ x: state.x, y: state.y, width: state.width, height: state.height })
displayWorkingArea = getWorkingArea(display)
} catch (error) {
// Electron has weird conditions under which it throws errors
// e.g. https://github.com/microsoft/vscode/issues/100334 when
// large numbers are passed in
}

if (
display && // we have a display matching the desired bounds
displayWorkingArea && // we have valid working area bounds
state.x + state.width > displayWorkingArea.x && // prevent window from falling out of the screen to the left
state.y + state.height > displayWorkingArea.y && // prevent window from falling out of the screen to the top
state.x < displayWorkingArea.x + displayWorkingArea.width && // prevent window from falling out of the screen to the right
state.y < displayWorkingArea.y + displayWorkingArea.height // prevent window from falling out of the screen to the bottom
) {
return state
}

return undefined
}

const displays = screen.getAllDisplays()
const validatedState = validateWindowState(state, displays)
if (validatedState) {
win!.setBounds(validatedState)
}
}
}
}

Expand All @@ -96,10 +203,10 @@ const saveWindowBounds = () => {
const fullscreen = win.isFullScreen()
const maximized = win.isMaximized()

// save bounds only when not fullscreen and not maximized
if (!fullscreen && !maximized) {
const bounds = win.getBounds()
store.set('window.bounds', bounds)
// save bounds only when not fullscreen
if (!fullscreen) {
const state: WindowState = { ...win.getBounds(), maximized }
store.set('window.state', state)
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/main/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ const proxy = async (ctx: any, next: any) => {
} else {
ctx.status = response.statusCode
ctx.set('content-type', response.headers['content-type'])

Object.keys(response.headers).forEach((key) => {
ctx.set(`x-origin-${key}`, response.headers[key])
})

ctx.body = body
resolve()
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/shell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const CD_COMMAND_PREFIX = '--yank-note-run-command-cd--'
const defaultShell = os.platform() === 'win32' ? 'cmd.exe' : (process.env.SHELL || 'bash')

const getShell = () => {
const shell = config.get(configKey, defaultShell)
const shell = config.get(configKey, defaultShell) || defaultShell

// use full path
// TODO better way.
Expand Down
144 changes: 144 additions & 0 deletions src/renderer/components/DefaultEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<template>
<div class="editor-container">
<MonacoEditor ref="refEditor" class="editor" />
</div>
</template>

<script lang="ts">
import { defineComponent, nextTick, onBeforeMount, onMounted, ref, toRefs, watch } from 'vue'
import { useStore } from 'vuex'
import { registerHook, removeHook } from '@fe/core/hook'
import { isEncrypted, saveDoc, toUri } from '@fe/services/document'
import { getEditor, whenEditorReady } from '@fe/services/editor'
import type { Doc } from '@fe/types'
import MonacoEditor from './MonacoEditor.vue'
import { getSetting } from '@fe/services/setting'
export default defineComponent({
name: 'editor',
components: { MonacoEditor },
setup () {
let editorIsReady = false
const store = useStore()
let timer: number | null = null
const refEditor = ref<any>(null)
const { currentFile, currentContent } = toRefs(store.state)
const getMonacoEditor = () => refEditor.value
function setCurrentValue ({ uri, value }: { uri: string; value: any}) {
if (toUri(currentFile.value) === uri) {
store.commit('setCurrentContent', value)
}
}
function clearTimer () {
if (timer) {
window.clearTimeout(timer)
timer = null
}
}
async function saveFile (f: Doc | null = null) {
const file = f || currentFile.value
if (!(file && file.repo && file.path && file.status)) {
return
}
if (file.content === currentContent.value) {
return
}
if (!currentContent.value) {
return
}
if (file.repo === '__help__') {
return
}
clearTimer()
await saveDoc(file, currentContent.value)
}
function restartTimer () {
clearTimer()
if (!(currentFile.value && currentFile.value.repo && currentFile.value.path)) {
return
}
const autoSave = getSetting('auto-save', 2000)
if (!autoSave) {
return
}
timer = window.setTimeout(() => {
// prevent auto save encrypted file.
if (!currentFile.value || isEncrypted(currentFile.value)) {
return
}
saveFile()
}, autoSave)
}
async function changeFile (current?: Doc | null) {
clearTimer()
if (!editorIsReady) {
return
}
getMonacoEditor().setModel(toUri(current), current?.content ?? '\n')
await nextTick()
getEditor().updateOptions({
readOnly: !current || !current.plain
})
}
function resize () {
nextTick(() => getMonacoEditor().resize())
}
watch(currentFile, changeFile)
watch(currentContent, restartTimer)
onMounted(() => {
registerHook('GLOBAL_RESIZE', resize)
registerHook('EDITOR_CHANGE', setCurrentValue)
restartTimer()
})
onBeforeMount(() => {
removeHook('GLOBAL_RESIZE', resize)
removeHook('EDITOR_CHANGE', setCurrentValue)
})
whenEditorReady().then(({ editor, monaco }) => {
editorIsReady = true
if (currentFile.value) {
changeFile(currentFile.value)
}
editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {
saveFile()
})
})
return { refEditor }
}
})
</script>

<style scoped>
.editor-container {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
Loading

1 comment on commit 9f18a1b

@vercel
Copy link

@vercel vercel bot commented on 9f18a1b Nov 4, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

yn-api-doc – ./

yn-api-doc.vercel.app
yn-api-doc-purocean.vercel.app
yn-api-doc-git-master-purocean.vercel.app

Please sign in to comment.