Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9a2959d
feat: implement toast notifications for user feedback & improvement i…
tonghoai Jul 18, 2026
2d7efec
feat: add confirmation modal for loading sample data with localizatio…
tonghoai Jul 18, 2026
5cb45fb
feat: add info button and localization for note deletion messages
tonghoai Jul 18, 2026
ea6b73b
feat: improve folder panel behavior and visibility on folder selection
tonghoai Jul 18, 2026
2badb8a
feat: add title property to notes and update related functionalities
tonghoai Jul 18, 2026
3984da5
feat: implement password change backup functionality and improve load…
tonghoai Jul 18, 2026
9ccb5dd
feat: add note history functionality
tonghoai Jul 19, 2026
593b1aa
feat: update Vietnamese localization for menu and modal messages
tonghoai Jul 19, 2026
b0abbfe
feat: add spacing between menu items in folder and note modals for im…
tonghoai Jul 19, 2026
6dfcc2e
feat: implement move note functionality with modal and localization u…
tonghoai Jul 19, 2026
464f5e4
feat: enhance image sync settings with font family options and locali…
tonghoai Jul 19, 2026
eb63c94
feat: adjust link edit height and add focus observer for improved use…
tonghoai Jul 19, 2026
11910bc
feat: enhance AppToast component with dedicated styling for improved …
tonghoai Jul 20, 2026
dd99927
feat: simplify reset service worker title in localization files
tonghoai Jul 20, 2026
6b7d29c
feat: update FloatNewNotes visibility condition to improve user exper…
tonghoai Jul 20, 2026
4c188db
feat: add force update functionality to clear cache and reload the ap…
tonghoai Jul 20, 2026
c01b149
feat: add force update functionality to clear cache and reload the ap…
tonghoai Jul 20, 2026
33c5f29
feat: add tag management functionality including create, update, dele…
tonghoai Jul 22, 2026
b11a538
feat: enhance data update functionality to support forced sync level
tonghoai Jul 22, 2026
f653cdc
feat: add cancel functionality for adapter changes in image sync sett…
tonghoai Jul 22, 2026
4343a04
feat: enhance tag and folder management with new UI elements and func…
tonghoai Jul 22, 2026
3352197
feat: update Vietnamese localization for tag management and enhance s…
tonghoai Jul 23, 2026
cf55697
feat: implement mobile back navigation handling and toggle functionality
tonghoai Jul 23, 2026
4954067
Merge pull request #9 from tonghoai/feature/improvement-image-sync
tonghoai Jul 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion adapter/adapter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { FolderType, NoteType } from "~/repositories/storage.type";
import type { FolderType, NoteType, TagType, NoteTagType } from "~/repositories/storage.type";

