feat: auto load file when file content changed

This commit is contained in:
Jocs 2017-12-12 17:40:56 +08:00
parent 0ac3d779ba
commit 0438d68fac
9 changed files with 130 additions and 243 deletions

274
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -57,6 +57,7 @@
}, },
"dependencies": { "dependencies": {
"axios": "^0.16.1", "axios": "^0.16.1",
"chokidar": "^1.7.0",
"codemirror": "^5.31.0", "codemirror": "^5.31.0",
"electron-window-state": "^4.1.1", "electron-window-state": "^4.1.1",
"markdown-it": "^8.4.0", "markdown-it": "^8.4.0",

View File

@ -1,11 +1,29 @@
'use strict' 'use strict'
import fs from 'fs' import fs from 'fs'
import chokidar from 'chokidar'
import path from 'path' import path from 'path'
import { dialog, ipcMain, BrowserWindow } from 'electron' import { dialog, ipcMain, BrowserWindow } from 'electron'
import createWindow from './createWindow' import createWindow from './createWindow'
import { EXTENSIONS } from './config' import { EXTENSIONS } from './config'
const watchAndReload = (pathname, win) => {
const watcher = chokidar.watch(pathname, {
persistent: true
})
const filename = path.basename(pathname)
watcher.on('change', path => {
fs.readFile(pathname, 'utf-8', (err, file) => {
if (err) return console.log(err)
win.webContents.send('AGANI::file-change', {
file,
filename,
pathname
})
})
})
}
ipcMain.on('AGANI:response-file-save', (e, { markdown, pathname }) => { ipcMain.on('AGANI:response-file-save', (e, { markdown, pathname }) => {
const win = BrowserWindow.fromWebContents(e.sender) const win = BrowserWindow.fromWebContents(e.sender)
if (pathname) { if (pathname) {
@ -21,9 +39,9 @@ ipcMain.on('AGANI:response-file-save', (e, { markdown, pathname }) => {
const filename = path.basename(filePath) const filename = path.basename(filePath)
fs.writeFile(filePath, markdown, 'utf-8', err => { fs.writeFile(filePath, markdown, 'utf-8', err => {
if (err) return console.log('save as file failed') if (err) return console.log('save as file failed')
win.setTitle(filename)
e.sender.send('AGANI::set-pathname', { pathname: filePath, filename }) e.sender.send('AGANI::set-pathname', { pathname: filePath, filename })
}) })
watchAndReload(filePath, win)
} }
} }
}) })
@ -36,7 +54,10 @@ export const open = win => {
extensions: EXTENSIONS extensions: EXTENSIONS
}] }]
}) })
createWindow(filename[0]) if (filename && filename[0]) {
const newWindow = createWindow(filename[0])
watchAndReload(filename[0], newWindow)
}
} }
export const newFile = () => { export const newFile = () => {

View File

@ -32,7 +32,6 @@ const createWindow = (pathname, options = {}) => {
win.show() win.show()
if (pathname) { if (pathname) {
console.log(typeof pathname)
const filename = path.basename(pathname) const filename = path.basename(pathname)
fs.readFile(path.resolve(pathname), 'utf-8', (err, file) => { fs.readFile(path.resolve(pathname), 'utf-8', (err, file) => {
if (err) return console.log(err) if (err) return console.log(err)
@ -41,14 +40,18 @@ const createWindow = (pathname, options = {}) => {
filename, filename,
pathname pathname
}) })
win.setTitle(filename)
}) })
} else {
win.setTitle('Untitled')
} }
}) })
win.on('focus', () => {
win.webContents.send('AGANI::window-active-status', { status: true })
})
win.on('blur', () => {
win.webContents.send('AGANI::window-active-status', { status: false })
})
win.on('close', () => { // before closed win.on('close', () => { // before closed
if (windows.has(win.id)) { if (windows.has(win.id)) {
windows.delete(win.id) windows.delete(win.id)
@ -56,6 +59,7 @@ const createWindow = (pathname, options = {}) => {
}) })
windows.set(win.id, win) windows.set(win.id, win)
return win
} }
export default createWindow export default createWindow

View File

