mirror of
https://github.com/heyman/heynote.git
synced 2025-01-22 05:48:47 +01:00
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 fs from "fs"
|
||||||
import { join, dirname, basename } from "path"
|
import { join, dirname, basename } from "path"
|
||||||
import { app } from "electron"
|
import { app, ipcMain, dialog } from "electron"
|
||||||
import * as jetpack from "fs-jetpack";
|
import * as jetpack from "fs-jetpack";
|
||||||
|
|
||||||
import CONFIG from "../config"
|
import CONFIG from "../config"
|
||||||
import { isDev } from "../detect-platform"
|
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() {
|
export function getBufferFilePath() {
|
||||||
let defaultPath = app.getPath("userData")
|
let defaultPath = app.getPath("userData")
|
||||||
let configPath = CONFIG.get("settings.bufferPath")
|
let configPath = CONFIG.get("settings.bufferPath")
|
||||||
let bufferPath = configPath.length ? configPath : defaultPath
|
let bufferPath = configPath.length ? configPath : defaultPath
|
||||||
let bufferFilePath = join(bufferPath, isDev ? "buffer-dev.txt" : "buffer.txt")
|
let bufferFilePath = constructBufferFilePath(bufferPath)
|
||||||
try {
|
try {
|
||||||
// use realpathSync to resolve a potential symlink
|
// use realpathSync to resolve a potential symlink
|
||||||
return fs.realpathSync(bufferFilePath)
|
return fs.realpathSync(bufferFilePath)
|
||||||
@ -73,10 +79,82 @@ export class Buffer {
|
|||||||
|
|
||||||
if (this._lastSavedContent !== content) {
|
if (this._lastSavedContent !== content) {
|
||||||
// file has changed on disk, trigger onChange
|
// 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 { app, BrowserWindow, Tray, shell, ipcMain, Menu, nativeTheme, globalShortcut, nativeImage } from 'electron'
|
||||||
import { release } from 'node:os'
|
import { release } from 'node:os'
|
||||||
import { join } from 'node:path'
|
import { join } from 'node:path'
|
||||||
|
import fs from "fs"
|
||||||
|
|
||||||
import { menu, getTrayMenu } from './menu'
|
import { menu, getTrayMenu } from './menu'
|
||||||
import { eraseInitialContent, initialContent, initialDevContent } from '../initial-content'
|
|
||||||
import { WINDOW_CLOSE_EVENT, SETTINGS_CHANGE_EVENT } from '../constants';
|
import { WINDOW_CLOSE_EVENT, SETTINGS_CHANGE_EVENT } from '../constants';
|
||||||
import CONFIG from "../config"
|
import CONFIG from "../config"
|
||||||
import { onBeforeInputEvent } from "../keymap"
|
import { onBeforeInputEvent } from "../keymap"
|
||||||
import { isDev, isMac, isWindows } from '../detect-platform';
|
import { isDev, isMac, isWindows } from '../detect-platform';
|
||||||
import { initializeAutoUpdate, checkForUpdates } from './auto-update';
|
import { initializeAutoUpdate, checkForUpdates } from './auto-update';
|
||||||
import { fixElectronCors } from './cors';
|
import { fixElectronCors } from './cors';
|
||||||
import { getBufferFilePath, Buffer } from './buffer';
|
import { loadBuffer, contentSaved } from './buffer';
|
||||||
|
|
||||||
|
|
||||||
// The built directory structure
|
// The built directory structure
|
||||||
@ -57,7 +57,6 @@ const url = process.env.VITE_DEV_SERVER_URL
|
|||||||
const indexHtml = join(process.env.DIST, 'index.html')
|
const indexHtml = join(process.env.DIST, 'index.html')
|
||||||
|
|
||||||
let currentKeymap = CONFIG.get("settings.keymap")
|
let currentKeymap = CONFIG.get("settings.keymap")
|
||||||
let contentSaved = false
|
|
||||||
|
|
||||||
// if this version is a beta version, set the release channel to beta
|
// if this version is a beta version, set the release channel to beta
|
||||||
const isBetaVersion = app.getVersion().includes("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)
|
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 () => {
|
ipcMain.handle('settings:set', async (event, settings) => {
|
||||||
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) => {
|
|
||||||
if (settings.keymap !== CONFIG.get("settings.keymap")) {
|
if (settings.keymap !== CONFIG.get("settings.keymap")) {
|
||||||
currentKeymap = settings.keymap
|
currentKeymap = settings.keymap
|
||||||
}
|
}
|
||||||
let globalHotkeyChanged = settings.enableGlobalHotkey !== CONFIG.get("settings.enableGlobalHotkey") || settings.globalHotkey !== CONFIG.get("settings.globalHotkey")
|
let globalHotkeyChanged = settings.enableGlobalHotkey !== CONFIG.get("settings.enableGlobalHotkey") || settings.globalHotkey !== CONFIG.get("settings.globalHotkey")
|
||||||
let showInDockChanged = settings.showInDock !== CONFIG.get("settings.showInDock");
|
let showInDockChanged = settings.showInDock !== CONFIG.get("settings.showInDock");
|
||||||
let showInMenuChanged = settings.showInMenu !== CONFIG.get("settings.showInMenu");
|
let showInMenuChanged = settings.showInMenu !== CONFIG.get("settings.showInMenu");
|
||||||
|
let bufferPathChanged = settings.bufferPath !== CONFIG.get("settings.bufferPath");
|
||||||
CONFIG.set("settings", settings)
|
CONFIG.set("settings", settings)
|
||||||
|
|
||||||
win?.webContents.send(SETTINGS_CHANGE_EVENT, settings)
|
win?.webContents.send(SETTINGS_CHANGE_EVENT, settings)
|
||||||
@ -300,4 +274,10 @@ ipcMain.handle('settings:set', (event, settings) => {
|
|||||||
if (showInMenuChanged) {
|
if (showInMenuChanged) {
|
||||||
registerShowInMenu()
|
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) {
|
onChangeCallback(callback) {
|
||||||
ipcRenderer.on("buffer-content:change", callback)
|
ipcRenderer.on("buffer-content:change", callback)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async selectLocation() {
|
||||||
|
return await ipcRenderer.invoke("buffer-content:selectLocation")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
settings: CONFIG.get("settings"),
|
settings: CONFIG.get("settings"),
|
||||||
|
@ -71,7 +71,7 @@
|
|||||||
window.document.addEventListener("currenciesLoaded", this.onCurrenciesLoaded)
|
window.document.addEventListener("currenciesLoaded", this.onCurrenciesLoaded)
|
||||||
|
|
||||||
// set up buffer change listener
|
// set up buffer change listener
|
||||||
window.heynote.buffer.onChangeCallback((event, {filename, content, eventType}) => {
|
window.heynote.buffer.onChangeCallback((event, content) => {
|
||||||
diskContent = content
|
diskContent = content
|
||||||
this.editor.setContent(content)
|
this.editor.setContent(content)
|
||||||
})
|
})
|
||||||
|
@ -32,9 +32,11 @@
|
|||||||
showInMenu: this.initialSettings.showInMenu,
|
showInMenu: this.initialSettings.showInMenu,
|
||||||
bracketClosing: this.initialSettings.bracketClosing,
|
bracketClosing: this.initialSettings.bracketClosing,
|
||||||
autoUpdate: this.initialSettings.autoUpdate,
|
autoUpdate: this.initialSettings.autoUpdate,
|
||||||
|
bufferPath: this.initialSettings.bufferPath,
|
||||||
|
|
||||||
activeTab: "general",
|
activeTab: "general",
|
||||||
isWebApp: window.heynote.isWebApp,
|
isWebApp: window.heynote.isWebApp,
|
||||||
|
customBufferLocation: !!this.initialSettings.bufferPath,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -66,8 +68,24 @@
|
|||||||
showInMenu: this.showInMenu || !this.showInDock,
|
showInMenu: this.showInMenu || !this.showInDock,
|
||||||
autoUpdate: this.autoUpdate,
|
autoUpdate: this.autoUpdate,
|
||||||
bracketClosing: this.bracketClosing,
|
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>
|
</script>
|
||||||
@ -166,6 +184,26 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
|
|
||||||
<TabContent tab="editing" :activeTab="activeTab">
|
<TabContent tab="editing" :activeTab="activeTab">
|
||||||
@ -318,6 +356,8 @@
|
|||||||
.entry
|
.entry
|
||||||
margin-bottom: 24px
|
margin-bottom: 24px
|
||||||
margin-right: 20px
|
margin-right: 20px
|
||||||
|
&:last-child
|
||||||
|
margin-right: 0
|
||||||
h2
|
h2
|
||||||
font-weight: 600
|
font-weight: 600
|
||||||
margin-bottom: 10px
|
margin-bottom: 10px
|
||||||
@ -335,6 +375,27 @@
|
|||||||
position: relative
|
position: relative
|
||||||
top: 2px
|
top: 2px
|
||||||
left: -3px
|
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
|
.bottom-bar
|
||||||
border-radius: 0 0 5px 5px
|
border-radius: 0 0 5px 5px
|
||||||
background: #eee
|
background: #eee
|
||||||
|
Loading…
Reference in New Issue
Block a user