@@ -63,6 +63,7 @@ class QuickServeClient {
6363 `${ this . serverUrl } /api/files?path=${ encodeURIComponent ( path ) } ` ,
6464 {
6565 headers : this . getAuthHeaders ( ) ,
66+ credentials : "include" ,
6667 }
6768 ) ;
6869
@@ -154,6 +155,7 @@ class QuickServeClient {
154155 ) } `,
155156 {
156157 headers : this . getAuthHeaders ( ) ,
158+ credentials : "include" ,
157159 }
158160 ) ;
159161
@@ -186,13 +188,13 @@ class QuickServeClient {
186188 try {
187189 const response = await fetch ( `${ this . serverUrl } /api/upload` , {
188190 method : "POST" ,
189- headers : this . getAuthHeaders ( false ) ,
191+ credentials : "include" ,
190192 body : formData ,
191193 } ) ;
192194
193195 if ( response . ok ) {
194196 await this . loadFiles ( currentPath ) ;
195- this . showTempMessage ( "Upload successful!" ) ;
197+ this . showSuccess ( "Upload successful!" ) ;
196198 } else {
197199 throw new Error ( "Upload failed" ) ;
198200 }
@@ -206,6 +208,10 @@ class QuickServeClient {
206208 if ( isJson ) {
207209 headers [ "Content-Type" ] = "application/json" ;
208210 }
211+
212+ const authString = btoa ( `${ this . username } :${ this . password } ` ) ;
213+ headers [ "Authorization" ] = `Basic ${ authString } ` ;
214+
209215 return headers ;
210216 }
211217
@@ -233,16 +239,75 @@ class QuickServeClient {
233239 }
234240
235241 showError ( message ) {
236- alert ( message ) ;
242+ this . showToast ( message , "error" ) ;
243+ }
244+
245+ showSuccess ( message ) {
246+ this . showToast ( message , "success" ) ;
247+ }
248+
249+ showInfo ( message ) {
250+ this . showToast ( message , "info" ) ;
251+ }
252+
253+ showToast ( message , type = "info" , duration = 5000 ) {
254+ const toastContainer = document . getElementById ( "toastContainer" ) ;
255+
256+ const toast = document . createElement ( "div" ) ;
257+ toast . className = `toast toast-${ type } ` ;
258+
259+ let icon = "info-circle" ;
260+ if ( type === "success" ) icon = "check-circle" ;
261+ if ( type === "error" ) icon = "exclamation-circle" ;
262+
263+ toast . innerHTML = `
264+ <i class="fas fa-${ icon } toast-icon"></i>
265+ <div class="toast-content">${ message } </div>
266+ <button class="toast-close" aria-label="Close notification">
267+ <i class="fas fa-times"></i>
268+ </button>
269+ ` ;
270+
271+ toastContainer . appendChild ( toast ) ;
272+
273+ let removeTimeout ;
274+ if ( duration > 0 ) {
275+ removeTimeout = setTimeout ( ( ) => {
276+ this . removeToast ( toast ) ;
277+ } , duration ) ;
278+ }
279+
280+ const closeBtn = toast . querySelector ( ".toast-close" ) ;
281+ closeBtn . addEventListener ( "click" , ( ) => {
282+ if ( removeTimeout ) clearTimeout ( removeTimeout ) ;
283+ this . removeToast ( toast ) ;
284+ } ) ;
285+
286+ return toast ;
287+ }
288+
289+ removeToast ( toast ) {
290+ toast . classList . add ( "hiding" ) ;
291+ setTimeout ( ( ) => {
292+ if ( toast . parentNode ) {
293+ toast . parentNode . removeChild ( toast ) ;
294+ }
295+ } , 300 ) ;
237296 }
238297
239298 showTempMessage ( message ) {
240299 const uploadLabel = document . getElementById ( "uploadLabel" ) ;
241300 const originalText = uploadLabel . innerHTML ;
242- uploadLabel . innerHTML = `<i class="fas fa-check"></i> ${ message } ` ;
301+
302+ this . showSuccess ( message ) ;
303+
304+ uploadLabel . innerHTML = `<i class="fas fa-check"></i> Uploaded` ;
305+ uploadLabel . style . opacity = "0.7" ;
306+
243307 setTimeout ( ( ) => {
244308 uploadLabel . innerHTML = originalText ;
245- } , 2000 ) ;
309+ uploadLabel . style . opacity = "1" ;
310+ } , 1500 ) ;
246311 }
247312
248313 updateNavigation ( currentPath ) {
0 commit comments