Skip to content

Commit

Permalink
Implement support for editing notes' metadata, and ability to move no…
Browse files Browse the repository at this point in the history
…tes into other directories.

Create separate pinia store for the editor cache functionality.
  • Loading branch information
heyman committed Sep 4, 2024
1 parent a9c962b commit d5dc476
Show file tree
Hide file tree
Showing 11 changed files with 512 additions and 52 deletions.
1 change: 1 addition & 0 deletions assets/icons/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions electron/main/file-library.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,15 @@ export class FileLibrary {
await this.jetpack.writeAsync(fullPath, content)
}

async move(path, newPath) {
if (await this.exists(newPath)) {
throw new Error(`File already exists: ${newPath}`)
}
const fullOldPath = join(this.basePath, path)
const fullNewPath = join(this.basePath, newPath)
await this.jetpack.moveAsync(fullOldPath, fullNewPath)
}

async getList() {
console.log("Loading notes")
const notes = {}
Expand Down Expand Up @@ -231,5 +240,9 @@ export function setupFileLibraryEventHandlers(library, win) {
app.quit()
})

ipcMain.handle('buffer:move', async (event, path, newPath) => {
return await library.move(path, newPath)
});

library.setupWatcher(win)
}
4 changes: 4 additions & 0 deletions electron/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ contextBridge.exposeInMainWorld("heynote", {
return await ipcRenderer.invoke("buffer:save", path, content)
},

async move(path, newPath) {
return await ipcRenderer.invoke("buffer:move", path, newPath)
},

async create(path, content) {
return await ipcRenderer.invoke("buffer:create", path, content)
},
Expand Down
13 changes: 11 additions & 2 deletions src/components/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import Settings from './settings/Settings.vue'
import ErrorMessages from './ErrorMessages.vue'
import NewNote from './NewNote.vue'
import EditNote from './EditNote.vue'
export default {
components: {
Expand All @@ -22,6 +23,7 @@
NoteSelector,
ErrorMessages,
NewNote,
EditNote,
},
data() {
Expand Down Expand Up @@ -67,6 +69,7 @@
showLanguageSelector(value) { this.dialogWatcher(value) },
showNoteSelector(value) { this.dialogWatcher(value) },
showCreateNote(value) { this.dialogWatcher(value) },
showEditNote(value) { this.dialogWatcher(value) },
currentNotePath() {
this.focusEditor()
Expand All @@ -79,10 +82,11 @@
"showLanguageSelector",
"showNoteSelector",
"showCreateNote",
"showEditNote",
]),
editorInert() {
return this.showCreateNote || this.showSettings
return this.showCreateNote || this.showSettings || this.showEditNote
},
},
Expand All @@ -92,6 +96,7 @@
"openNoteSelector",
"openCreateNote",
"closeDialog",
"closeNoteSelector",
"openNote",
]),
Expand Down Expand Up @@ -186,7 +191,7 @@
<NoteSelector
v-if="showNoteSelector"
@openNote="openNote"
@close="closeDialog"
@close="closeNoteSelector"
/>
<Settings
v-if="showSettings"
Expand All @@ -197,6 +202,10 @@
v-if="showCreateNote"
@close="closeDialog"
/>
<EditNote
v-if="showEditNote"
@close="closeDialog"
/>
<ErrorMessages />
</div>
</div>
Expand Down
274 changes: 274 additions & 0 deletions src/components/EditNote.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
<script>
import slugify from '@sindresorhus/slugify';
import { toRaw } from 'vue';
import { mapState, mapActions } from 'pinia'
import { useNotesStore } from "../stores/notes-store"
import FolderSelector from './folder-selector/FolderSelector.vue'
export default {
data() {
return {
name: "",
filename: "",
tags: [],
directoryTree: null,
parentPath: "",
errors: {
name: null,
},
}
},
components: {
FolderSelector
},
async mounted() {
this.$refs.nameInput.focus()
this.updateNotes()
console.log("EditNote mounted", this.currentNote)
this.name = this.currentNote.name
// build directory tree
const directories = await window.heynote.buffer.getDirectoryList()
const rootNode = {
name: "Heynote Root",
path: "",
children: [],
open: true,
}
const getNodeFromList = (list, part) => list.find(node => node.name === part)
directories.forEach((path) => {
const parts = path.split("/")
let currentLevel = rootNode
let currentParts = []
parts.forEach(part => {
currentParts.push(part)
let node = getNodeFromList(currentLevel.children, part)
if (node) {
currentLevel = node
} else {
const currentPath = currentParts.join("/")
node = {
name: part,
children: [],
path: currentPath,
open: this.currentNotePath.startsWith(currentPath),
}
currentLevel.children.push(node)
currentLevel = node
}
})
})
//console.log("tree:", rootNode)
this.directoryTree = rootNode
},
computed: {
...mapState(useNotesStore, [
"notes",
"currentNotePath",
]),
currentNote() {
return this.notes[this.currentNotePath]
},
currentNoteDirectory() {
return this.currentNotePath.split("/").slice(0, -1).join("/")
},
nameInputClass() {
return {
"name-input": true,
"error": this.errors.name,
}
}
},
methods: {
...mapActions(useNotesStore, [
"updateNotes",
"updateNoteMetadata",
]),
onKeydown(event) {
if (event.key === "Escape") {
this.$emit("close")
event.preventDefault()
} if (event.key === "Enter") {
this.submit()
event.preventDefault()
}
},
onInputKeydown(event) {
// redirect arrow keys and page up/down to folder selector
const redirectKeys = ["ArrowDown", "ArrowUp", "PageDown", "PageUp"]
if (redirectKeys.includes(event.key)) {
this.$refs.folderSelect.$el.dispatchEvent(new KeyboardEvent("keydown", {key: event.key}))
event.preventDefault()
}
},
submit() {
let slug = slugify(this.name)
if (slug === "") {
this.errors.name = true
return
}
const parentPathPrefix = this.parentPath === "" ? "" : this.parentPath + "/"
let path;
for (let i=0; i<1000; i++) {
let filename = slug + ".txt"
path = parentPathPrefix + filename
if (path === this.currentNotePath || !this.notes[path]) {
// file name is ok if it's the current note, or if it doesn't exist
break
}
slug = slugify(this.name + "-" + i)
}
if (path !== this.currentNotePath && this.notes[path]) {
console.error("Failed to edit note, path already exists", path)
this.errors.name = true
return
}
console.log("Update note", path)
this.updateNoteMetadata(this.currentNotePath, this.name, path)
this.$emit("close")
//this.$emit("create", this.$refs.input.value)
},
}
}
</script>