class NotasAdapter {
async pullFolders(lastSync: number): Promise<FolderType[]> {
Expand All @@ -17,6 +17,23 @@ class NotasAdapter {
throw new Error("Not implemented");
}

// tags
async pullTags(lastSync: number): Promise<TagType[]> {
throw new Error("Not implemented");
}

async pushTag(tag: any): Promise<any> {
throw new Error("Not implemented");
}

async pullNoteTags(lastSync: number): Promise<NoteTagType[]> {
throw new Error("Not implemented");
}

async pushNoteTag(noteTag: any): Promise<any> {
throw new Error("Not implemented");
}

// settings
async pushSettings(setting: any): Promise<any> {
throw new Error("Not implemented");
Expand Down
19 changes: 18 additions & 1 deletion adapter/localforage/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { FolderType, NoteType } from "~/repositories/storage.type";
import type { FolderType, NoteType, TagType, NoteTagType } from "~/repositories/storage.type";
import type NotasAdapter from "../adapter";

class LocalForageAdapter implements NotasAdapter {
Expand All @@ -20,6 +20,23 @@ class LocalForageAdapter implements NotasAdapter {
return {};
}

// tags
async pullTags(lastSync: number): Promise<TagType[]> {
return [];
}

async pushTag(tag: any): Promise<any> {
return {};
}

async pullNoteTags(lastSync: number): Promise<NoteTagType[]> {
return [];
}

async pushNoteTag(noteTag: any): Promise<any> {
return {};
}

// settings
async pushSettings(setting: any): Promise<any> {
return {};
Expand Down
128 changes: 127 additions & 1 deletion adapter/turso/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,27 @@ import { LibSQLDatabase, drizzle } from "drizzle-orm/libsql";
import { gt } from "drizzle-orm";

import type NotasAdapter from "../adapter";
import type { FolderType, NoteType } from "~/repositories/storage.type";
import type { FolderType, NoteType, TagType, NoteTagType } from "~/repositories/storage.type";
import { applySchemaMigrations } from "~/migrate/scripts/apply-migrations";

import noteModel from "./models/note";
import folderModel from "./models/folder";
import settingModel from "./models/setting";
import tagModel from "./models/tag";
import noteTagModel from "./models/note-tag";

class TursoAdapter implements NotasAdapter {
private turso: LibSQLDatabase;
private ready: Promise<void>;
constructor(config: string) {
const configJSON = JSON.parse(config);
const client = createClient(configJSON);
this.turso = drizzle(client);
this.ready = applySchemaMigrations(client);
}

async pullFolders(lastSync: number): Promise<FolderType[]> {
await this.ready;
const folders = await this.turso
.select()
.from(folderModel)
Expand All @@ -35,6 +41,7 @@ class TursoAdapter implements NotasAdapter {
}

async pullNotes(lastSync: number): Promise<NoteType[]> {
await this.ready;
const notes = await this.turso
.select()
.from(noteModel)
Expand All @@ -56,6 +63,7 @@ class TursoAdapter implements NotasAdapter {
}

async pushFolder(folder: any): Promise<any> {
await this.ready;
return this.turso
.insert(folderModel)
.values({
Expand Down Expand Up @@ -90,6 +98,7 @@ class TursoAdapter implements NotasAdapter {
}

async pushNote(note: any): Promise<any> {
await this.ready;
return this.turso
.insert(noteModel)
.values({
Expand Down Expand Up @@ -135,8 +144,124 @@ class TursoAdapter implements NotasAdapter {
});
}

// tags
async pullTags(lastSync: number): Promise<TagType[]> {
await this.ready;
const tags = await this.turso
.select()
.from(tagModel)
.where(gt(tagModel.updatedAt, lastSync))
.all();

return tags.map((tag: any) => ({
id: tag.id,
name: tag.name,
color: tag.color,
lastSync: tag.lastSync,
createdAt: tag.createdAt,
updatedAt: tag.updatedAt,
deletedAt: tag.deletedAt || null,
}));
}

async pushTag(tag: any): Promise<any> {
await this.ready;
return this.turso
.insert(tagModel)
.values({
id: tag.id,
name: tag.name,
color: tag.color,
lastSync: tag.lastSync,
createdAt: tag.createdAt,
updatedAt: tag.updatedAt,
deletedAt: tag.deletedAt,
})
.onConflictDoUpdate({
target: tagModel.id,
set: {
name: tag.name,
color: tag.color,
lastSync: tag.lastSync,
createdAt: tag.createdAt,
updatedAt: tag.updatedAt,
deletedAt: tag.deletedAt,
},
})
.returning({
id: tagModel.id,
name: tagModel.name,
color: tagModel.color,
lastSync: tagModel.lastSync,
createdAt: tagModel.createdAt,
updatedAt: tagModel.updatedAt,
deletedAt: tagModel.deletedAt,
})
.catch((err) => {
console.log("pushTag error", err);
});
}

async pullNoteTags(lastSync: number): Promise<NoteTagType[]> {
await this.ready;
const noteTags = await this.turso
.select()
.from(noteTagModel)
.where(gt(noteTagModel.updatedAt, lastSync))
.all();

return noteTags.map((noteTag: any) => ({
id: noteTag.id,
noteId: noteTag.noteId,
tagId: noteTag.tagId,
lastSync: noteTag.lastSync,
createdAt: noteTag.createdAt,
updatedAt: noteTag.updatedAt,
deletedAt: noteTag.deletedAt || null,
}));
}

async pushNoteTag(noteTag: any): Promise<any> {
await this.ready;
return this.turso
.insert(noteTagModel)
.values({
id: noteTag.id,
noteId: noteTag.noteId,
tagId: noteTag.tagId,
lastSync: noteTag.lastSync,
createdAt: noteTag.createdAt,
updatedAt: noteTag.updatedAt,
deletedAt: noteTag.deletedAt,
})
.onConflictDoUpdate({
target: noteTagModel.id,
set: {
noteId: noteTag.noteId,
tagId: noteTag.tagId,
lastSync: noteTag.lastSync,
createdAt: noteTag.createdAt,
updatedAt: noteTag.updatedAt,
deletedAt: noteTag.deletedAt,
},
})
.returning({
id: noteTagModel.id,
noteId: noteTagModel.noteId,
tagId: noteTagModel.tagId,
lastSync: noteTagModel.lastSync,
createdAt: noteTagModel.createdAt,
updatedAt: noteTagModel.updatedAt,
deletedAt: noteTagModel.deletedAt,
})
.catch((err) => {
console.log("pushNoteTag error", err);
});
}

// settings
async pushSettings(setting: any): Promise<any> {
await this.ready;
return this.turso
.insert(settingModel)
.values({
Expand Down Expand Up @@ -164,6 +289,7 @@ class TursoAdapter implements NotasAdapter {
});
}
async pullSettings(lastSync: number): Promise<any> {
await this.ready;
const setting = await this.turso
.select()
.from(settingModel)
Expand Down
21 changes: 21 additions & 0 deletions adapter/turso/migrations/0005_tired_king_bedlam.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
CREATE TABLE `note_tags` (
`id` text PRIMARY KEY NOT NULL,
`noteId` text,
`tagId` text,
`lastSync` integer,
`createdAt` integer,
`updatedAt` integer,
`deletedAt` integer
);
--> statement-breakpoint
CREATE TABLE `tags` (
`id` text PRIMARY KEY NOT NULL,
`name` text,
`color` text,
`lastSync` integer,
`createdAt` integer,
`updatedAt` integer,
`deletedAt` integer
);
--> statement-breakpoint
ALTER TABLE settings ADD `schemaVersion` integer;
Loading
Loading