mirror of https://github.com/heyman/heynote.git
Add functionality for selecting a custom path for the buffer file. (#130)
Automatically reload the buffer file (if one exists) when buffer path is changed. Move code buffer related code from main/index.ts into buffer.js
This commit is contained in:
parent
a94415ab65
commit
b9fd161551
|
@ -1,17 +1,23 @@
|
|||
import fs from "fs"
|
||||
import { join, dirname, basename } from "path"
|
||||
import { app } from "electron"
|
||||
import { app, ipcMain, dialog } from "electron"
|
||||
import * as jetpack from "fs-jetpack";
|
||||
|
||||
import CONFIG from "../config"
|
||||
import { isDev } from "../detect-platform"
|
||||
import { win } from "./index"
|
||||
import { eraseInitialContent, initialContent, initialDevContent } from '../initial-content'
|
||||
|
||||
|
||||
export function constructBufferFilePath(directoryPath) {
|
||||
return join(directoryPath, isDev ? "buffer-dev.txt" : "buffer.txt")
|
||||
}
|
||||
|
||||
export function getBufferFilePath() {
|
||||
let defaultPath = app.getPath("userData")
|
||||
let configPath = CONFIG.get("settings.bufferPath")
|
||||
let bufferPath = configPath.length ? configPath : defaultPath
|
||||
let bufferFilePath = join(bufferPath, isDev ? "buffer-dev.txt" : "buffer.txt")
|
||||
let bufferFilePath = constructBufferFilePath(bufferPath)
|
||||
try {
|
||||
// use realpathSync to resolve a potential symlink
|
||||
return fs.realpathSync(bufferFilePath)
|
||||
|
@ -73,10 +79,82 @@ export class Buffer {
|
|||
|
||||
if (this._lastSavedContent !== content) {
|
||||
// file has changed on disk, trigger onChange
|
||||
this.onChange({filename, eventType, content})
|
||||
this.onChange(content)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
close() {
|
||||
if (this.watcher) {
|
||||
this.watcher.close()
|
||||
this.watcher = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Buffer
|
||||
let buffer
|
||||
export function loadBuffer() {
|
||||
if (buffer) {
|
||||
buffer.close()
|
||||
}
|
||||
buffer = new Buffer({
|
||||
filePath: getBufferFilePath(),
|
||||
onChange: (content) => {
|
||||
win?.webContents.send("buffer-content:change", content)
|
||||
},
|
||||
})
|
||||
return buffer
|
||||
}
|
||||
|
||||
ipcMain.handle('buffer-content:load', async () => {
|
||||
if (buffer.exists() && !(eraseInitialContent && isDev)) {
|
||||
return await buffer.load()
|
||||
} else {
|
||||
return isDev ? initialDevContent : initialContent
|
||||
}
|
||||
});
|
||||
|
||||
async function save(content) {
|
||||
return await buffer.save(content)
|
||||
}
|
||||
|
||||
ipcMain.handle('buffer-content:save', async (event, content) => {
|
||||
return await save(content)
|
||||
});
|
||||
|
||||
export let contentSaved = false
|
||||
ipcMain.handle('buffer-content:saveAndQuit', async (event, content) => {
|
||||
await save(content)
|
||||
contentSaved = true
|
||||
app.quit()
|
||||
})
|
||||
|
||||
ipcMain.handle("buffer-content:selectLocation", async () => {
|
||||
let result = await dialog.showOpenDialog({
|
||||
title: "Select directory to store buffer",
|
||||
properties: [
|
||||
"openDirectory",
|
||||
"createDirectory",
|
||||
"noResolveAliases",
|
||||
],
|
||||
})
|
||||
if (result.canceled) {
|
||||
return
|
||||
}
|
||||
const filePath = result.filePaths[0]
|
||||
if (fs.existsSync(constructBufferFilePath(filePath))) {
|
||||
if (dialog.showMessageBoxSync({
|
||||
type: "question",
|
||||
message: "The selected directory already contains a buffer file. It will be loaded. Do you want to continue?",
|
||||
buttons: ["Cancel", "Continue"],
|
||||
}) === 0) {
|
||||
return
|
||||
}
|
||||
}
|
||||
return filePath
|
||||
})
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { app, BrowserWindow, Tray, shell, ipcMain, Menu, nativeTheme, globalShortcut, nativeImage } from 'electron'
|
||||
import { release } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import fs from "fs"
|
||||
|
||||
import { menu, getTrayMenu } from './menu'
|
||||
import { eraseInitialContent, initialContent, initialDevContent } from '../initial-content'
|
||||
import { WINDOW_CLOSE_EVENT, SETTINGS_CHANGE_EVENT } from '../constants';
|
||||
import CONFIG from "../config"
|
||||
import { onBeforeInputEvent } from "../keymap"
|
||||
import { isDev, isMac, isWindows } from '../detect-platform';
|
||||
import { initializeAutoUpdate, checkForUpdates } from './auto-update';
|
||||
import { fixElectronCors } from './cors';
|
||||
import { getBufferFilePath, Buffer } from './buffer';
|
||||
import { loadBuffer, contentSaved } from './buffer';
|
||||
|
||||
|
||||
// The built directory structure
|
||||
|
@ -57,7 +57,6 @@ const url = process.env.VITE_DEV_SERVER_URL
|
|||
const indexHtml = join(process.env.DIST, 'index.html')
|
||||
|
||||
let currentKeymap = CONFIG.get("settings.keymap")
|
||||
let contentSaved = false
|
||||
|
||||
// if this version is a beta version, set the release channel to beta
|
||||
const isBetaVersion = app.getVersion().includes("beta")
|
||||
|
@ -250,43 +249,18 @@ ipcMain.handle('dark-mode:set', (event, mode) => {
|
|||
|
||||
ipcMain.handle('dark-mode:get', () => nativeTheme.themeSource)
|
||||
|
||||
// load buffer on app start
|
||||
loadBuffer()
|
||||
|
||||
const buffer = new Buffer({
|
||||
filePath: getBufferFilePath(),
|
||||
onChange: (eventData) => {
|
||||
win?.webContents.send("buffer-content:change", eventData)
|
||||
},
|
||||
})
|
||||
|
||||
ipcMain.handle('buffer-content:load', async () => {
|
||||
if (buffer.exists() && !(eraseInitialContent && isDev)) {
|
||||
return await buffer.load()
|
||||
} else {
|
||||
return isDev ? initialDevContent : initialContent
|
||||
}
|
||||
});
|
||||
|
||||
async function save(content) {
|
||||
return await buffer.save(content)
|
||||
}
|
||||
|
||||
ipcMain.handle('buffer-content:save', async (event, content) => {
|
||||
return await save(content)
|
||||
});
|
||||
|
||||
ipcMain.handle('buffer-content:saveAndQuit', async (event, content) => {
|
||||
await save(content)
|
||||
contentSaved = true
|
||||
app.quit()
|
||||
})
|
||||
|
||||
ipcMain.handle('settings:set', (event, settings) => {
|
||||
ipcMain.handle('settings:set', async (event, settings) => {
|
||||
if (settings.keymap !== CONFIG.get("settings.keymap")) {
|
||||
currentKeymap = settings.keymap
|
||||
}
|
||||
let globalHotkeyChanged = settings.enableGlobalHotkey !== CONFIG.get("settings.enableGlobalHotkey") || settings.globalHotkey !== CONFIG.get("settings.globalHotkey")
|
||||
let showInDockChanged = settings.showInDock !== CONFIG.get("settings.showInDock");
|
||||
let showInMenuChanged = settings.showInMenu !== CONFIG.get("settings.showInMenu");
|
||||
let bufferPathChanged = settings.bufferPath !== CONFIG.get("settings.bufferPath");
|
||||
CONFIG.set("settings", settings)
|
||||
|
||||
win?.webContents.send(SETTINGS_CHANGE_EVENT, settings)
|
||||
|
@ -300,4 +274,10 @@ ipcMain.handle('settings:set', (event, settings) => {
|
|||
if (showInMenuChanged) {
|
||||
registerShowInMenu()
|
||||
}
|
||||
if (bufferPathChanged) {
|
||||
const buffer = loadBuffer()
|
||||
if (buffer.exists()) {
|
||||
win?.webContents.send("buffer-content:change", await buffer.load())
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -58,6 +58,10 @@ contextBridge.exposeInMainWorld("heynote", {
|
|||
onChangeCallback(callback) {
|
||||
ipcRenderer.on("buffer-content:change", callback)
|
||||
},
|
||||
|
||||
async selectLocation() {
|
||||
return await ipcRenderer.invoke("buffer-content:selectLocation")
|
||||
}
|
||||
},
|
||||
|
||||
settings: CONFIG.get("settings"),
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
window.document.addEventListener("currenciesLoaded", this.onCurrenciesLoaded)
|
||||
|
||||
// set up buffer change listener
|
||||
window.heynote.buffer.onChangeCallback((event, {filename, content, eventType}) => {
|
||||
window.heynote.buffer.onChangeCallback((event, content) => {
|
||||
diskContent = content
|
||||
this.editor.setContent(content)
|
||||
})
|
||||
|
|
|
@ -32,9 +32,11 @@
|
|||
showInMenu: this.initialSettings.showInMenu,
|
||||
bracketClosing: this.initialSettings.bracketClosing,
|
||||
autoUpdate: this.initialSettings.autoUpdate,
|
||||
bufferPath: this.initialSettings.bufferPath,
|
||||
|
||||
activeTab: "general",
|
||||
isWebApp: window.heynote.isWebApp,
|
||||
customBufferLocation: !!this.initialSettings.bufferPath,
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -66,8 +68,24 @@
|
|||
showInMenu: this.showInMenu || !this.showInDock,
|
||||
autoUpdate: this.autoUpdate,
|
||||
bracketClosing: this.bracketClosing,
|
||||
bufferPath: this.bufferPath,
|
||||
})
|
||||
},
|
||||
|
||||
async selectBufferLocation() {
|
||||
const path = await window.heynote.buffer.selectLocation()
|
||||
if (path) {
|
||||
this.bufferPath = path
|
||||
this.updateSettings()
|
||||
}
|
||||
},
|
||||
|
||||
onCustomBufferLocationChange() {
|
||||
if (!this.customBufferLocation) {
|
||||
this.bufferPath = ""
|
||||
this.updateSettings()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -166,6 +184,26 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-if="!isWebApp">
|
||||
<div class="entry buffer-location">
|
||||
<h2>Buffer File Path</h2>
|
||||
<label class="keyboard-shortcut-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="customBufferLocation"
|
||||
@change="onCustomBufferLocationChange"
|
||||
/>
|
||||
Use custom buffer file location
|
||||
</label>
|
||||
<div class="file-path">
|
||||
<button
|
||||
:disabled="!customBufferLocation"
|
||||
@click="selectBufferLocation"
|
||||
>Select Directory</button>
|
||||
<span class="path" v-show="customBufferLocation && bufferPath">{{ bufferPath }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</TabContent>
|
||||
|
||||
<TabContent tab="editing" :activeTab="activeTab">
|
||||
|
@ -318,6 +356,8 @@
|
|||
.entry
|
||||
margin-bottom: 24px
|
||||
margin-right: 20px
|
||||
&:last-child
|
||||
margin-right: 0
|
||||
h2
|
||||
font-weight: 600
|
||||
margin-bottom: 10px
|
||||
|
@ -335,6 +375,27 @@
|
|||
position: relative
|
||||
top: 2px
|
||||
left: -3px
|
||||
.buffer-location
|
||||
width: 100%
|
||||
.file-path
|
||||
display: flex
|
||||
> button
|
||||
flex-shrink: 0
|
||||
padding: 3px 8px
|
||||
.path
|
||||
flex-grow: 1
|
||||
margin-left: 10px
|
||||
font-size: 12px
|
||||
font-family: "Hack"
|
||||
padding: 5px 8px
|
||||
border-radius: 3px
|
||||
background: #f1f1f1
|
||||
color: #555
|
||||
white-space: nowrap
|
||||
overflow-x: auto
|
||||
+dark-mode
|
||||
background: #222
|
||||
color: #aaa
|
||||
.bottom-bar
|
||||
border-radius: 0 0 5px 5px
|
||||
background: #eee
|
||||
|
|
Loading…
Reference in New Issue