@@ -3,15 +3,11 @@ import { HocuspocusProvider } from "@hocuspocus/provider";
33import type { SelectableModel } from " @nota/ai" ;
44import { toast } from " @nota/ui" ;
55import { createEditor , Edra } from " @nota/ui/edra/shadcn/index.js" ;
6- import type {
7- Editor ,
8- Extension ,
9- Extensions ,
10- } from " @nota/ui/edra/tiptap/index.js" ;
6+ import type { Editor } from " @nota/ui/edra/tiptap/index.js" ;
117import { IconPicker , IconsRenderer } from " @nota/ui/icons/index.js" ;
128import { Button } from " @nota/ui/shadcn/button/index.js" ;
139import { Skeleton } from " @nota/ui/shadcn/skeleton/index.js" ;
14- import { onMount } from " svelte" ;
10+ import { onDestroy , onMount } from " svelte" ;
1511import type { Doc } from " yjs" ;
1612import { getAuthSession } from " #lib/auth-session.svelte.js" ;
1713import { Topbar } from " #lib/components/custom/index.ts" ;
@@ -20,8 +16,8 @@ import { onFileUpload } from "#lib/data/cloud/storage.js";
2016import { callAI , getUserModels } from " #lib/data/local/ai/ai.js" ;
2117import { getNotesContext } from " #lib/data/notes.svelte.ts" ;
2218import type { NoteMeta } from " #lib/data/types.js" ;
23- import { secureStorage } from " #lib/platform/securestorage.js " ;
24- import { ISDESKTOP } from " #lib/utils.js " ;
19+ import " ./page.css " ;
20+
2521import { afterNavigate , beforeNavigate } from " $app/navigation" ;
2622
2723const noteCtx = getNotesContext ();
@@ -32,28 +28,63 @@ let availableModels = $state<SelectableModel[]>([]);
3228let provider = $state .raw <HocuspocusProvider >();
3329let editor = $state .raw <Editor >();
3430let ydoc = $state .raw <Doc >();
31+ let connectionStatus = $state (" disconnected" );
3532
3633let isContentReady = $state (false );
3734let isNotFound = $state (false );
38- let isDirty = false ;
39- let isSaving = false ;
40- let pendingContent: any = null ;
41- let pendingText: string = " " ;
4235
4336onMount (() => {
4437 getUserModels ().then ((models ) => (availableModels = models ));
4538});
4639
47- beforeNavigate (async () => {
48- provider ?.disconnect ();
49- editor ?.destroy ();
50- ydoc ?.destroy ();
40+ onDestroy (() => {
41+ teardownEditor ();
42+ });
43+
44+ beforeNavigate (() => {
45+ teardownEditor ();
5146});
5247
5348afterNavigate (() => {
5449 if (data .id ) loadNote (data .id );
5550});
5651
52+ const setupEditor = async (id : string ) => {
53+ teardownEditor ();
54+ if (! user ) {
55+ throw new Error (" User not signed in" );
56+ }
57+ const {
58+ ydoc : y,
59+ provider : p,
60+ extensions,
61+ } = await realtimeProvider (
62+ id ,
63+ user .name ?? " Unknow" ,
64+ user .image ?? undefined ,
65+ );
66+ ydoc = y ;
67+ provider = p ;
68+
69+ provider .on (" status" , (event : any ) => {
70+ connectionStatus = event .status ;
71+ });
72+
73+ editor = createEditor ({
74+ collaborative: true ,
75+ onFileUpload : (fileType ) => onFileUpload (fileType , data .id ),
76+ callAI ,
77+ extensions: [... extensions ],
78+ });
79+ };
80+
81+ const teardownEditor = () => {
82+ provider ?.disconnect ();
83+ provider ?.destroy ();
84+ editor ?.destroy ();
85+ ydoc ?.destroy ();
86+ };
87+
5788const loadNote = async (id : string ) => {
5889 isContentReady = false ;
5990 isNotFound = false ;
@@ -64,19 +95,7 @@ const loadNote = async (id: string) => {
6495 isNotFound = true ;
6596 return ;
6697 }
67- const {
68- ydoc : y,
69- provider : p,
70- extensions,
71- } = await realtimeProvider (id , user ?.name ?? " Unknow" );
72- ydoc = y ;
73- provider = p ;
74- editor = createEditor ({
75- collaborative: true ,
76- onFileUpload : (fileType ) => onFileUpload (fileType , data .id ),
77- callAI ,
78- extensions: [... extensions ],
79- });
98+ await setupEditor (id );
8099 isContentReady = true ;
81100 } catch (e ) {
82101 console .error (" Failed to load note:" , e );
@@ -109,6 +128,14 @@ const { data } = $props();
109128 <Skeleton class =" h-8 w-24" />
110129 {/if }
111130 {/ snippet }
131+ {#snippet right ()}
132+ <div class =" flex items-center mr-4" >
133+ <div class =" text-xs uppercase px-2 py-1 bg-muted rounded font-medium flex items-center gap-2" >
134+ <div class ="w-2 h-2 rounded-full {connectionStatus === ' connected' ? ' bg-green-500' : connectionStatus === ' connecting' ? ' bg-yellow-500' : ' bg-red-500' }" ></div >
135+ {connectionStatus }
136+ </div >
137+ </div >
138+ {/ snippet }
112139</Topbar >
113140
114141<div
0 commit comments