@@ -55,6 +55,9 @@ function extractFileName(path: string): string {
5555 return path . split ( / [ \\ / ] / ) . pop ( ) || path ;
5656}
5757
58+ // Check if we're running in a web environment
59+ const isWeb = typeof window !== 'undefined' && ! window . __TAURI__ ;
60+
5861export const useTabsStore = defineStore ( "tabs" , {
5962 state : ( ) => {
6063 const firstTabId = generateId ( ) ;
@@ -99,9 +102,11 @@ export const useTabsStore = defineStore("tabs", {
99102 this . tabs . push ( newTab ) ;
100103 this . activeTabId = newTab . id ;
101104
102- // Show and focus window when a new tab is created
103- await appWindow . show ( ) ;
104- await appWindow . setFocus ( ) ;
105+ // Show and focus window when a new tab is created (Tauri only)
106+ if ( ! isWeb ) {
107+ await appWindow . show ( ) ;
108+ await appWindow . setFocus ( ) ;
109+ }
105110 } ,
106111
107112 /**
@@ -116,18 +121,30 @@ export const useTabsStore = defineStore("tabs", {
116121
117122 // If tab has unsaved changes, ask user before closing
118123 if ( tabToClose . isUnsaved ) {
119- const result = await ask ( `"${ tabToClose . name } " has unsaved changes.` , {
120- title : "Unsaved Changes" ,
121- type : "warning" ,
122- okLabel : "Save" ,
123- cancelLabel : "Don't Save" , // This will return `false`
124- } ) ;
125-
126- if ( result ) {
127- // User clicked "Save", result is true
128- const savedSuccessfully = await this . saveActiveFile ( ) ;
129- if ( ! savedSuccessfully ) {
130- return ; // User cancelled the save dialog, so we abort closing the tab
124+ if ( isWeb ) {
125+ // In web environment, use browser confirm dialog
126+ const result = confirm ( `"${ tabToClose . name } " has unsaved changes. Do you want to save?` ) ;
127+ if ( result ) {
128+ const savedSuccessfully = await this . saveActiveFile ( ) ;
129+ if ( ! savedSuccessfully ) {
130+ return ; // User cancelled the save dialog, so we abort closing the tab
131+ }
132+ }
133+ } else {
134+ // In Tauri environment, use native dialog
135+ const result = await ask ( `"${ tabToClose . name } " has unsaved changes.` , {
136+ title : "Unsaved Changes" ,
137+ type : "warning" ,
138+ okLabel : "Save" ,
139+ cancelLabel : "Don't Save" , // This will return `false`
140+ } ) ;
141+
142+ if ( result ) {
143+ // User clicked "Save", result is true
144+ const savedSuccessfully = await this . saveActiveFile ( ) ;
145+ if ( ! savedSuccessfully ) {
146+ return ; // User cancelled the save dialog, so we abort closing the tab
147+ }
131148 }
132149 }
133150 // If user clicked "Don't Save" (result is false), we just proceed to close.
@@ -166,8 +183,8 @@ export const useTabsStore = defineStore("tabs", {
166183 }
167184 }
168185
169- // Hide window if no tabs left
170- if ( this . tabs . length === 0 ) {
186+ // Hide window if no tabs left (Tauri only)
187+ if ( ! isWeb && this . tabs . length === 0 ) {
171188 appWindow . hide ( ) ;
172189 }
173190 } ,
@@ -201,6 +218,12 @@ export const useTabsStore = defineStore("tabs", {
201218
202219 // === File operations using backend commands ===
203220 async openFileFromDialog ( ) {
221+ if ( isWeb ) {
222+ // In web environment, show a message that file operations are not available
223+ alert ( "File operations are not available in the web version. Please download the desktop app for full functionality." ) ;
224+ return ;
225+ }
226+
204227 try {
205228 const results = await invoke < Array < {
206229 path : string ;
@@ -232,6 +255,12 @@ export const useTabsStore = defineStore("tabs", {
232255 } ,
233256
234257 async openSpecificFile ( path : string ) {
258+ if ( isWeb ) {
259+ // In web environment, show a message that file operations are not available
260+ alert ( "File operations are not available in the web version. Please download the desktop app for full functionality." ) ;
261+ return ;
262+ }
263+
235264 try {
236265 // 如果已經有這個檔案的分頁,直接切換
237266 const existingTab = this . tabs . find ( ( tab ) => tab . path === path ) ;
@@ -275,6 +304,12 @@ export const useTabsStore = defineStore("tabs", {
275304 return this . saveActiveFileAs ( ) ;
276305 }
277306
307+ if ( isWeb ) {
308+ // In web environment, just mark as saved
309+ activeTab . isUnsaved = false ;
310+ return true ;
311+ }
312+
278313 try {
279314 await invoke ( "save_file" , {
280315 path : activeTab . path ,
@@ -293,6 +328,23 @@ export const useTabsStore = defineStore("tabs", {
293328 const activeTab = this . tabs . find ( ( tab ) => tab . id === this . activeTabId ) ;
294329 if ( ! activeTab ) return false ;
295330
331+ if ( isWeb ) {
332+ // In web environment, create a download link
333+ const blob = new Blob ( [ activeTab . content ] , { type : 'text/plain' } ) ;
334+ const url = URL . createObjectURL ( blob ) ;
335+ const a = document . createElement ( 'a' ) ;
336+ a . href = url ;
337+ a . download = activeTab . name || 'untitled.txt' ;
338+ document . body . appendChild ( a ) ;
339+ a . click ( ) ;
340+ document . body . removeChild ( a ) ;
341+ URL . revokeObjectURL ( url ) ;
342+
343+ // Mark as saved
344+ activeTab . isUnsaved = false ;
345+ return true ;
346+ }
347+
296348 const settingsStore = useSettingsStore ( ) ;
297349
298350 try {
@@ -316,6 +368,11 @@ export const useTabsStore = defineStore("tabs", {
316368
317369 // === Menu event listeners ===
318370 setup_menu_listeners ( ) {
371+ if ( isWeb ) {
372+ // Skip menu listeners in web environment
373+ return ;
374+ }
375+
319376 // Listen for shortcut-new-note event from backend
320377 listen ( "shortcut-new-note" , ( ) => {
321378 this . createTab ( ) ;
0 commit comments