load in optimization and error correction
This commit is contained in:
@@ -7,15 +7,16 @@ interface EmbedLayoutProps {
|
||||
export const EmbedLayout: Component<EmbedLayoutProps> = (props) => {
|
||||
return (
|
||||
<div class="flex h-screen w-full min-w-0 bg-background overflow-hidden relative font-sans antialiased text-foreground">
|
||||
<main
|
||||
class="flex-1 min-w-0 overflow-y-auto overflow-x-hidden relative scroll-smooth bg-background"
|
||||
style={{
|
||||
"padding-bottom": "calc(8px + env(safe-area-inset-bottom, 0px))"
|
||||
}}
|
||||
>
|
||||
<main class="flex-1 min-w-0 overflow-y-auto overflow-x-hidden relative scroll-smooth bg-background">
|
||||
<div class="w-full h-full mx-auto p-4">
|
||||
{props.children}
|
||||
</div>
|
||||
<div
|
||||
class="md:hidden shrink-0"
|
||||
style={{
|
||||
height: "calc(8px + env(safe-area-inset-bottom, 0px))"
|
||||
}}
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
|
||||
+14
-13
@@ -1,6 +1,6 @@
|
||||
import { type Component, type JSX, createSignal, createEffect, Show, lazy, Suspense, onMount, onCleanup } from "solid-js";
|
||||
import { Sidebar, BottomNav, ContextSwitcher } from "./Navigation";
|
||||
import { store, setStore, activeTaskId, setActiveTaskId } from "@/store";
|
||||
import { store, setStore, activeTaskId, setActiveTaskId, requestImmediateNotesMetadataLoad } from "@/store";
|
||||
import { PanelLeftOpen, PanelLeftClose } from "lucide-solid";
|
||||
|
||||
const TaskDetail = lazy(() => import("./TaskDetail").then(m => ({ default: m.TaskDetail })));
|
||||
@@ -54,6 +54,12 @@ export const Layout: Component<LayoutProps> = (props) => {
|
||||
// Derived active task for the detail view
|
||||
const activeTask = () => store.tasks.find(t => t.id === activeTaskId());
|
||||
|
||||
createEffect(() => {
|
||||
if (store.isNotepadMode) {
|
||||
void requestImmediateNotesMetadataLoad();
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div class="flex h-screen w-full min-w-0 bg-background overflow-hidden relative font-sans antialiased text-foreground">
|
||||
{/* Desktop UI Container */}
|
||||
@@ -189,25 +195,20 @@ export const Layout: Component<LayoutProps> = (props) => {
|
||||
</div>
|
||||
|
||||
{/* Sync Progress Bar Overlay */}
|
||||
<Show when={store.isInitializing}>
|
||||
<Show when={store.isInitializing || (store.isNotepadMode && store.isNotesLoading)}>
|
||||
<div class="fixed top-0 left-0 w-full h-0.5 z-[100] overflow-hidden bg-primary/10">
|
||||
<div class="h-full bg-primary animate-progress-fast w-1/3" />
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
{/* Main Content Area */}
|
||||
<main
|
||||
class={cn(
|
||||
"flex-1 min-w-0 overflow-y-auto overflow-x-hidden relative scroll-smooth",
|
||||
!store.isNotepadMode ? "pb-32 sm:pb-6" : ""
|
||||
)}
|
||||
style={{
|
||||
"padding-bottom": "calc(8px + env(safe-area-inset-bottom, 0px))"
|
||||
}}
|
||||
>
|
||||
<main class={cn(
|
||||
"flex-1 min-w-0 overflow-y-auto overflow-x-hidden relative scroll-smooth",
|
||||
!store.isNotepadMode ? "sm:pb-6" : ""
|
||||
)}>
|
||||
<div class={cn(
|
||||
"w-full h-full mx-auto",
|
||||
!store.isNotepadMode ? "max-w-screen-2xl px-4 sm:px-8 lg:px-12 pt-16 sm:pt-20 pb-8 space-y-6 sm:space-y-8" : "max-w-screen-2xl md:px-8 lg:px-12 md:pt-20 md:pb-8 pt-14"
|
||||
"w-full min-h-full mx-auto",
|
||||
!store.isNotepadMode ? "max-w-screen-2xl px-4 sm:px-8 lg:px-12 pt-16 sm:pt-20 mobile-footer-clearance space-y-6 sm:space-y-8" : "max-w-screen-2xl md:px-8 lg:px-12 md:pt-20 md:pb-8 pt-14"
|
||||
)}>
|
||||
<div class={cn(store.isNotepadMode ? "hidden" : "block")}>
|
||||
<Show when={props.currentView.toLowerCase() !== "settings"}>
|
||||
|
||||
@@ -58,7 +58,13 @@ export const BottomNav: Component<{ currentView: string; setView: (v: string) =>
|
||||
};
|
||||
|
||||
return (
|
||||
<nav class="fixed bottom-0 left-0 right-0 bg-background border-t border-border flex justify-around items-center h-16 md:hidden z-50">
|
||||
<nav
|
||||
class="fixed bottom-0 left-0 right-0 bg-background border-t border-border flex justify-around items-center md:hidden z-50"
|
||||
style={{
|
||||
"padding-bottom": "env(safe-area-inset-bottom, 0px)",
|
||||
height: "calc(4rem + env(safe-area-inset-bottom, 0px))"
|
||||
}}
|
||||
>
|
||||
<For each={mobileNavGroups}>
|
||||
{(group) => (
|
||||
<Show when={group.items} fallback={
|
||||
|
||||
@@ -216,7 +216,7 @@ export const NotesSidebar: Component<{
|
||||
|
||||
{/* List */}
|
||||
<div class="flex-1 overflow-y-auto p-2 space-y-1 pb-20 md:pb-2">
|
||||
<For each={filteredNotes()} fallback={<div class="p-4 text-center text-xs text-muted-foreground">No notes found.</div>}>
|
||||
<For each={filteredNotes()} fallback={<div class="p-4 text-center text-xs text-muted-foreground">{store.isNotesLoading ? "Loading notes..." : "No notes found."}</div>}>
|
||||
{(note) => (
|
||||
<button
|
||||
onClick={() => props.setSelectedNoteId(note.id)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type Component, createSignal, createEffect, onMount, For, Show, Suspense, lazy } from "solid-js";
|
||||
import { addTask, calculateDateFromUrgency, calculateUrgencyFromDate, store, upsertTagDefinition, type TaskTemplate, currentTaskContext } from "@/store";
|
||||
import { addTask, calculateDateFromUrgency, calculateUrgencyFromDate, store, upsertTagDefinition, type TaskTemplate, currentTaskContext, isCurrentUserContextTag } from "@/store";
|
||||
import { Search, Command, Clock, ArrowUpCircle, Copy, ChevronDown, Gauge, RotateCcw } from "lucide-solid";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
@@ -414,7 +414,7 @@ export const QuickEntryForm: Component<QuickEntryFormProps> = (props) => {
|
||||
<div class="flex flex-col md:flex-row items-stretch md:items-center px-4 py-3 gap-4 bg-muted/10 border-b border-border">
|
||||
<div class="flex-1 flex flex-wrap gap-2 items-center">
|
||||
<TagPicker selectedTags={tags()} onTagsChange={setTags} />
|
||||
<For each={tags().filter(t => !t.endsWith("_favorite__"))}>
|
||||
<For each={tags().filter(t => !t.endsWith("_favorite__") && !isCurrentUserContextTag(t))}>
|
||||
{(tag) => (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type Component, createSignal, For, createEffect } from "solid-js";
|
||||
import { store, upsertTagDefinition } from "@/store";
|
||||
import { store, upsertTagDefinition, isCurrentUserContextTag } from "@/store";
|
||||
import { useTheme } from "./ThemeProvider";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -20,7 +20,7 @@ export const TagPicker: Component<TagPickerProps> = (props) => {
|
||||
|
||||
// Filter tags for the "Name" part
|
||||
const localTagNames = () => {
|
||||
const localDef = store.tagDefinitions.filter(d => !d.isUser && !d.isBucket).map(d => d.name);
|
||||
const localDef = store.tagDefinitions.filter(d => !d.isUser && !d.isBucket).map(d => d.name).filter(tag => !isCurrentUserContextTag(tag));
|
||||
return [...new Set(localDef)].sort();
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ export const TagPicker: Component<TagPickerProps> = (props) => {
|
||||
const noteTags = store.notes
|
||||
.filter(n => !(n.tags || []).some(t => t.startsWith("child-of-")))
|
||||
.map(n => buildNoteTag(n.key || n.title));
|
||||
return [...new Set([...definedTags, ...contextTags, ...noteTags])].sort();
|
||||
return [...new Set([...definedTags, ...contextTags, ...noteTags])].filter(tag => !isCurrentUserContextTag(tag)).sort();
|
||||
};
|
||||
|
||||
const suggestedTags = () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { type Component, createMemo, For, Show } from "solid-js";
|
||||
import { type Task, calculateUrgencyFromDate, setActiveTaskId, store, copyTask, updateTask, currentTaskContext, now, getFavoriteTag } from "@/store";
|
||||
import { type Task, calculateUrgencyFromDate, setActiveTaskId, store, copyTask, updateTask, currentTaskContext, now, getFavoriteTag, isCurrentUserContextTag } from "@/store";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Clock, ArrowUpCircle, Copy, Users2, Star } from "lucide-solid";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
@@ -36,10 +36,10 @@ export const TaskCard: Component<{ task: Task, isShaking?: boolean }> = (props)
|
||||
if (typeof ctx === 'object' && 'bucketId' in ctx) {
|
||||
const bucketContext = store.contexts.find(context => context.id === ctx.bucketId);
|
||||
const bucketTagName = buildShareTag(bucketContext?.displayName || ctx.name).toLowerCase();
|
||||
return tags.filter(t => t.toLowerCase() !== bucketTagName && !t.endsWith("_favorite__"));
|
||||
return tags.filter(t => t.toLowerCase() !== bucketTagName && !t.endsWith("_favorite__") && !isCurrentUserContextTag(t));
|
||||
}
|
||||
|
||||
return tags.filter(t => !t.endsWith("_favorite__"));
|
||||
return tags.filter(t => !t.endsWith("_favorite__") && !isCurrentUserContextTag(t));
|
||||
});
|
||||
|
||||
const isDueWithin12Hours = createMemo(() => {
|
||||
@@ -59,13 +59,15 @@ export const TaskCard: Component<{ task: Task, isShaking?: boolean }> = (props)
|
||||
if (props.task.status !== 10) return null;
|
||||
return getRecurrenceProgress(props.task.recurrence, props.task.updated, now());
|
||||
});
|
||||
const shouldQuickloadFade = createMemo(() => store.quickloadFadeTaskIds.includes(props.task.id));
|
||||
|
||||
return (
|
||||
<div
|
||||
class={cn(
|
||||
"group relative flex items-center p-3 sm:p-4 bg-card border border-border rounded-2xl transition-[background-color,border-color,box-shadow,opacity] duration-500 hover:duration-100 hover:shadow-xl hover:shadow-primary/5 hover:-translate-y-0.5 cursor-pointer w-full min-w-0 overflow-hidden",
|
||||
props.task.completed && "opacity-60",
|
||||
props.isShaking && "animate-task-shake bg-accent/20"
|
||||
props.isShaking && "animate-task-shake bg-accent/20",
|
||||
shouldQuickloadFade() && "animate-task-quickload-fade"
|
||||
)}
|
||||
onClick={() => setActiveTaskId(props.task.id)}
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type Component, createEffect, createSignal, For, createMemo, onCleanup, Show } from "solid-js";
|
||||
import { Sheet, SheetContent } from "@/components/ui/sheet";
|
||||
import { type Task, removeTask, restoreTask, updateTask, saveTaskAsTemplate, loadTaskContent, currentTaskContext, cleanupTaskAttachments, getFavoriteTag, now } from "@/store";
|
||||
import { type Task, removeTask, restoreTask, updateTask, saveTaskAsTemplate, loadTaskContent, currentTaskContext, cleanupTaskAttachments, getFavoriteTag, now, isCurrentUserContextTag } from "@/store";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
|
||||
import { ArrowUpCircle, Clock, Calendar, Type, Trash2, X, Copy, MoreHorizontal, Gauge, Star, FileText } from "lucide-solid";
|
||||
@@ -170,8 +170,17 @@ export const TaskDetail: Component<TaskDetailProps> = (props) => {
|
||||
|
||||
const updateTags = (tags: string[]) => {
|
||||
const ctx = currentTaskContext();
|
||||
const currentTags = props.task.tags || [];
|
||||
let newTags = [...tags];
|
||||
|
||||
currentTags
|
||||
.filter(tag => isCurrentUserContextTag(tag))
|
||||
.forEach(tag => {
|
||||
if (!newTags.some(existing => existing.toLowerCase() === tag.toLowerCase())) {
|
||||
newTags.push(tag);
|
||||
}
|
||||
});
|
||||
|
||||
// If in a bucket view, ensure the bucket tag is preserved (it was hidden from the UI so it's missing from 'tags')
|
||||
if (typeof ctx === 'object' && 'bucketId' in ctx) {
|
||||
const bucketContext = store.contexts.find(context => context.id === ctx.bucketId);
|
||||
@@ -204,10 +213,10 @@ export const TaskDetail: Component<TaskDetailProps> = (props) => {
|
||||
if (typeof ctx === 'object' && 'bucketId' in ctx) {
|
||||
const bucketContext = store.contexts.find(context => context.id === ctx.bucketId);
|
||||
const bucketTagName = buildShareTag(bucketContext?.displayName || ctx.name).toLowerCase();
|
||||
return tags.filter(t => t.toLowerCase() !== bucketTagName && !t.endsWith("_favorite__"));
|
||||
return tags.filter(t => t.toLowerCase() !== bucketTagName && !t.endsWith("_favorite__") && !isCurrentUserContextTag(t));
|
||||
}
|
||||
|
||||
return tags.filter(t => !t.endsWith("_favorite__"));
|
||||
return tags.filter(t => !t.endsWith("_favorite__") && !isCurrentUserContextTag(t));
|
||||
});
|
||||
|
||||
const statusOptions = createMemo(() => getStatusOptionsForTask(props.task.recurrence));
|
||||
@@ -692,7 +701,10 @@ export const TaskDetail: Component<TaskDetailProps> = (props) => {
|
||||
fallback={<p class="text-[0.6875rem] text-muted-foreground/70">No shared contexts on this task.</p>}
|
||||
>
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
<For each={props.task.shareRefs}>
|
||||
<For each={props.task.shareRefs.filter(ref => {
|
||||
const context = store.contexts.find(existing => existing.id === ref.contextId) || store.contexts.find(existing => existing.key === ref.key);
|
||||
return !isCurrentUserContextTag(`@${context?.displayName || ref.key}`);
|
||||
})}>
|
||||
{(ref) => {
|
||||
const context = store.contexts.find(existing => existing.id === ref.contextId) || store.contexts.find(existing => existing.key === ref.key);
|
||||
const label = `@${context?.displayName || ref.key}`;
|
||||
|
||||
Reference in New Issue
Block a user