Skip to content

Commit

Permalink
Merge branch 'release/2.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
purocean committed Nov 29, 2019
2 parents 14de2fa + 2d68be1 commit 0cd5530
Show file tree
Hide file tree
Showing 14 changed files with 259 additions and 322 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@
+ [x] 使用 `Electron` 构建为桌面应用。不追求完全做成客户端,还是可以沿用 CS 架构。同样可以在浏览器中使用
+ [x] 支持嵌入 `draw.io` 文档
+ [x] 文件目录增加右键菜单
+ [ ] 支持打开多个文件
+ [ ] 支持使用快捷键打开常用文档
+ [ ] 全局剪切板功能
+ [x] 支持多标签打开多个文件
+ [ ] 拥有更友好的配置界面
+ [ ] 可以自定义快捷键

Expand Down Expand Up @@ -150,13 +148,16 @@ yarn run start

[Windows 商店下载](https://www.microsoft.com/zh-cn/p/yank-note-%e4%b8%80%e6%ac%be%e9%9d%a2%e5%90%91%e7%a8%8b%e5%ba%8f%e5%91%98%e7%9a%84-markdown-%e7%ac%94%e8%ae%b0%e5%ba%94%e7%94%a8/9n08bq8k8681?rtc=1#activetab=pivot:overviewtab)

### [v2.0.2](https://github.com/purocean/yn/releases/tag/v2.0.2) 2019-11-21
1. 修复相对链接解析
1. 图片增加背景色便于透明图片的阅读
### [v2.1.0](https://github.com/purocean/yn/releases/tag/v2.1.0) 2019-11-21
1. 增加多标签同时打开多个文件

<details>
<summary>展开查看更多版本记录</summary>

### [v2.0.2](https://github.com/purocean/yn/releases/tag/v2.0.2) 2019-11-21
1. 修复相对链接解析
1. 图片增加背景色便于透明图片的阅读

### [v2.0.1](https://github.com/purocean/yn/releases/tag/v2.0.1) 2019-11-20
1. 增加 2.0 计划
1. Electron 打包
Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"monaco-editor": "^0.17.1",
"normalize.css": "^8.0.1",
"socket.io-client": "^2.2.0",
"sortablejs": "^1.10.1",
"transliteration": "^2.1.3",
"turndown": "^5.0.3",
"vue": "^2.6.10",
Expand Down
6 changes: 1 addition & 5 deletions frontend/src/components/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,7 @@ export default {
this.saveFileOpenPositionDebounce(top)
},
toUri (file) {
if (file) {
return `yank-note://${file.repo}/${file.path.replace(/^\//, '')}`
} else {
return 'yank-note://system/blank.md'
}
return File.toUri(file)
},
async saveFile (f = null) {
const file = f || this.currentFile
Expand Down
83 changes: 83 additions & 0 deletions frontend/src/components/FileTabs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<template>
<Tabs :list="tabs" :value="current" @remove="removeTabs" @switch="switchTab" @change-list="setTabs"></Tabs>
</template>

<script>
import { mapState } from 'vuex'
import Tabs from './Tabs'
import File from '@/lib/file'
const blankUri = File.toUri(null)
export default {
name: 'file-tabs',
components: { Tabs },
data () {
return {
list: [],
current: blankUri
}
},
methods: {
setTabs (list) {
this.$store.commit('app/setTabs', list)
},
switchTab (item) {
this.switchFile(item.payload.file)
},
removeTabs (items) {
const keys = items.map(x => x.key)
const tabs = this.tabs.filter(x => keys.indexOf(x.key) === -1)
this.setTabs(tabs)
},
addTab (item) {
const tab = this.tabs.find(x => item.key === x.key)
// 没有打开此 Tab,新建一个
if (!tab) {
this.setTabs(this.tabs.concat([item]))
}
this.current = item.key
},
switchFile (file) {
this.$store.commit('app/setCurrentFile', file)
}
},
computed: {
...mapState('app', ['currentFile', 'tabs'])
},
watch: {
currentFile: {
immediate: true,
handler (file) {
const uri = File.toUri(file)
const item = {
key: uri,
label: file ? file.name : '空白页',
description: file ? file.path : '空白页',
payload: { file },
}
this.addTab(item)
}
},
tabs (list) {
if (list.length < 1) {
this.addTab({
key: blankUri,
label: '空白页',
description: '空白页',
payload: { file: null }
})
}
const tab = list.find(x => x.key === this.current)
if (!tab) {
const currentFile = list.length > 0 ? list[list.length - 1].payload.file : null
this.switchFile(currentFile)
}
}
}
}
</script>
2 changes: 2 additions & 0 deletions frontend/src/components/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ export default {
height: 100%;
position: relative;
flex: 1;
display: flex;
flex-direction: column;
}
.terminal {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Mask.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default {
height: 100%;
background: rgba(255, 255, 255, 0.089);
z-index: 99999;
padding-top: 4em;
padding-top: 6em;
}
.fade-enter-active, .fade-leave-active {
Expand Down
138 changes: 138 additions & 0 deletions frontend/src/components/Tabs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<template>
<div ref="tabs" class="tabs">
<div
v-for="item in list"
:key="item.key"
:class="{tab: true, current: item.key === value}"
:title="item.description"
:data-key="item.key"
@contextmenu.exact.prevent.stop="showContextMenu(item)"
@click="switchTab(item)">
<div class="label">{{item.label}}</div>
<div class="close" @click.prevent.stop="removeTabs([item])">
<y-icon class="close-icon" name="times" title="关闭"></y-icon>
</div>
</div>
</div>
</template>

<script>
import Sortable from 'sortablejs'
import 'vue-awesome/icons/times'
export default {
name: 'tabs',
props: {
value: String,
list: Array,
},
mounted () {
Sortable.create(this.$refs.tabs, {
animation: 250,
ghostClass: 'on-sort',
direction: 'horizontal',
onEnd: ({ oldIndex, newIndex }) => {
this.swapTab(oldIndex, newIndex)
}
})
},
methods: {
showContextMenu (item) {
this.$contextMenu.show([
{ id: 'close', label: '关闭', onClick: () => this.removeTabs([item]) },
{ id: 'close-other', label: '关闭其他', onClick: () => this.removeOther(item) },
{ id: 'close-right', label: '关闭到右侧', onClick: () => this.removeRight(item) },
{ id: 'close-left', label: '关闭到左侧', onClick: () => this.removeLeft(item) },
{ id: 'close-all', label: '全部关闭', onClick: () => this.removeAll(item) },
])
},
switchTab (item) {
if (item.key !== this.value) {
this.$emit('input', item.key)
this.$emit('switch', item)
}
},
removeOther (item) {
this.removeTabs(this.list.filter(x => x.key !== item.key))
},
removeRight (item) {
this.removeTabs(this.list.slice(this.list.findIndex(x => x.key === item.key) + 1))
},
removeLeft (item) {
this.removeTabs(this.list.slice(0, this.list.findIndex(x => x.key === item.key)))
},
removeAll () {
this.removeTabs(this.list)
},
removeTabs (items) {
this.$emit('remove', items)
},
swapTab (oldIndex, newIndex) {
const list = this.list
const tmp = list[oldIndex]
list[oldIndex] = list[newIndex]
list[newIndex] = tmp
this.$emit('change-list', list)
}
},
}
</script>

<style scoped>
.tabs {
flex: none;
height: 30px;
background: #333;
display: flex;
}
.tab {
width: 100%;
max-width: 150px;
display: flex;
justify-content: space-between;
align-items: center;
margin-right: 1px;
color: #888;
cursor: default;
font-size: 12px;
background: #282828;
overflow: hidden;
}
.label {
padding: 5px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.tab.current {
color: #eee;
background: #1d1f21;
}
.close {
color: #999;
height: 18px;
width: 18px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
margin-right: 5px;
}
.close:hover {
color: #aaa;
background: #444;
}
.close-icon {
zoom: .6;
}
.tab.on-sort {
background: rgb(112, 112, 112);
}
</style>
1 change: 1 addition & 0 deletions frontend/src/components/TitleBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ export default {
-webkit-user-select: none;
-webkit-app-region: drag;
position: relative;
z-index: 199999;
}
.resizer {
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/lib/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ const extname = path => {
return path.substr(path.lastIndexOf('.'))
}

const toUri = (file) => {
if (file && file.repo && file.path) {
return encodeURI(`yank-note://${file.repo}/${file.path.replace(/^\//, '')}`)
} else {
return 'yank-note://system/blank.md'
}
}

const decrypt = (content, password) => {
if (!password) {
throw new Error('未输入解密密码')
Expand Down Expand Up @@ -153,6 +161,7 @@ export default {
dirname,
basename,
extname,
toUri,
decrypt,
encrypt,
read,
Expand Down
11 changes: 6 additions & 5 deletions frontend/src/pages/Main.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
<StatusBar slot="footer"></StatusBar>
<Tree slot="left"></Tree>
<Xterm slot="terminal"></Xterm>
<Editor
ref="editor"
slot="editor"
@scroll-line="line => $refs.preview.revealLine(line)" />
<template slot="editor">
<FileTabs />
<Editor ref="editor" @scroll-line="line => $refs.preview.revealLine(line)" />
</template>
<Preview
ref="preview"
slot="preview"
Expand All @@ -23,6 +23,7 @@
import { mapState } from 'vuex'
import Layout from '@/components/Layout'
import TitleBar from '@/components/TitleBar'
import FileTabs from '@/components/FileTabs'
import StatusBar from '@/components/StatusBar'
import Tree from '@/components/Tree'
import Editor from '@/components/Editor'
Expand All @@ -33,7 +34,7 @@ import Xterm from '@/components/Xterm'
export default {
name: 'x-main',
components: { Layout, TitleBar, StatusBar, Tree, Editor, Preview, XFilter, Xterm },
components: { Layout, TitleBar, StatusBar, Tree, Editor, Preview, XFilter, Xterm, FileTabs },
mounted () {
RunPlugin.clearCache()
this.$bus.on('editor-ready', this.init)
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/store/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default {
currentRepo: Storage.get('currentRepo'),
currentFile: getLastOpenFile(Storage.get('currentRepo')),
recentOpenTime: Storage.get('recentOpenTime', {}),
tabs: Storage.get('tabs', []),
passwordHash: {},
documentInfo: {
textLength: 0,
Expand Down Expand Up @@ -77,6 +78,10 @@ export default {
state.showSide = data
Storage.set('showSide', data)
},
setTabs (state, data) {
state.tabs = data
Storage.set('tabs', data)
},
setShowXterm (state, data) {
state.showXterm = data
},
Expand Down
Loading

0 comments on commit 0cd5530

Please sign in to comment.