Compare commits
No commits in common. "83cba54bf5301ab4efdb9788457b1ec40f8d86a8" and "7342c18c00c9c39c24f21d4a89f3c1bbd4469d56" have entirely different histories.
83cba54bf5
...
7342c18c00
|
@ -11,11 +11,5 @@
|
||||||
"svelte.plugin.svelte.compilerWarnings": {
|
"svelte.plugin.svelte.compilerWarnings": {
|
||||||
"a11y-no-noninteractive-element-interactions": "ignore",
|
"a11y-no-noninteractive-element-interactions": "ignore",
|
||||||
"a11y-click-events-have-key-events": "ignore"
|
"a11y-click-events-have-key-events": "ignore"
|
||||||
},
|
|
||||||
"[typescript]": {
|
|
||||||
"editor.defaultFormatter": "vscode.typescript-language-features"
|
|
||||||
},
|
|
||||||
"[json]": {
|
|
||||||
"editor.defaultFormatter": "vscode.json-language-features"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,3 @@ A simple notes app built with [SvelteKit](https://kit.svelte.dev/), [Kysely](htt
|
||||||
- Local-first; all data is stored on-device
|
- Local-first; all data is stored on-device
|
||||||
|
|
||||||
Hosted at https://notes.dallashoffman.com/
|
Hosted at https://notes.dallashoffman.com/
|
||||||
|
|
||||||
|
|
||||||
# ollama
|
|
||||||
|
|
||||||
```
|
|
||||||
OLLAMA_HOST=0.0.0.0:11434 ollama serve
|
|
||||||
```
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
35
package.json
35
package.json
|
@ -18,28 +18,23 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bytemd/plugin-gfm": "^1.21.0",
|
"@bytemd/plugin-gfm": "^1.21.0",
|
||||||
"bytemd": "1.21.0",
|
"bytemd": "1.21.0",
|
||||||
"kysely": "^0.27.3",
|
"kysely": "^0.26.3",
|
||||||
"sqlocal": "^0.11.1"
|
"sqlocal": "^0.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@picocss/pico": "^1.5.10",
|
"@picocss/pico": "^1.5.10",
|
||||||
"@sveltejs/adapter-static": "^3.0.6",
|
"@sveltejs/adapter-static": "^2.0.3",
|
||||||
"@vite-pwa/assets-generator": "^0.2.4",
|
"@sveltejs/kit": "^1.20.4",
|
||||||
"@vite-pwa/sveltekit": "^0.4.0",
|
"@vite-pwa/assets-generator": "^0.0.10",
|
||||||
|
"@vite-pwa/sveltekit": "^0.2.7",
|
||||||
"patch-package": "^8.0.0",
|
"patch-package": "^8.0.0",
|
||||||
"prettier": "^3.3.2",
|
"prettier": "^2.8.0",
|
||||||
"prettier-plugin-svelte": "^3.2.6",
|
"prettier-plugin-svelte": "^2.10.1",
|
||||||
"sass": "^1.69.5",
|
"sass": "^1.66.1",
|
||||||
"@sveltejs/adapter-node": "^5.2.2",
|
"svelte": "^4.0.5",
|
||||||
"@sveltejs/kit": "^2.5.25",
|
"svelte-check": "^3.4.3",
|
||||||
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
"tslib": "^2.4.1",
|
||||||
"svelte": "^5.0.0",
|
"typescript": "^5.2.2",
|
||||||
"svelte-check": "^3.6.8",
|
"vite": "^4.4.9"
|
||||||
"tslib": "^2.6.2",
|
|
||||||
"typescript": "^5.4.3",
|
|
||||||
"vite": "^5.0.3",
|
|
||||||
"fast-glob": "^3.3.2",
|
|
||||||
"openai": "^4.74.0",
|
|
||||||
"ollama": "^0.5.10"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,3 @@
|
||||||
diff --git a/node_modules/bytemd/package.json b/node_modules/bytemd/package.json
|
|
||||||
index 9103d88..e59f261 100644
|
|
||||||
--- a/node_modules/bytemd/package.json
|
|
||||||
+++ b/node_modules/bytemd/package.json
|
|
||||||
@@ -16,6 +16,7 @@
|
|
||||||
"author": "Rongjian Zhang",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
+ "svelte": "./svelte/index.js",
|
|
||||||
"types": "./dist/index.d.ts",
|
|
||||||
"import": "./dist/index.mjs",
|
|
||||||
"require": "./dist/index.js"
|
|
||||||
diff --git a/node_modules/bytemd/svelte/editor.svelte b/node_modules/bytemd/svelte/editor.svelte
|
diff --git a/node_modules/bytemd/svelte/editor.svelte b/node_modules/bytemd/svelte/editor.svelte
|
||||||
index 652a063..9ab0895 100644
|
index 652a063..9ab0895 100644
|
||||||
--- a/node_modules/bytemd/svelte/editor.svelte
|
--- a/node_modules/bytemd/svelte/editor.svelte
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
import ThemeToggle from '$lib/components/theme-toggle.svelte';
|
import ThemeToggle from '$lib/components/theme-toggle.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- <header class="app-header">
|
<header class="app-header">
|
||||||
<ThemeToggle />
|
<ThemeToggle />
|
||||||
<h1 class="app-header__title">Notes</h1>
|
<h1 class="app-header__title">Notes</h1>
|
||||||
<SettingsButton />
|
<SettingsButton />
|
||||||
</header> -->
|
</header>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.app-header {
|
.app-header {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
button {
|
button {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 1rem;
|
bottom: 2rem;
|
||||||
right: 1rem;
|
right: 1rem;
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
height: 4rem;
|
height: 4rem;
|
||||||
|
|
|
@ -34,12 +34,8 @@
|
||||||
<article class="note-card" style:--note-color={NoteColor[note.color][$themeUpperCase]}>
|
<article class="note-card" style:--note-color={NoteColor[note.color][$themeUpperCase]}>
|
||||||
<header class="note-card__header" hidden={$editing}>
|
<header class="note-card__header" hidden={$editing}>
|
||||||
<div class="note-card__header-buttons">
|
<div class="note-card__header-buttons">
|
||||||
{#if !$editing}
|
|
||||||
<NoteEditButton on:click={noteEditorStore.startEditing} />
|
|
||||||
{/if}
|
|
||||||
<NoteDeleteButton {note} {noteEditorStore} />
|
<NoteDeleteButton {note} {noteEditorStore} />
|
||||||
<div class="note-card__spacer" />
|
<div class="note-card__spacer" />
|
||||||
<NoteTimestamp {note} />
|
|
||||||
<NoteColorPicker {note} {noteEditorStore} />
|
<NoteColorPicker {note} {noteEditorStore} />
|
||||||
<NoteTagButton on:click={focusTags} />
|
<NoteTagButton on:click={focusTags} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -55,13 +51,16 @@
|
||||||
>
|
>
|
||||||
<NoteContent {note} {noteEditorStore} />
|
<NoteContent {note} {noteEditorStore} />
|
||||||
</div>
|
</div>
|
||||||
{#if $editing}
|
<footer class="note-card__footer">
|
||||||
<footer class="note-card__footer">
|
{#if !$editing}
|
||||||
|
<NoteEditButton on:click={noteEditorStore.startEditing} />
|
||||||
|
{:else}
|
||||||
<NoteSaveButton on:click={noteEditorStore.save} />
|
<NoteSaveButton on:click={noteEditorStore.save} />
|
||||||
<NoteDiscardButton on:click={noteEditorStore.discard} />
|
<NoteDiscardButton on:click={noteEditorStore.discard} />
|
||||||
<div class="note-card__spacer" />
|
{/if}
|
||||||
</footer>
|
<div class="note-card__spacer" />
|
||||||
{/if}
|
<NoteTimestamp {note} />
|
||||||
|
</footer>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -76,7 +75,6 @@
|
||||||
background-color: var(--note-color);
|
background-color: var(--note-color);
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
box-shadow: var(--card-shadow);
|
box-shadow: var(--card-shadow);
|
||||||
scrollbar-color: hsl(0 0% 0% / 0.2) hsl(0 0% 0% / 0.2);
|
|
||||||
|
|
||||||
&__header,
|
&__header,
|
||||||
&__footer {
|
&__footer {
|
||||||
|
|
|
@ -5,4 +5,5 @@
|
||||||
|
|
||||||
<Button icon plain on:click>
|
<Button icon plain on:click>
|
||||||
<FaPenToSquare />
|
<FaPenToSquare />
|
||||||
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -6,20 +6,18 @@
|
||||||
import { get, type Unsubscriber } from 'svelte/store';
|
import { get, type Unsubscriber } from 'svelte/store';
|
||||||
|
|
||||||
let noteListElement: HTMLUListElement;
|
let noteListElement: HTMLUListElement;
|
||||||
const noteHeight = 400;
|
const noteHeight = 385;
|
||||||
const noteGap = 16;
|
const noteGap = 16;
|
||||||
const paddingRows = 2;
|
const paddingRows = 2;
|
||||||
let scrollHeight = 0;
|
let scrollHeight = 0;
|
||||||
let scrollOffset = 0;
|
let scrollOffset = 0;
|
||||||
|
let flipDuration = 0;
|
||||||
|
|
||||||
let notesOffset = 0;
|
let notesOffset = 0;
|
||||||
let notesLimit = 100;
|
let notesLimit = 100;
|
||||||
let prevNotesCount = 0;
|
let prevNotesCount = 0;
|
||||||
let prevRowHeight = 0;
|
let prevRowHeight = 0;
|
||||||
|
|
||||||
let flipDuration = 0;
|
|
||||||
let flipTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
||||||
|
|
||||||
const { noteScale } = settings;
|
const { noteScale } = settings;
|
||||||
let scaleUnsubscribe: Unsubscriber;
|
let scaleUnsubscribe: Unsubscriber;
|
||||||
let countUnsubscribe: Unsubscriber;
|
let countUnsubscribe: Unsubscriber;
|
||||||
|
@ -43,8 +41,7 @@
|
||||||
|
|
||||||
if (notesCount !== prevNotesCount) {
|
if (notesCount !== prevNotesCount) {
|
||||||
flipDuration = 300;
|
flipDuration = 300;
|
||||||
clearTimeout(flipTimeout);
|
setTimeout(() => {
|
||||||
flipTimeout = setTimeout(() => {
|
|
||||||
flipDuration = 0;
|
flipDuration = 0;
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
|
@ -105,8 +102,8 @@
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.note-list {
|
.note-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(0, var(--note-height)));
|
grid-template-columns: repeat(auto-fill, minmax(0, calc(var(--note-height, 385px) * 0.92)));
|
||||||
grid-auto-rows: var(--note-height);
|
grid-auto-rows: var(--note-height, 385px);
|
||||||
gap: var(--note-gap, 1rem);
|
gap: var(--note-gap, 1rem);
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: var(--scroll-height, auto);
|
height: var(--scroll-height, auto);
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import FaPlus from '$icon/fa-potato.svelte';
|
|
||||||
import { notes } from '$lib/stores';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
aria-label="Search note"
|
|
||||||
data-tooltip="Search note"
|
|
||||||
data-placement="left"
|
|
||||||
on:click={() => notes.search()}
|
|
||||||
>
|
|
||||||
<FaPlus />
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
button {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 1rem;
|
|
||||||
right: 6rem;
|
|
||||||
width: 4rem;
|
|
||||||
height: 4rem;
|
|
||||||
margin: 0;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: var(--card-shadow);
|
|
||||||
|
|
||||||
& > :global(svg) {
|
|
||||||
width: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -4,8 +4,7 @@
|
||||||
import { settings } from '$lib/stores';
|
import { settings } from '$lib/stores';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button
|
<Button
|
||||||
type="button"
|
|
||||||
plain
|
plain
|
||||||
icon
|
icon
|
||||||
size="lg"
|
size="lg"
|
||||||
|
@ -14,21 +13,4 @@
|
||||||
on:click={() => settings.open.set(true)}
|
on:click={() => settings.open.set(true)}
|
||||||
>
|
>
|
||||||
<FaGear />
|
<FaGear />
|
||||||
</button>
|
</Button>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
button {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 6rem;
|
|
||||||
right: 1rem;
|
|
||||||
width: 4rem;
|
|
||||||
height: 4rem;
|
|
||||||
margin: 0;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: var(--card-shadow);
|
|
||||||
|
|
||||||
& > :global(svg) {
|
|
||||||
width: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ export class NoteEditorStore {
|
||||||
readonly draftContent = readonly(this._draftContent);
|
readonly draftContent = readonly(this._draftContent);
|
||||||
readonly expanded = readonly(this._expanded);
|
readonly expanded = readonly(this._expanded);
|
||||||
|
|
||||||
constructor(private noteId: Note['id'], private notes: NotesStore) { }
|
constructor(private noteId: Note['id'], private notes: NotesStore) {}
|
||||||
|
|
||||||
startEditing = () => {
|
startEditing = () => {
|
||||||
const note = this.notes.get(this.noteId);
|
const note = this.notes.get(this.noteId);
|
||||||
|
|
|
@ -4,8 +4,6 @@ import type { Insertable, Selectable, Updateable } from 'kysely';
|
||||||
import { writable, type Readable, get, readonly } from 'svelte/store';
|
import { writable, type Readable, get, readonly } from 'svelte/store';
|
||||||
import type { TagsStore } from './tags';
|
import type { TagsStore } from './tags';
|
||||||
import { settings } from '.';
|
import { settings } from '.';
|
||||||
import OpenAI from 'openai';
|
|
||||||
import { Ollama } from 'ollama'
|
|
||||||
|
|
||||||
export type Note = Selectable<Schema['note']>;
|
export type Note = Selectable<Schema['note']>;
|
||||||
export type NewNote = Insertable<Schema['note']>;
|
export type NewNote = Insertable<Schema['note']>;
|
||||||
|
@ -37,13 +35,13 @@ export class NotesStore implements Readable<Note[]> {
|
||||||
selectedTags.length === 0
|
selectedTags.length === 0
|
||||||
? db.selectFrom('note').selectAll().orderBy('createdAt desc')
|
? db.selectFrom('note').selectAll().orderBy('createdAt desc')
|
||||||
: db
|
: db
|
||||||
.selectFrom('noteTag')
|
.selectFrom('noteTag')
|
||||||
.innerJoin('note', 'note.id', 'noteTag.noteId')
|
.innerJoin('note', 'note.id', 'noteTag.noteId')
|
||||||
.selectAll('note')
|
.selectAll('note')
|
||||||
.where('tagId', 'in', selectedTags)
|
.where('tagId', 'in', selectedTags)
|
||||||
.groupBy('noteId')
|
.groupBy('noteId')
|
||||||
.having(({ fn }) => fn.count('noteId'), '=', selectedTags.length)
|
.having(({ fn }) => fn.count('noteId'), '=', selectedTags.length)
|
||||||
.orderBy('createdAt desc');
|
.orderBy('createdAt desc');
|
||||||
|
|
||||||
const notesData = await query.offset(this.offset).limit(this.limit).execute();
|
const notesData = await query.offset(this.offset).limit(this.limit).execute();
|
||||||
const { notesCount } = await db
|
const { notesCount } = await db
|
||||||
|
@ -68,20 +66,6 @@ export class NotesStore implements Readable<Note[]> {
|
||||||
return notes.find((note) => note.id === noteId);
|
return notes.find((note) => note.id === noteId);
|
||||||
};
|
};
|
||||||
|
|
||||||
search = async () => {
|
|
||||||
|
|
||||||
const ol = new Ollama({ host: 'http://deve.work:11434' })
|
|
||||||
const response = await ol.chat({
|
|
||||||
model: 'qwen2.5-coder:14b',
|
|
||||||
messages: [{ role: 'user', content: 'python编写1+1=?' }],
|
|
||||||
})
|
|
||||||
alert(response.message.content)
|
|
||||||
|
|
||||||
// const all = await db.selectFrom('note').selectAll().execute();
|
|
||||||
// alert(all[0].content);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
add = async (newNote?: NewNote, scrollToTop?: boolean) => {
|
add = async (newNote?: NewNote, scrollToTop?: boolean) => {
|
||||||
if (!newNote) {
|
if (!newNote) {
|
||||||
newNote = {
|
newNote = {
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
import '$styles/index.scss';
|
import '$styles/index.scss';
|
||||||
export const ssr = false;
|
export const ssr = false;
|
||||||
export const prerender = true;
|
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
import AppHeader from '$lib/components/app-header.svelte';
|
import AppHeader from '$lib/components/app-header.svelte';
|
||||||
import AppUpdatePrompt from '$lib/components/app-update-prompt.svelte';
|
import AppUpdatePrompt from '$lib/components/app-update-prompt.svelte';
|
||||||
import FilterTags from '$lib/components/filter-tags.svelte';
|
import FilterTags from '$lib/components/filter-tags.svelte';
|
||||||
import NoteSearchButton from '$lib/components/notes/note-search-button.svelte';
|
|
||||||
import SettingsButton from '$lib/components/settings/settings-button.svelte';
|
|
||||||
import NoteAddButton from '$lib/components/notes/note-add-button.svelte';
|
import NoteAddButton from '$lib/components/notes/note-add-button.svelte';
|
||||||
import NoteListPlaceholder from '$lib/components/notes/note-list-placeholder.svelte';
|
import NoteListPlaceholder from '$lib/components/notes/note-list-placeholder.svelte';
|
||||||
import NoteList from '$lib/components/notes/note-list.svelte';
|
import NoteList from '$lib/components/notes/note-list.svelte';
|
||||||
|
@ -25,8 +23,6 @@
|
||||||
{:else if $notesCount === 0}
|
{:else if $notesCount === 0}
|
||||||
<NoteListPlaceholder />
|
<NoteListPlaceholder />
|
||||||
{/if}
|
{/if}
|
||||||
<SettingsButton />
|
|
||||||
<NoteSearchButton />
|
|
||||||
<NoteAddButton />
|
<NoteAddButton />
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -68,10 +68,6 @@
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
:where(dl, ol, ul) {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-list-item {
|
.task-list-item {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@ html {
|
||||||
background-size: min(20vw, 150px);
|
background-size: min(20vw, 150px);
|
||||||
background-position: center center;
|
background-position: center center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
scrollbar-color: var(--range-thumb-color) var(--range-border-color);
|
|
||||||
|
|
||||||
&[data-theme] {
|
&[data-theme] {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import adapter from '@sveltejs/adapter-static';
|
import adapter from '@sveltejs/adapter-static';
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
import { vitePreprocess } from '@sveltejs/kit/vite';
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
const config = {
|
const config = {
|
||||||
|
|
Loading…
Reference in New Issue