note window opening
This commit is contained in:
@@ -2,30 +2,49 @@
|
||||
const electron = require("electron");
|
||||
const path = require("path");
|
||||
const utils = require("@electron-toolkit/utils");
|
||||
const icon = path.join(__dirname, "../../resources/icon.png");
|
||||
function createWindow() {
|
||||
const mainWindow = new electron.BrowserWindow({
|
||||
const mainWindow2 = new electron.BrowserWindow({
|
||||
width: 354,
|
||||
height: 549,
|
||||
show: false,
|
||||
autoHideMenuBar: true,
|
||||
...process.platform === "linux" ? { icon } : {},
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, "../preload/index.js"),
|
||||
sandbox: false
|
||||
}
|
||||
});
|
||||
mainWindow.on("ready-to-show", () => {
|
||||
mainWindow.show();
|
||||
mainWindow2.on("ready-to-show", () => {
|
||||
mainWindow2.show();
|
||||
});
|
||||
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
mainWindow2.webContents.setWindowOpenHandler((details) => {
|
||||
electron.shell.openExternal(details.url);
|
||||
return { action: "deny" };
|
||||
});
|
||||
if (utils.is.dev && process.env["ELECTRON_RENDERER_URL"]) {
|
||||
mainWindow.loadURL(process.env["ELECTRON_RENDERER_URL"]);
|
||||
mainWindow2.loadURL(process.env["ELECTRON_RENDERER_URL"]);
|
||||
} else {
|
||||
mainWindow.loadFile(path.join(__dirname, "../renderer/index.html"));
|
||||
mainWindow2.loadFile(path.join(__dirname, "../renderer/index.html"));
|
||||
}
|
||||
}
|
||||
function createNoteWindow(noteId) {
|
||||
const noteWindow = new electron.BrowserWindow({
|
||||
width: 354,
|
||||
height: 549,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, "preload.js"),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false
|
||||
}
|
||||
});
|
||||
if (utils.is.dev && process.env["ELECTRON_RENDERER_URL"]) {
|
||||
noteWindow.loadURL(
|
||||
`${process.env["ELECTRON_RENDERER_URL"]}/note/${noteId}`
|
||||
);
|
||||
} else {
|
||||
mainWindow.loadFile(path.join(__dirname, "../renderer/index.html"), {
|
||||
path: `/notes/${noteId}`
|
||||
});
|
||||
}
|
||||
}
|
||||
electron.app.whenReady().then(() => {
|
||||
@@ -33,11 +52,14 @@ electron.app.whenReady().then(() => {
|
||||
electron.app.on("browser-window-created", (_, window) => {
|
||||
utils.optimizer.watchWindowShortcuts(window);
|
||||
});
|
||||
electron.ipcMain.on("ping", () => console.log("pong"));
|
||||
console.log(electron.app.getPath("userData"));
|
||||
createWindow();
|
||||
electron.app.on("activate", function() {
|
||||
if (electron.BrowserWindow.getAllWindows().length === 0) createWindow();
|
||||
});
|
||||
electron.ipcMain.on("open-note-window", (_, noteId) => {
|
||||
createNoteWindow(noteId);
|
||||
});
|
||||
});
|
||||
electron.app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") {
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
"use strict";
|
||||
const electron = require("electron");
|
||||
const preload = require("@electron-toolkit/preload");
|
||||
const api = {};
|
||||
const api = {
|
||||
openNoteWindow: (noteId) => {
|
||||
electron.ipcRenderer.send("open-note-window", noteId);
|
||||
}
|
||||
};
|
||||
if (process.contextIsolated) {
|
||||
try {
|
||||
electron.contextBridge.exposeInMainWorld("electron", preload.electronAPI);
|
||||
|
||||
642
package-lock.json
generated
642
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -35,11 +35,13 @@
|
||||
"@tiptap/vue-3": "^3.19.0",
|
||||
"@vueuse/core": "^14.2.1",
|
||||
"electron-updater": "^6.3.9",
|
||||
"fecha": "^4.2.3",
|
||||
"gsap": "^3.14.2",
|
||||
"lenis": "^1.3.17",
|
||||
"sass": "^1.97.3",
|
||||
"sass-embedded": "^1.97.3",
|
||||
"tempus": "^1.0.0-dev.17"
|
||||
"tempus": "^1.0.0-dev.17",
|
||||
"vue-router": "^5.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^6.0.2",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB |
@@ -1,7 +1,6 @@
|
||||
import { app, shell, BrowserWindow, ipcMain } from 'electron'
|
||||
import { join } from 'path'
|
||||
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
||||
import icon from '../../resources/icon.png?asset'
|
||||
|
||||
function createWindow() {
|
||||
// Create the browser window.
|
||||
@@ -10,7 +9,6 @@ function createWindow() {
|
||||
height: 549,
|
||||
show: false,
|
||||
autoHideMenuBar: true,
|
||||
...(process.platform === 'linux' ? { icon } : {}),
|
||||
webPreferences: {
|
||||
preload: join(__dirname, '../preload/index.js'),
|
||||
sandbox: false,
|
||||
@@ -35,6 +33,29 @@ function createWindow() {
|
||||
}
|
||||
}
|
||||
|
||||
function createNoteWindow(noteId) {
|
||||
const noteWindow = new BrowserWindow({
|
||||
width: 354,
|
||||
height: 549,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
preload: join(__dirname, 'preload.js'),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
},
|
||||
})
|
||||
|
||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||
noteWindow.loadURL(
|
||||
`${process.env['ELECTRON_RENDERER_URL']}/note/${noteId}`,
|
||||
)
|
||||
} else {
|
||||
mainWindow.loadFile(join(__dirname, '../renderer/index.html'), {
|
||||
path: `/notes/${noteId}`,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
@@ -49,8 +70,7 @@ app.whenReady().then(() => {
|
||||
optimizer.watchWindowShortcuts(window)
|
||||
})
|
||||
|
||||
// IPC test
|
||||
ipcMain.on('ping', () => console.log('pong'))
|
||||
console.log(app.getPath('userData'))
|
||||
|
||||
createWindow()
|
||||
|
||||
@@ -59,6 +79,11 @@ app.whenReady().then(() => {
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
|
||||
// Open note in new window
|
||||
ipcMain.on('open-note-window', (_, noteId) => {
|
||||
createNoteWindow(noteId)
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
@@ -69,6 +94,3 @@ app.on('window-all-closed', () => {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { contextBridge } from 'electron'
|
||||
import { contextBridge, ipcRenderer } from 'electron'
|
||||
import { electronAPI } from '@electron-toolkit/preload'
|
||||
|
||||
// Custom APIs for renderer
|
||||
const api = {}
|
||||
const api = {
|
||||
openNoteWindow: (noteId) => {
|
||||
ipcRenderer.send('open-note-window', noteId)
|
||||
},
|
||||
}
|
||||
|
||||
// Use `contextBridge` APIs to expose Electron APIs to
|
||||
// renderer only if context isolation is enabled, otherwise
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<lenis root :options="{ duration: 1 }">
|
||||
<div :class="classes" :style="styles">
|
||||
<editor />
|
||||
<router-view :key="$route.fullPath" />
|
||||
</div>
|
||||
</lenis>
|
||||
</template>
|
||||
@@ -11,7 +11,6 @@ import Lenis from './components/Lenis.vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import loadFonts from '@fuzzco/font-loader'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
import Editor from './components/editor/Index.vue'
|
||||
|
||||
const { height } = useWindowSize()
|
||||
|
||||
|
||||
27
src/renderer/src/composables/useOpenNote.js
Normal file
27
src/renderer/src/composables/useOpenNote.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
export function useOpenNote() {
|
||||
const router = useRouter()
|
||||
|
||||
function openNote(noteId, options = {}) {
|
||||
const { newWindow = true } = options
|
||||
|
||||
// Electron environment check
|
||||
const isElectron =
|
||||
typeof window !== 'undefined' &&
|
||||
window.api &&
|
||||
typeof window.api.openNoteWindow === 'function'
|
||||
|
||||
if (newWindow && isElectron) {
|
||||
window.api.openNoteWindow(noteId)
|
||||
return
|
||||
}
|
||||
|
||||
// Fallback to SPA navigation
|
||||
router.push(`/note/${noteId}`)
|
||||
}
|
||||
|
||||
return {
|
||||
openNote,
|
||||
}
|
||||
}
|
||||
@@ -27,12 +27,12 @@ const breakpoints = {
|
||||
|
||||
const viewports = {
|
||||
mobile: {
|
||||
width: 440,
|
||||
width: 200,
|
||||
height: 956,
|
||||
},
|
||||
desktop: {
|
||||
width: 1728,
|
||||
height: 1117,
|
||||
width: 354,
|
||||
height: 549,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import './styles/main.scss'
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import { router } from './plugins/router'
|
||||
|
||||
createApp(App).mount('#app')
|
||||
const app = createApp(App)
|
||||
|
||||
// Plugins
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
||||
|
||||
14
src/renderer/src/plugins/router.js
Normal file
14
src/renderer/src/plugins/router.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
import Directory from '../views/Directory.vue'
|
||||
import Editor from '../views/Editor.vue'
|
||||
|
||||
const routes = [
|
||||
{ path: '/', name: 'directory', component: Directory },
|
||||
{ path: '/note/:id', name: 'note', component: Editor },
|
||||
]
|
||||
|
||||
export const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes,
|
||||
})
|
||||
@@ -4,7 +4,7 @@
|
||||
font-family: var(--font-display);
|
||||
font-weight: 400;
|
||||
letter-spacing: -0.02em;
|
||||
line-height: 1;
|
||||
line-height: 1.3;
|
||||
font-size: size-vw(30px);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,10 +36,10 @@ $layout: (
|
||||
//internal process, do not touch
|
||||
:root {
|
||||
--layout-column-count: #{list.nth(map.get($layout, 'columns-count'), 1)};
|
||||
--layout-column-gap: #{mobile-vw(
|
||||
--layout-column-gap: #{size-vw(
|
||||
list.nth(map.get($layout, 'columns-gap'), 1)
|
||||
)};
|
||||
--layout-margin: #{mobile-vw(list.nth(map.get($layout, 'margin'), 1))};
|
||||
--layout-margin: #{size-vw(list.nth(map.get($layout, 'margin'), 1))};
|
||||
--layout-width: calc(100vw - (2 * var(--layout-margin)));
|
||||
--layout-column-width: calc(
|
||||
(
|
||||
@@ -51,14 +51,6 @@ $layout: (
|
||||
) /
|
||||
var(--layout-column-count)
|
||||
);
|
||||
|
||||
@include desktop {
|
||||
--layout-column-count: #{list.nth(map.get($layout, 'columns-count'), 2)};
|
||||
--layout-column-gap: #{desktop-vw(
|
||||
list.nth(map.get($layout, 'columns-gap'), 2)
|
||||
)};
|
||||
--layout-margin: #{desktop-vw(list.nth(map.get($layout, 'margin'), 2))};
|
||||
}
|
||||
}
|
||||
|
||||
.layout-block {
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
:root {
|
||||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
|
||||
background: var(--theme-bg);
|
||||
color: var(--theme-fg);
|
||||
background: var(--black);
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
@@ -37,6 +36,10 @@ h4,
|
||||
h5,
|
||||
h6 {
|
||||
@include h1;
|
||||
|
||||
&.mono {
|
||||
@include h1-mono;
|
||||
}
|
||||
}
|
||||
.p,
|
||||
p,
|
||||
@@ -46,7 +49,20 @@ input,
|
||||
pre {
|
||||
@include p;
|
||||
}
|
||||
.bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
#app {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
// Text selection
|
||||
::selection {
|
||||
color: var(--theme-bg);
|
||||
background: var(--theme-accent);
|
||||
}
|
||||
::-moz-selection {
|
||||
color: var(--theme-bg);
|
||||
background: var(--theme-accent);
|
||||
}
|
||||
|
||||
145
src/renderer/src/views/Directory.vue
Normal file
145
src/renderer/src/views/Directory.vue
Normal file
@@ -0,0 +1,145 @@
|
||||
<template>
|
||||
<main class="directory layout-block">
|
||||
<button
|
||||
class="capitula"
|
||||
v-for="(capitula, i) in capitulum"
|
||||
@click="openNote(capitula.slug)"
|
||||
>
|
||||
<span class="index">{{ String(i + 1).padStart(2, '0') }}.</span>
|
||||
<span class="title h1">{{ capitula.title }}</span>
|
||||
</button>
|
||||
|
||||
<h2 class="label">Summarium</h2>
|
||||
|
||||
<div class="summarium">
|
||||
<button
|
||||
class="summaria"
|
||||
v-for="summaria in summarium"
|
||||
@click="openNote(summaria.slug)"
|
||||
>
|
||||
<span class="date">{{ formatDate(summaria.date) }}</span>
|
||||
<span class="title bold">{{ summaria.title }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { format } from 'fecha'
|
||||
import { useOpenNote } from '@/composables/useOpenNote'
|
||||
|
||||
const capitulum = [
|
||||
{
|
||||
slug: 'category-name',
|
||||
date: new Date(),
|
||||
title: 'Category Name',
|
||||
},
|
||||
{
|
||||
slug: 'alternate-tuning',
|
||||
date: new Date(),
|
||||
title: 'Alternate Tuning',
|
||||
},
|
||||
{
|
||||
slug: 'hungarian-citizenship',
|
||||
date: new Date(),
|
||||
title: 'Hungarian Citizenship Application and More and More',
|
||||
},
|
||||
]
|
||||
|
||||
const summarium = [
|
||||
{
|
||||
slug: 'birthday-dinner',
|
||||
date: new Date(),
|
||||
title: 'Birthday Dinner Recipe to make for Gina',
|
||||
},
|
||||
{
|
||||
slug: 'to-do-reminders',
|
||||
date: new Date(),
|
||||
title: 'To-Do Reminders',
|
||||
},
|
||||
{
|
||||
slug: 'client-feedback',
|
||||
date: new Date(),
|
||||
title: 'Client Feedback',
|
||||
},
|
||||
]
|
||||
|
||||
const { openNote } = useOpenNote()
|
||||
|
||||
const formatDate = (date) => {
|
||||
return format(date, 'MM/DD/YYYY')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.directory {
|
||||
padding-top: size-vw(18px);
|
||||
|
||||
.capitula {
|
||||
display: grid;
|
||||
grid-template-columns: size-vw(26px) 1fr;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: size-vw(5px) 0 size-vw(15px);
|
||||
cursor: pointer;
|
||||
|
||||
.index {
|
||||
margin-top: size-vw(19px);
|
||||
}
|
||||
.title {
|
||||
display: block;
|
||||
width: 100%;
|
||||
@include line-clamp(2);
|
||||
}
|
||||
&::after {
|
||||
content: '----------------------------------------';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
&:hover {
|
||||
color: var(--theme-accent);
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
text-transform: uppercase;
|
||||
margin: size-vw(17px) 0 size-vw(24px);
|
||||
@include p;
|
||||
}
|
||||
.summarium {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: size-vw(14px);
|
||||
|
||||
.summaria {
|
||||
grid-template-columns: auto 1fr;
|
||||
display: grid;
|
||||
gap: size-vw(20px);
|
||||
cursor: pointer;
|
||||
|
||||
.title {
|
||||
width: size-vw(159px);
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '(open)';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
transform: translateX(100%);
|
||||
font-weight: 700;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
color: var(--theme-accent);
|
||||
|
||||
.title::after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -17,33 +17,6 @@
|
||||
</div>
|
||||
</bubble-menu>
|
||||
|
||||
<floating-menu :editor="editor">
|
||||
<div class="floating-menu">
|
||||
<button
|
||||
@click="
|
||||
editor.chain().focus().toggleHeading({ level: 1 }).run()
|
||||
"
|
||||
:class="{
|
||||
active: editor.isActive('heading', { level: 1 }),
|
||||
}"
|
||||
>
|
||||
H1
|
||||
</button>
|
||||
<button
|
||||
@click="editor.chain().focus().toggleBulletList().run()"
|
||||
:class="{ active: editor.isActive('bulletList') }"
|
||||
>
|
||||
Bullet List
|
||||
</button>
|
||||
<button
|
||||
@click="editor.chain().focus().toggleOrderedList().run()"
|
||||
:class="{ active: editor.isActive('orderedlist') }"
|
||||
>
|
||||
Number List
|
||||
</button>
|
||||
</div>
|
||||
</floating-menu>
|
||||
|
||||
<editor-content :editor="editor" class="editor-wrap" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -111,7 +84,7 @@ onBeforeUnmount(() => {
|
||||
<style lang="scss">
|
||||
.editor {
|
||||
padding-top: size-vw(8px);
|
||||
// padding-top: 100px;
|
||||
padding-bottom: size-vw(20px);
|
||||
|
||||
h1 {
|
||||
font-weight: 700 !important;
|
||||
@@ -134,7 +107,8 @@ onBeforeUnmount(() => {
|
||||
font-style: italic;
|
||||
}
|
||||
hr::before {
|
||||
content: '-----------------------------------------';
|
||||
content: '----------------------------------------';
|
||||
@include p;
|
||||
}
|
||||
ul {
|
||||
list-style-type: disc;
|
||||
@@ -173,7 +147,6 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.floating-menu,
|
||||
.bubble-menu {
|
||||
display: flex;
|
||||
gap: size-vw(5px);
|
||||
Reference in New Issue
Block a user