From 55b6408cb703d1ede923e5bb79ff76358a6c6436 Mon Sep 17 00:00:00 2001 From: purocean Date: Fri, 25 Mar 2022 17:34:05 +0800 Subject: [PATCH] feat: add action bar --- src/renderer/components/ActionBar.vue | 137 ++++++++++++++++++ src/renderer/components/Layout.vue | 12 ++ src/renderer/components/Outline.vue | 107 ++++++++++++++ src/renderer/components/Preview.vue | 55 +------ src/renderer/components/SvgIcon.vue | 1 + src/renderer/components/Tree.vue | 1 - .../plugins/document-history-stack.ts | 2 + .../plugins/markdown-heading-number.ts | 20 +-- .../plugins/status-bar-control-center.ts | 1 + src/renderer/services/control-center.ts | 2 + src/renderer/services/layout.ts | 7 + src/renderer/services/view.ts | 30 ++++ src/renderer/support/store.ts | 4 + src/renderer/views/Main.vue | 16 +- src/share/i18n/languages/en.ts | 2 + src/share/i18n/languages/zh-CN.ts | 2 + 16 files changed, 336 insertions(+), 63 deletions(-) create mode 100644 src/renderer/components/ActionBar.vue create mode 100644 src/renderer/components/Outline.vue diff --git a/src/renderer/components/ActionBar.vue b/src/renderer/components/ActionBar.vue new file mode 100644 index 00000000..49d3df07 --- /dev/null +++ b/src/renderer/components/ActionBar.vue @@ -0,0 +1,137 @@ + + + + + diff --git a/src/renderer/components/Layout.vue b/src/renderer/components/Layout.vue index d296c780..ea9349ea 100644 --- a/src/renderer/components/Layout.vue +++ b/src/renderer/components/Layout.vue @@ -231,6 +231,18 @@ export default defineComponent({ flex: none; height: 100%; border-right: 1px solid var(--g-color-86); + display: flex; + flex-direction: column; + background: var(--g-color-98); + + ::v-deep(.action-bar .btns) { + opacity: 0; + transition: 0.2s; + } + + &:hover ::v-deep(.action-bar .btns) { + opacity: 1; + } } .sash-right { diff --git a/src/renderer/components/Outline.vue b/src/renderer/components/Outline.vue new file mode 100644 index 00000000..88bdcd6b --- /dev/null +++ b/src/renderer/components/Outline.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/src/renderer/components/Preview.vue b/src/renderer/components/Preview.vue index 3f6853ff..e7a818d9 100644 --- a/src/renderer/components/Preview.vue +++ b/src/renderer/components/Preview.vue @@ -26,15 +26,7 @@
-
- {{ head.text }} - {{head.tag}} -
+
TOP
@@ -55,7 +47,7 @@ import { registerHook, removeHook, triggerHook } from '@fe/core/hook' import { registerAction, removeAction } from '@fe/core/action' import { revealLineInCenter } from '@fe/services/editor' import { showExport, toUri } from '@fe/services/document' -import { getContextMenuItems } from '@fe/services/view' +import { getContextMenuItems, getHeadings, Heading } from '@fe/services/view' import { useContextMenu } from '@fe/support/ui/context-menu' import { DOM_ATTR_NAME } from '@fe/support/constant' import { useI18n } from '@fe/services/i18n' @@ -64,6 +56,7 @@ import type { RenderEnv } from '@fe/types' import Render from './Render.vue' import SvgIcon from './SvgIcon.vue' +import Outline from './Outline.vue' import 'highlight.js/styles/atom-one-dark.css' import 'katex/dist/katex.min.css' @@ -72,7 +65,7 @@ const logger = getLogger('preview') export default defineComponent({ name: 'xview', - components: { Render, SvgIcon }, + components: { Render, SvgIcon, Outline }, setup () { useI18n() @@ -93,13 +86,7 @@ export default defineComponent({ const width = ref(1024) const height = ref(1024) - const heads = ref<{ - tag: string; - class: string[]; - text: string; - level: number; - sourceLine: number; - }[]>([]) + const heads = ref([]) const todoCount = ref(0) const todoDoneCount = ref(0) const scrollTop = ref(0) @@ -122,18 +109,7 @@ export default defineComponent({ } function updateOutline () { - const tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] - const nodes = refView.value!.querySelectorAll(tags.join(',')) - heads.value = Array.from(nodes).map(node => { - const tag = node.tagName.toLowerCase() - return { - tag, - class: [...node.classList, 'tag-' + tag], - text: node.innerText, - level: tags.indexOf(tag), - sourceLine: parseInt(node.dataset.sourceLine || '0') - } - }) + heads.value = getHeadings() } function updateTodoCount () { @@ -447,25 +423,6 @@ export default defineComponent({ cursor: pointer; overflow: auto; overflow-x: hidden; - padding-bottom: 1em; - - & > div { - font-size: 14px; - line-height: 18px; - padding: 7px .5em; - display: flex; - border-radius: var(--g-border-radius); - - &:hover { - background: var(--g-color-75); - } - - .tag-name { - color: var(--g-color-60); - font-size: 12px; - padding-left: 0.5em; - } - } } .outline-title { diff --git a/src/renderer/components/SvgIcon.vue b/src/renderer/components/SvgIcon.vue index 28220170..d7c8023b 100644 --- a/src/renderer/components/SvgIcon.vue +++ b/src/renderer/components/SvgIcon.vue @@ -48,6 +48,7 @@ export default defineComponent({ 'star-solid': '', 'star-regular': '', 'pen-solid': '', + 'folder-tree-solid': '', } const name = props.name! diff --git a/src/renderer/components/Tree.vue b/src/renderer/components/Tree.vue index 85d39764..59ac8229 100644 --- a/src/renderer/components/Tree.vue +++ b/src/renderer/components/Tree.vue @@ -92,7 +92,6 @@ export default defineComponent({ width: 100%; box-sizing: border-box; overflow: auto; - background: var(--g-color-98); padding-bottom: 20px; } diff --git a/src/renderer/plugins/document-history-stack.ts b/src/renderer/plugins/document-history-stack.ts index 9bb19f54..34156816 100644 --- a/src/renderer/plugins/document-history-stack.ts +++ b/src/renderer/plugins/document-history-stack.ts @@ -93,6 +93,7 @@ export default { flat: true, title: ctx.i18n.t('control-center.navigation.back', ctx.command.getKeysLabel(backId)), disabled: idx <= 0, + showInActionBar: true, onClick: () => ctx.action.getActionHandler(backId)() }, { @@ -101,6 +102,7 @@ export default { flat: true, title: ctx.i18n.t('control-center.navigation.forward', ctx.command.getKeysLabel(forwardId)), disabled: idx >= stack.length - 1, + showInActionBar: true, onClick: () => ctx.action.getActionHandler(forwardId)() }, ) diff --git a/src/renderer/plugins/markdown-heading-number.ts b/src/renderer/plugins/markdown-heading-number.ts index 43ad520b..9a1994db 100644 --- a/src/renderer/plugins/markdown-heading-number.ts +++ b/src/renderer/plugins/markdown-heading-number.ts @@ -46,31 +46,31 @@ export default { counter(h6counter) ".\\0000a0\\0000a0"; } - .markdown-view .outline .tag-h1.show-number { counter-reset: outline-h2counter; } - .markdown-view .outline .tag-h2.show-number { counter-reset: outline-h3counter; } - .markdown-view .outline .tag-h3.show-number { counter-reset: outline-h4counter; } - .markdown-view .outline .tag-h4.show-number { counter-reset: outline-h5counter; } - .markdown-view .outline .tag-h5.show-number { counter-reset: outline-h6counter; } + .outline-toc .tag-h1.show-number { counter-reset: outline-h2counter; } + .outline-toc .tag-h2.show-number { counter-reset: outline-h3counter; } + .outline-toc .tag-h3.show-number { counter-reset: outline-h4counter; } + .outline-toc .tag-h4.show-number { counter-reset: outline-h5counter; } + .outline-toc .tag-h5.show-number { counter-reset: outline-h6counter; } - .markdown-view .outline .tag-h2.show-number:before { + .outline-toc .tag-h2.show-number:before { counter-increment: outline-h2counter; content: counter(outline-h2counter) ".\\0000a0\\0000a0"; } - .markdown-view .outline .tag-h3.show-number:before { + .outline-toc .tag-h3.show-number:before { counter-increment: outline-h3counter; content: counter(outline-h2counter) "." counter(outline-h3counter) ".\\0000a0\\0000a0"; } - .markdown-view .outline .tag-h4.show-number:before { + .outline-toc .tag-h4.show-number:before { counter-increment: outline-h4counter; content: counter(outline-h2counter) "." counter(outline-h3counter) "." counter(outline-h4counter) ".\\0000a0\\0000a0"; } - .markdown-view .outline .tag-h5.show-number:before { + .outline-toc .tag-h5.show-number:before { counter-increment: outline-h5counter; content: counter(outline-h2counter) "." counter(outline-h3counter) "." @@ -78,7 +78,7 @@ export default { counter(outline-h5counter) ".\\0000a0\\0000a0"; } - .markdown-view .outline .tag-h6.show-number:before { + .outline-toc .tag-h6.show-number:before { counter-increment: outline-h6counter; content: counter(outline-h2counter) "." counter(outline-h3counter) "." diff --git a/src/renderer/plugins/status-bar-control-center.ts b/src/renderer/plugins/status-bar-control-center.ts index a2d48671..8c48cfe9 100644 --- a/src/renderer/plugins/status-bar-control-center.ts +++ b/src/renderer/plugins/status-bar-control-center.ts @@ -111,6 +111,7 @@ export default { icon: 'search-solid', flat: true, title: ctx.i18n.t('control-center.navigation.goto', ctx.command.getKeysLabel('filter.show-quick-open')), + showInActionBar: true, onClick: () => { ctx.action.getActionHandler('filter.show-quick-open')() ctx.controlCenter.toggle(false) diff --git a/src/renderer/services/control-center.ts b/src/renderer/services/control-center.ts index bb9b61e5..510b4da2 100644 --- a/src/renderer/services/control-center.ts +++ b/src/renderer/services/control-center.ts @@ -12,6 +12,7 @@ export type Item = { icon: string, title: string, onClick?: () => void, + showInActionBar?: boolean, } export type SchemaItem = { items: Item[] } @@ -26,6 +27,7 @@ export type SchemaTapper = (schema: Schema) => void const _refresh = debounce(() => { getActionHandler('control-center.refresh')() + getActionHandler('action-bar.refresh')() }, 10) /** diff --git a/src/renderer/services/layout.ts b/src/renderer/services/layout.ts index 466b23c6..d8d0957d 100644 --- a/src/renderer/services/layout.ts +++ b/src/renderer/services/layout.ts @@ -67,6 +67,13 @@ export function toggleXterm (visible?: boolean) { } }) } +/** + * Toggle outline visible. + * @param visible + */ +export function toggleOutline (visible?: boolean) { + store.commit('setShowOutline', typeof visible === 'boolean' ? visible : !store.state.showOutline) +} registerAction({ name: 'layout.toggle-side', handler: toggleSide, keys: [Alt, 'e'] }) registerAction({ name: 'layout.toggle-editor', handler: toggleEditor, keys: [Alt, 'x'] }) diff --git a/src/renderer/services/view.ts b/src/renderer/services/view.ts index 83793f7e..2c2691fd 100644 --- a/src/renderer/services/view.ts +++ b/src/renderer/services/view.ts @@ -12,6 +12,13 @@ import { switchDoc } from './document' export type MenuItem = Components.ContextMenu.Item export type BuildContextMenu = (items: MenuItem[], e: MouseEvent) => void +export type Heading = { + tag: string; + class: string[]; + text: string; + level: number; + sourceLine: number; +} let tmpEnableSyncScroll = true let syncScrollTimer: any @@ -168,6 +175,29 @@ export function getViewDom () { return getActionHandler('view.get-view-dom')() } +/** + * Get Headings + */ +export function getHeadings (): Heading[] { + const tags = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'] + const dom = getViewDom() + if (!dom) { + return [] + } + + const nodes = dom.querySelectorAll(tags.join(',')) + return Array.from(nodes).map(node => { + const tag = node.tagName.toLowerCase() + return { + tag, + class: [...node.classList, 'tag-' + tag], + text: node.innerText, + level: tags.indexOf(tag), + sourceLine: parseInt(node.dataset.sourceLine || '0') + } + }) +} + /** * Get render env. * @returns diff --git a/src/renderer/support/store.ts b/src/renderer/support/store.ts index c655e0a3..d4af0c4d 100644 --- a/src/renderer/support/store.ts +++ b/src/renderer/support/store.ts @@ -11,6 +11,7 @@ export const initState = { showView: storage.get('showView', true), showEditor: storage.get('showEditor', true), showXterm: false, + showOutline: false, autoPreview: true, syncScroll: true, showSetting: false, @@ -88,6 +89,9 @@ export default createStore({ setShowXterm (state, data) { state.showXterm = data }, + setShowOutline (state, data) { + state.showOutline = data + }, setInComposition (state, data) { state.inComposition = data }, diff --git a/src/renderer/views/Main.vue b/src/renderer/views/Main.vue index df0bd3e0..515690d5 100644 --- a/src/renderer/views/Main.vue +++ b/src/renderer/views/Main.vue @@ -7,7 +7,9 @@ diff --git a/src/share/i18n/languages/en.ts b/src/share/i18n/languages/en.ts index b58abfae..ad38397b 100644 --- a/src/share/i18n/languages/en.ts +++ b/src/share/i18n/languages/en.ts @@ -26,6 +26,8 @@ const data = { 'close': 'Close', 'discard': 'Discard', 'edit': 'Edit', + 'outline': 'Outline', + 'files': 'Files', 'premium': { 'need-purchase': '[%s] Premium is required', 'buy-license': 'Buy License', diff --git a/src/share/i18n/languages/zh-CN.ts b/src/share/i18n/languages/zh-CN.ts index 0706926c..265b33c9 100644 --- a/src/share/i18n/languages/zh-CN.ts +++ b/src/share/i18n/languages/zh-CN.ts @@ -27,6 +27,8 @@ const data: BaseLanguage = { 'close': '关闭', 'edit': '编辑', 'discard': '放弃', + 'outline': '目录', + 'files': '文件', 'premium': { 'need-purchase': '[%s] 需要高级版', 'buy-license': '立即购买',