@ -2,6 +2,7 @@
<div class="editor-container"> <div class="editor-container">
<title-bar <title-bar
:filename="filename" :filename="filename"
:active="windowActive"
></title-bar> ></title-bar>
<editor <editor
:markdown="markdown" :markdown="markdown"
@ -21,12 +22,14 @@
TitleBar TitleBar
}, },
computed: { computed: {
...mapState(['filename', 'markdown']) ...mapState(['filename', 'markdown', 'windowActive'])
}, },
created () { created () {
this.$store.dispatch('LINTEN_WIN_STATUS')
this.$store.dispatch('LISTEN_FOR_SAVE') this.$store.dispatch('LISTEN_FOR_SAVE')
this.$store.dispatch('GET_FILENAME') this.$store.dispatch('GET_FILENAME')
this.$store.dispatch('LISTEN_FOR_FILE_LOAD') this.$store.dispatch('LISTEN_FOR_FILE_LOAD')
this.$store.dispatch('LISTEN_FOR_FILE_CHANGE')
} }
} }
</script> </script>

View File

@ -0,0 +1,2 @@
import Vue from 'vue'
export default new Vue()

View File

@ -5,6 +5,7 @@
<script> <script>
import Aganippe from '../../editor' import Aganippe from '../../editor'
import bus from '../bus'
export default { export default {
props: { props: {
@ -23,12 +24,7 @@
const ele = this.$refs.editor const ele = this.$refs.editor
this.editor = new Aganippe(ele) this.editor = new Aganippe(ele)
const unwatch = this.$watch('markdown', newValue => { bus.$on('file-loaded', this.handleFileLoaded)
if (newValue !== '' && this.editor) {
this.editor.setMarkdown(newValue)
unwatch()
}
})
this.editor.on('auto-save', markdown => { this.editor.on('auto-save', markdown => {
console.log('auto-save') console.log('auto-save')
@ -36,7 +32,13 @@
}) })
}) })
}, },
destroyed () { methods: {
handleFileLoaded (file) {
this.editor && this.editor.setMarkdown(file)
}
},
beforeDestroy () {
bus.$off('file-loaded', this.handleFileLoaded)
this.editor = null this.editor = null
} }
} }

View File

@ -1,5 +1,7 @@
<template> <template>
<div class="title-bar active"> <div class="title-bar"
:class="{'active': active}"
>
<div class="title"> <div class="title">
<img src="../assets/icons/markdown.svg" v-if="filename"> <img src="../assets/icons/markdown.svg" v-if="filename">
{{ filename }} {{ filename }}
@ -10,7 +12,8 @@
<script> <script>
export default { export default {
props: { props: {
filename: String filename: String,
active: Boolean
} }
} }
</script> </script>
@ -31,7 +34,7 @@
} }
.active { .active {
background: linear-gradient(180deg, #efefef, #ccc); background: linear-gradient(180deg, #efefef, #ccc);
color: #666; color: #333;
} }
img { img {
height: 90%; height: 90%;

View File

@ -1,13 +1,17 @@
import { ipcRenderer } from 'electron' import { ipcRenderer } from 'electron'
import bus from '../bus'
const state = { const state = {
filename: 'Untitled - unsaved', filename: 'Untitled - unsaved',
pathname: '', pathname: '',
isSaved: false, isSaved: false,
markdown: '' markdown: '',
windowActive: true
} }
const mutations = { const mutations = {
SET_WIN_STATUS (state, status) {
state.windowActive = status
},
SET_FILENAME (state, filename) { SET_FILENAME (state, filename) {
state.filename = filename state.filename = filename
}, },
@ -23,6 +27,12 @@ const mutations = {
} }
const actions = { const actions = {
LINTEN_WIN_STATUS ({ commit }) {
ipcRenderer.on('AGANI::window-active-status', (e, { status }) => {
console.log(status)
commit('SET_WIN_STATUS', status)
})
},
LISTEN_FOR_SAVE ({ commit, state }) { LISTEN_FOR_SAVE ({ commit, state }) {
ipcRenderer.on('AGANI::ask-file-save', () => { ipcRenderer.on('AGANI::ask-file-save', () => {
const { pathname, markdown } = state const { pathname, markdown } = state
@ -42,6 +52,19 @@ const actions = {
commit('SET_PATHNAME', pathname) commit('SET_PATHNAME', pathname)
commit('SET_MARKDOWN', file) commit('SET_MARKDOWN', file)
commit('SET_STATUS', true) commit('SET_STATUS', true)
bus.$emit('file-loaded', file)
})
},
LISTEN_FOR_FILE_CHANGE ({ commit, state }) {
ipcRenderer.on('AGANI::file-change', (e, { file, filename, pathname }) => {
const { windowActive } = state
commit('SET_FILENAME', filename)
commit('SET_PATHNAME', pathname)
commit('SET_MARKDOWN', file)
commit('SET_STATUS', true)
if (!windowActive) {
bus.$emit('file-loaded', file)
}
}) })
}, },
EDITE_FILE ({ commit }) { EDITE_FILE ({ commit }) {