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:
Jonatan Heyman 2024-01-05 00:41:46 +01:00 committed by GitHub
parent a94415ab65
commit b9fd161551
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 159 additions and 36 deletions

View File

@ -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
})

View File

@ -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())
}
}
})

View File

@ -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"),

View File

@ -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)
})

View File

@ -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