<template>
<div class="fader" @keydown.stop="onKeydown" tabindex="-1">
<form class="new-note" tabindex="-1" @focusout="onFocusOut" ref="container" @submit.prevent="submit">
<div class="container">
<h1>Edit Note</h1>
<input
placeholder="Name"
type="text"
v-model="name"
:class="nameInputClass"
ref="nameInput"
@keydown="onInputKeydown"
@input="errors.name = false"
/>

<label for="folder-select">Move to</label>
<FolderSelector
v-if="directoryTree"
:directoryTree="directoryTree"
:selectedPath="currentNoteDirectory"
id="folder-select"
v-model="parentPath"
ref="folderSelect"
/>
</div>
<div class="bottom-bar">
<button type="submit">Create Note</button>
</div>
</form>
</div>
</template>

<style scoped lang="sass">
.fader
position: fixed
top: 0
left: 0
bottom: 0
right: 0
background: rgba(0,0,0, 0.2)
.new-note
font-size: 13px
//background: #48b57e
background: #efefef
width: 420px
position: absolute
top: 0
left: 50%
transform: translateX(-50%)
border-radius: 0 0 5px 5px
box-shadow: 0 0 10px rgba(0,0,0,0.3)
display: flex
flex-direction: column
max-height: 100%
&:focus
outline: none
+dark-mode
background: #151516
box-shadow: 0 0 10px rgba(0,0,0,0.5)
color: rgba(255,255,255, 0.7)
+webapp-mobile
max-width: calc(100% - 80px)
.container
padding: 10px
min-height: 0
display: flex
flex-direction: column
h1
font-weight: bold
margin-bottom: 14px
label
display: block
margin-bottom: 6px
//padding-left: 2px
font-size: 12px
font-weight: 600
.name-input
width: 100%
background: #fff
padding: 4px 5px
border: 1px solid #ccc
box-sizing: border-box
border-radius: 2px
margin-bottom: 16px
&:focus
outline: none
border: 1px solid #fff
outline: 2px solid #48b57e
&.error
background: #ffe9e9
+dark-mode
background: #3b3b3b
color: rgba(255,255,255, 0.9)
border: 1px solid #5a5a5a
&:focus
border: 1px solid #3b3b3b
+webapp-mobile
font-size: 16px
max-width: 100%
.bottom-bar
border-radius: 0 0 5px 5px
//background: #e3e3e3
padding: 10px
padding-top: 0
display: flex
justify-content: flex-end
button
font-size: 12px
height: 28px
border: 1px solid #c5c5c5
border-radius: 3px
padding-left: 10px
padding-right: 10px
&:focus
outline-color: #48b57e
+dark-mode
background: #444
border: none
color: rgba(255,255,255, 0.75)
</style>
Loading

0 comments on commit d5dc476

Please sign in to comment.