Skip to content

Commit

Permalink
feat: files panel + set / browse working directory + menu checkboxes …
Browse files Browse the repository at this point in the history
…sync
  • Loading branch information
NGPixel committed Feb 16, 2024
1 parent ed8090c commit 189dbc3
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 41 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@electron/remote": "2.1.0",
"@ietf-tools/idnits": "3.0.0-alpha.33",
"@quasar/extras": "1.16.9",
"lodash": "4.17.21",
"lodash-es": "4.17.21",
"luxon": "3.4.4",
"mitt": "3.0.1",
Expand Down
17 changes: 5 additions & 12 deletions src-electron/electron-main.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { app, BrowserWindow, ipcMain, nativeTheme, screen } from 'electron'
import { app, BrowserWindow, nativeTheme, screen } from 'electron'
import { initialize, enable } from '@electron/remote/main'
import path from 'path'
import os from 'os'

import { registerMenu } from './menu'
import {
saveDocument,
saveDocumentAs
} from './handlers'
import { registerCallbacks } from './handlers'

/**
* Merge new header with existing headers, handling lowercase header duplicates
Expand Down Expand Up @@ -35,6 +32,7 @@ try {
} catch (_) { }

let mainWindow
let mainMenu

function createWindow () {
initialize()
Expand Down Expand Up @@ -66,7 +64,7 @@ function createWindow () {
}
})

registerMenu(mainWindow)
mainMenu = registerMenu(mainWindow)
// mainWindow.setMenu(null)

enable(mainWindow.webContents)
Expand Down Expand Up @@ -100,12 +98,7 @@ function createWindow () {
mainWindow = null
})

ipcMain.on('save', (ev, opts) => {
saveDocument(mainWindow, opts.path, opts.data)
})
ipcMain.on('promptSaveAs', (ev, opts) => {
saveDocumentAs(mainWindow, opts.type, opts.fileName)
})
registerCallbacks(mainWindow, mainMenu)
}

app.whenReady().then(createWindow)
Expand Down
5 changes: 4 additions & 1 deletion src-electron/electron-preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ contextBridge.exposeInMainWorld('ipcBridge', {

subscribe (channel, callback) {
ipcRenderer.on(channel, callback)
}
},

promptWorkingDirectory: (current) => ipcRenderer.invoke('promptWorkingDirectory', { current }),
readDirectory: (dirPath) => ipcRenderer.invoke('readDirectory', { dirPath })
})
53 changes: 52 additions & 1 deletion src-electron/handlers.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { app, dialog } from 'electron'
import { app, dialog, ipcMain } from 'electron'
import fs from 'node:fs/promises'
import path from 'node:path'
import orderBy from 'lodash/orderBy'

export async function openDocument (mainWindow) {
const files = await dialog.showOpenDialog(mainWindow, {
Expand Down Expand Up @@ -82,3 +83,53 @@ export async function saveDocumentAs (mainWindow, type, defaultFileName) {
mainWindow.webContents.send('save', saveOpts.filePath)
}
}

export async function selectWorkingDirectory (mainWindow, current) {
const setWdOpts = await dialog.showOpenDialog(mainWindow, {
title: 'Set Working Directory...',
...(current && { defaultPath: current }),
properties: ['openDirectory', 'createDirectory', 'dontAddToRecent']
})
if (!setWdOpts.canceled && setWdOpts.filePaths.length > 0) {
return setWdOpts.filePaths[0]
} else {
return ''
}
}

export async function readDirectory (dirPath) {
const dirItems = []
const files = await fs.readdir(dirPath, { withFileTypes: true })
for (const file of files) {
if (!file.isDirectory() && !file.isFile()) { continue }
dirItems.push({
isDirectory: file.isDirectory(),
name: file.name,
path: path.join(file.path, file.name)
})
}
return orderBy(dirItems, ['isDirectory', 'name'], ['desc', 'asc'])
}

export function registerCallbacks (mainWindow, mainMenu) {
ipcMain.on('save', (ev, opts) => {
saveDocument(mainWindow, opts.path, opts.data)
})
ipcMain.on('promptSaveAs', (ev, opts) => {
saveDocumentAs(mainWindow, opts.type, opts.fileName)
})
ipcMain.handle('promptWorkingDirectory', async (ev, opts) => {
return selectWorkingDirectory(mainWindow, opts.current)
})
ipcMain.on('setMenuItemCheckedState', (ev, opts) => {
const mItem = mainMenu.getMenuItemById(opts.id)
if (mItem) {
mItem.checked = opts.value
} else {
dialog.showErrorBox('Internal Error', `Invalid Menu Item ${opts.id} [checked: ${opts.value}]`)
}
})
ipcMain.handle('readDirectory', async (evt, opts) => {
return readDirectory(opts.dirPath)
})
}
19 changes: 16 additions & 3 deletions src-electron/menu.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { Menu, app, shell } from 'electron'
import os from 'node:os'

import {
openDocument
} from './handlers'
import { openDocument } from './handlers'

export function registerMenu (mainWindow) {
const platform = process.platform || os.platform()
Expand Down Expand Up @@ -328,6 +326,7 @@ export function registerMenu (mainWindow) {
},
{ type: 'separator' },
{
id: 'viewShowPreviewPane',
label: 'Show Preview Pane',
type: 'checkbox',
checked: true,
Expand All @@ -351,6 +350,7 @@ export function registerMenu (mainWindow) {
},
{ type: 'separator' },
{
id: 'viewWordWrap',
label: 'Word Wrap',
type: 'checkbox',
checked: true,
Expand Down Expand Up @@ -440,6 +440,18 @@ export function registerMenu (mainWindow) {
{
label: 'Debug',
submenu: [
{
label: 'Clear HTTP Cache',
click () {
mainWindow.webContents.session.clearCache()
}
},
{
label: 'Clear Session Data',
click () {
mainWindow.webContents.session.clearStorageData()
}
},
{
role: 'reload'
},
Expand All @@ -463,4 +475,5 @@ export function registerMenu (mainWindow) {
]
const menu = Menu.buildFromTemplate(menuTemplate)
Menu.setApplicationMenu(menu)
return menu
}
5 changes: 5 additions & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import { defineAsyncComponent } from 'vue'
import { useQuasar } from 'quasar'
import { useDocsStore } from 'src/stores/docs'
import { useEditorStore } from 'src/stores/editor'
const $q = useQuasar()
const docsStore = useDocsStore()
const editorStore = useEditorStore()
window.ipcBridge.subscribe('dialogAction', (evt, action) => {
switch (action) {
Expand Down Expand Up @@ -51,5 +53,8 @@ window.ipcBridge.subscribe('save', (evt, filePath) => {
window.ipcBridge.subscribe('saveAs', () => {
docsStore.saveDocument(null, true)
})
window.ipcBridge.subscribe('setWorkingDirectory', (evt, dirPath) => {
editorStore.workingDirectory = dirPath
})
</script>
105 changes: 96 additions & 9 deletions src/components/DrawerFiles.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,99 @@
<template lang="pug">
q-list(padding)
q-item-label.text-caption.text-light-blue-3(header): strong Files
q-item
q-btn.full-width(
icon='mdi-folder-open'
label='Set Working Directory...'
color='primary'
no-caps
unelevated
.q-pa-md
.flex.items-center
.text-caption.text-light-blue-3
strong Files
q-tooltip {{ editorStore.workingDirectory }}
q-space
q-btn(
v-if='editorStore.workingDirectory'
size='sm'
icon='mdi-folder-edit'
padding='xs xs'
text-color='light-blue-3'
@click='setWorkingDirectory'
)
q-tooltip Set Working Directory...
q-btn.full-width.q-mt-sm(
v-if='!editorStore.workingDirectory'
icon='mdi-folder-open'
label='Set Working Directory...'
color='primary'
no-caps
unelevated
@click='setWorkingDirectory'
)
q-tree.q-mt-md(
:nodes='editorStore.workingDirFiles'
node-key='id'
label-key='name'
@lazy-load='onLazyLoad'
selected-color='light-blue-5'
v-model:selected='state.selected'
)
</template>

<script setup>
import { onMounted, reactive, watch } from 'vue'
import { useEditorStore } from 'src/stores/editor'
const editorStore = useEditorStore()
watch(() => editorStore.workingDirectory, reloadWorkingDirectory)
// STATE
const state = reactive({
selected: ''
})
// METHODS
async function setWorkingDirectory () {
const wdPath = await window.ipcBridge.promptWorkingDirectory(editorStore.workingDirectory)
if (wdPath) {
editorStore.workingDirectory = wdPath
}
}
async function reloadWorkingDirectory () {
const files = await window.ipcBridge.readDirectory(editorStore.workingDirectory)
editorStore.workingDirFiles = processFiles(files)
}
function processFiles (files) {
return files.map(f => ({
id: crypto.randomUUID(),
name: f.name,
path: f.path,
...(f.isDirectory && {
icon: 'mdi-folder',
iconColor: 'yellow-8',
lazy: true,
selectable: false
}),
...(!f.isDirectory && {
icon: 'mdi-file',
expandable: false,
selectable: true
})
}))
}
async function onLazyLoad ({ node, done, fail }) {
try {
const files = await window.ipcBridge.readDirectory(node.path)
done(processFiles(files))
} catch (err) {
fail()
}
}
// MOUNTED
onMounted(() => {
if (editorStore.workingDirectory) {
reloadWorkingDirectory()
}
})
</script>
25 changes: 17 additions & 8 deletions src/components/PreferencesDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ q-dialog(ref='dialogRef', @hide='onDialogHide')
emit-value
map-options
)
q-separator
.row
.col-8
.text-body2 Cursor Style
Expand Down Expand Up @@ -86,6 +87,22 @@ q-dialog(ref='dialogRef', @hide='onDialogHide')
suffix='px'
style='width: 200px'
)
.row
.col-8
.text-body2 Format on Type
.text-caption.text-grey-5 Controls whether the editor should automatically format the line after typing.
.col-4
q-toggle(
v-model='editorStore.formatOnType'
)
.row
.col-8
.text-body2 Preview Pane
.text-caption.text-grey-5 Controls whether the preview pane should be displayed.
.col-4
q-toggle(
v-model='editorStore.previewPaneShown'
)
.row
.col-8
.text-body2 Tab Size
Expand All @@ -100,14 +117,6 @@ q-dialog(ref='dialogRef', @hide='onDialogHide')
suffix='spaces'
style='width: 200px'
)
.row
.col-8
.text-body2 Format on Type
.text-caption.text-grey-5 Controls whether the editor should automatically format the line after typing.
.col-4
q-toggle(
v-model='editorStore.formatOnType'
)
.row
.col-8
.text-body2 Word Wrap
Expand Down
10 changes: 10 additions & 0 deletions src/pages/IndexPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,16 @@ onMounted(async () => {
if (editor) {
editor.updateOptions({ wordWrap: newValue ? 'on' : 'off' })
}
window.ipcBridge.emit('setMenuItemCheckedState', {
id: 'viewWordWrap',
value: newValue
})
})
watch(() => editorStore.previewPaneShown, (newValue) => {
window.ipcBridge.emit('setMenuItemCheckedState', {
id: 'viewShowPreviewPane',
value: newValue
})
})
window.ipcBridge.subscribe('editorAction', (evt, action) => {
Expand Down
Loading

0 comments on commit 189dbc3

Please sign in to comment.