fix: unify theme system - fix theme switching persistence

- Unified localStorage key to 'theme-preference' across all components
- Fixed header.tsx using wrong localStorage key ('theme' instead of 'theme-preference')
- Added localStorage hybrid persistence for instant theme changes
- Removed router.refresh() which was causing stale data revert
- Replaced Blue theme with Sepia
- Consolidated auth() calls to prevent race conditions
- Updated UserSettingsData types to include all themes
This commit is contained in:
2026-01-18 22:33:41 +01:00
parent ef60dafd73
commit ddb67ba9e5
306 changed files with 59580 additions and 6063 deletions

File diff suppressed because one or more lines are too long

View File

@@ -124,17 +124,160 @@ exports.Prisma.NoteScalarFieldEnum = {
title: 'title',
content: 'content',
color: 'color',
isPinned: 'isPinned',
isArchived: 'isArchived',
type: 'type',
checkItems: 'checkItems',
labels: 'labels',
images: 'images',
isPinned: 'isPinned',
isArchived: 'isArchived',
links: 'links',
reminder: 'reminder',
isReminderDone: 'isReminderDone',
reminderRecurrence: 'reminderRecurrence',
reminderLocation: 'reminderLocation',
isMarkdown: 'isMarkdown',
size: 'size',
embedding: 'embedding',
sharedWith: 'sharedWith',
userId: 'userId',
order: 'order',
notebookId: 'notebookId',
createdAt: 'createdAt',
updatedAt: 'updatedAt',
autoGenerated: 'autoGenerated',
aiProvider: 'aiProvider',
aiConfidence: 'aiConfidence',
language: 'language',
languageConfidence: 'languageConfidence',
lastAiAnalysis: 'lastAiAnalysis'
};
exports.Prisma.NotebookScalarFieldEnum = {
id: 'id',
name: 'name',
icon: 'icon',
color: 'color',
order: 'order',
userId: 'userId',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.LabelScalarFieldEnum = {
id: 'id',
name: 'name',
color: 'color',
notebookId: 'notebookId',
userId: 'userId',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.UserScalarFieldEnum = {
id: 'id',
name: 'name',
email: 'email',
emailVerified: 'emailVerified',
password: 'password',
role: 'role',
image: 'image',
theme: 'theme',
resetToken: 'resetToken',
resetTokenExpiry: 'resetTokenExpiry',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.AccountScalarFieldEnum = {
userId: 'userId',
type: 'type',
provider: 'provider',
providerAccountId: 'providerAccountId',
refresh_token: 'refresh_token',
access_token: 'access_token',
expires_at: 'expires_at',
token_type: 'token_type',
scope: 'scope',
id_token: 'id_token',
session_state: 'session_state',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.SessionScalarFieldEnum = {
sessionToken: 'sessionToken',
userId: 'userId',
expires: 'expires',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.VerificationTokenScalarFieldEnum = {
identifier: 'identifier',
token: 'token',
expires: 'expires'
};
exports.Prisma.NoteShareScalarFieldEnum = {
id: 'id',
noteId: 'noteId',
userId: 'userId',
sharedBy: 'sharedBy',
status: 'status',
permission: 'permission',
notifiedAt: 'notifiedAt',
respondedAt: 'respondedAt',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.SystemConfigScalarFieldEnum = {
key: 'key',
value: 'value'
};
exports.Prisma.AiFeedbackScalarFieldEnum = {
id: 'id',
noteId: 'noteId',
userId: 'userId',
feedbackType: 'feedbackType',
feature: 'feature',
originalContent: 'originalContent',
correctedContent: 'correctedContent',
metadata: 'metadata',
createdAt: 'createdAt'
};
exports.Prisma.MemoryEchoInsightScalarFieldEnum = {
id: 'id',
userId: 'userId',
note1Id: 'note1Id',
note2Id: 'note2Id',
similarityScore: 'similarityScore',
insight: 'insight',
insightDate: 'insightDate',
viewed: 'viewed',
feedback: 'feedback',
dismissed: 'dismissed'
};
exports.Prisma.UserAISettingsScalarFieldEnum = {
userId: 'userId',
titleSuggestions: 'titleSuggestions',
semanticSearch: 'semanticSearch',
paragraphRefactor: 'paragraphRefactor',
memoryEcho: 'memoryEcho',
memoryEchoFrequency: 'memoryEchoFrequency',
aiProvider: 'aiProvider',
preferredLanguage: 'preferredLanguage',
fontSize: 'fontSize',
demoMode: 'demoMode',
showRecentNotes: 'showRecentNotes',
emailNotifications: 'emailNotifications',
desktopNotifications: 'desktopNotifications',
anonymousAnalytics: 'anonymousAnalytics'
};
exports.Prisma.SortOrder = {
asc: 'asc',
desc: 'desc'
@@ -147,7 +290,18 @@ exports.Prisma.NullsOrder = {
exports.Prisma.ModelName = {
Note: 'Note'
Note: 'Note',
Notebook: 'Notebook',
Label: 'Label',
User: 'User',
Account: 'Account',
Session: 'Session',
VerificationToken: 'VerificationToken',
NoteShare: 'NoteShare',
SystemConfig: 'SystemConfig',
AiFeedback: 'AiFeedback',
MemoryEchoInsight: 'MemoryEchoInsight',
UserAISettings: 'UserAISettings'
};
/**

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
{
"name": "prisma-client-695acdec538e6176bd4e5288817cc61667217cda4bd3eacb6556ee22de6c4cd1",
"name": "prisma-client-335178138a2302fddc6069fd0c4da8598be3b531edb6ec6288b57b847324be3b",
"main": "index.js",
"types": "index.d.ts",
"browser": "index-browser.js",

View File

@@ -9,17 +9,168 @@ datasource db {
}
model Note {
id String @id @default(cuid())
title String?
content String
color String @default("default")
isPinned Boolean @default(false)
isArchived Boolean @default(false)
type String @default("text")
checkItems String?
labels String?
images String?
links String?
reminder DateTime?
isReminderDone Boolean @default(false)
reminderRecurrence String?
reminderLocation String?
isMarkdown Boolean @default(false)
size String @default("small")
embedding String?
sharedWith String?
userId String?
order Int @default(0)
notebookId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
autoGenerated Boolean?
aiProvider String?
aiConfidence Int?
language String?
languageConfidence Float?
lastAiAnalysis DateTime?
}
model Notebook {
id String @id @default(cuid())
name String
icon String?
color String?
order Int
userId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Label {
id String @id @default(cuid())
title String?
content String
color String @default("default")
type String @default("text")
checkItems String?
labels String?
images String?
isPinned Boolean @default(false)
isArchived Boolean @default(false)
order Int @default(0)
name String
color String @default("gray")
notebookId String?
userId String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model User {
id String @id @default(cuid())
name String?
email String @unique
emailVerified DateTime?
password String?
role String @default("USER")
image String?
theme String @default("light")
resetToken String? @unique
resetTokenExpiry DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Account {
userId String
type String
provider String
providerAccountId String
refresh_token String?
access_token String?
expires_at Int?
token_type String?
scope String?
id_token String?
session_state String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@id([provider, providerAccountId])
}
model Session {
sessionToken String @unique
userId String
expires DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model VerificationToken {
identifier String
token String
expires DateTime
@@id([identifier, token])
}
model NoteShare {
id String @id @default(cuid())
noteId String
userId String
sharedBy String
status String @default("pending")
permission String @default("view")
notifiedAt DateTime?
respondedAt DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([noteId, userId])
}
model SystemConfig {
key String @id
value String
}
model AiFeedback {
id String @id @default(cuid())
noteId String
userId String?
feedbackType String
feature String
originalContent String
correctedContent String?
metadata String?
createdAt DateTime @default(now())
}
model MemoryEchoInsight {
id String @id @default(cuid())
userId String?
note1Id String
note2Id String
similarityScore Float
insight String
insightDate DateTime @default(now())
viewed Boolean @default(false)
feedback String?
dismissed Boolean @default(false)
@@unique([userId, insightDate])
}
model UserAISettings {
userId String @id
titleSuggestions Boolean @default(true)
semanticSearch Boolean @default(true)
paragraphRefactor Boolean @default(true)
memoryEcho Boolean @default(true)
memoryEchoFrequency String @default("daily")
aiProvider String @default("auto")
preferredLanguage String @default("auto")
fontSize String @default("medium")
demoMode Boolean @default(false)
showRecentNotes Boolean @default(false)
emailNotifications Boolean @default(false)
desktopNotifications Boolean @default(false)
anonymousAnalytics Boolean @default(false)
}

View File

@@ -124,17 +124,160 @@ exports.Prisma.NoteScalarFieldEnum = {
title: 'title',
content: 'content',
color: 'color',
isPinned: 'isPinned',
isArchived: 'isArchived',
type: 'type',
checkItems: 'checkItems',
labels: 'labels',
images: 'images',
isPinned: 'isPinned',
isArchived: 'isArchived',
links: 'links',
reminder: 'reminder',
isReminderDone: 'isReminderDone',
reminderRecurrence: 'reminderRecurrence',
reminderLocation: 'reminderLocation',
isMarkdown: 'isMarkdown',
size: 'size',
embedding: 'embedding',
sharedWith: 'sharedWith',
userId: 'userId',
order: 'order',
notebookId: 'notebookId',
createdAt: 'createdAt',
updatedAt: 'updatedAt',
autoGenerated: 'autoGenerated',
aiProvider: 'aiProvider',
aiConfidence: 'aiConfidence',
language: 'language',
languageConfidence: 'languageConfidence',
lastAiAnalysis: 'lastAiAnalysis'
};
exports.Prisma.NotebookScalarFieldEnum = {
id: 'id',
name: 'name',
icon: 'icon',
color: 'color',
order: 'order',
userId: 'userId',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.LabelScalarFieldEnum = {
id: 'id',
name: 'name',
color: 'color',
notebookId: 'notebookId',
userId: 'userId',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.UserScalarFieldEnum = {
id: 'id',
name: 'name',
email: 'email',
emailVerified: 'emailVerified',
password: 'password',
role: 'role',
image: 'image',
theme: 'theme',
resetToken: 'resetToken',
resetTokenExpiry: 'resetTokenExpiry',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.AccountScalarFieldEnum = {
userId: 'userId',
type: 'type',
provider: 'provider',
providerAccountId: 'providerAccountId',
refresh_token: 'refresh_token',
access_token: 'access_token',
expires_at: 'expires_at',
token_type: 'token_type',
scope: 'scope',
id_token: 'id_token',
session_state: 'session_state',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.SessionScalarFieldEnum = {
sessionToken: 'sessionToken',
userId: 'userId',
expires: 'expires',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.VerificationTokenScalarFieldEnum = {
identifier: 'identifier',
token: 'token',
expires: 'expires'
};
exports.Prisma.NoteShareScalarFieldEnum = {
id: 'id',
noteId: 'noteId',
userId: 'userId',
sharedBy: 'sharedBy',
status: 'status',
permission: 'permission',
notifiedAt: 'notifiedAt',
respondedAt: 'respondedAt',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.SystemConfigScalarFieldEnum = {
key: 'key',
value: 'value'
};
exports.Prisma.AiFeedbackScalarFieldEnum = {
id: 'id',
noteId: 'noteId',
userId: 'userId',
feedbackType: 'feedbackType',
feature: 'feature',
originalContent: 'originalContent',
correctedContent: 'correctedContent',
metadata: 'metadata',
createdAt: 'createdAt'
};
exports.Prisma.MemoryEchoInsightScalarFieldEnum = {
id: 'id',
userId: 'userId',
note1Id: 'note1Id',
note2Id: 'note2Id',
similarityScore: 'similarityScore',
insight: 'insight',
insightDate: 'insightDate',
viewed: 'viewed',
feedback: 'feedback',
dismissed: 'dismissed'
};
exports.Prisma.UserAISettingsScalarFieldEnum = {
userId: 'userId',
titleSuggestions: 'titleSuggestions',
semanticSearch: 'semanticSearch',
paragraphRefactor: 'paragraphRefactor',
memoryEcho: 'memoryEcho',
memoryEchoFrequency: 'memoryEchoFrequency',
aiProvider: 'aiProvider',
preferredLanguage: 'preferredLanguage',
fontSize: 'fontSize',
demoMode: 'demoMode',
showRecentNotes: 'showRecentNotes',
emailNotifications: 'emailNotifications',
desktopNotifications: 'desktopNotifications',
anonymousAnalytics: 'anonymousAnalytics'
};
exports.Prisma.SortOrder = {
asc: 'asc',
desc: 'desc'
@@ -147,7 +290,18 @@ exports.Prisma.NullsOrder = {
exports.Prisma.ModelName = {
Note: 'Note'
Note: 'Note',
Notebook: 'Notebook',
Label: 'Label',
User: 'User',
Account: 'Account',
Session: 'Session',
VerificationToken: 'VerificationToken',
NoteShare: 'NoteShare',
SystemConfig: 'SystemConfig',
AiFeedback: 'AiFeedback',
MemoryEchoInsight: 'MemoryEchoInsight',
UserAISettings: 'UserAISettings'
};
/**