|
282 | 282 |
|
283 | 283 |
|
284 | 284 | document.addEventListener('alpine:init', () => { |
| 285 | + // Draft keys are scoped to the logged-in user so drafts never leak across |
| 286 | + // accounts sharing the same browser. |
| 287 | + const TAGLINE_DRAFT_KEY = 'boost:editUser:taglineDraft:{{ request.user.pk }}'; |
| 288 | + const BIO_DRAFT_KEY = 'boost:editUser:bioDraft:{{ request.user.pk }}'; |
| 289 | + |
285 | 290 | window.createTagline = function () { |
286 | 291 | const taglineInput = document.querySelector("input[name='{{user_profile_form.tagline.name}}']") |
287 | 292 |
|
|
297 | 302 | }, |
298 | 303 |
|
299 | 304 | taglineDraftKey() { |
300 | | - return 'boost:editUser:taglineDraft'; |
| 305 | + return TAGLINE_DRAFT_KEY; |
301 | 306 | }, |
302 | 307 |
|
303 | 308 | onTaglineEdited() { |
|
347 | 352 | contentLength: 0, |
348 | 353 | contentSaveStatus: '', // same states, for the Content field |
349 | 354 | _contentSaveTimer: null, |
| 355 | + _draftRestored: false, |
350 | 356 | errors: { |
351 | 357 | content: '{{ user_profile_form.bio.errors.0|default:""|escapejs }}', |
352 | 358 | }, |
353 | 359 |
|
354 | | - |
355 | | - async init() { |
356 | | - await Alpine.nextTick() |
357 | | - this.restoreContentDraft(); |
358 | | - }, |
359 | | - |
360 | 360 | // Bridge from the WYSIWYG editor: keep the counter, indicator, and draft |
361 | 361 | // in sync. Programmatic updates (initial load / restore) skip the |
362 | 362 | // "Saving to draft" animation and persistence. |
363 | 363 | handleWysiwygUpdate(e) { |
364 | 364 | if (e.detail.id !== 'field-content') return; |
365 | 365 | this.contentLength = e.detail.markdownCharacters; |
366 | 366 | this.content = e.detail.value; |
| 367 | + // The first (programmatic) update signals the editor is mounted — |
| 368 | + // restoring any sooner would dispatch into a not-yet-created editor. |
| 369 | + if (!this._draftRestored) { |
| 370 | + this._draftRestored = true; |
| 371 | + this.restoreContentDraft(); |
| 372 | + } |
367 | 373 | if (!e.detail.programmatic) { |
368 | 374 | this.onContentEdited(); |
369 | 375 | } |
|
376 | 382 | })); |
377 | 383 | }, |
378 | 384 |
|
379 | | - // ── Content draft: localStorage, keyed per post type (mirrors Description) ── |
| 385 | + // ── Content draft: localStorage, keyed per user (mirrors Tagline) ── |
380 | 386 | contentDraftKey() { |
381 | | - return 'boost:userEdit:bioDraft:' + (this.postType || ''); |
| 387 | + return BIO_DRAFT_KEY; |
382 | 388 | }, |
383 | 389 |
|
384 | 390 | onContentEdited(e) { |
|
567 | 573 | throw new Error(fieldErrors.length ? fieldErrors.join(' ') : `Save failed (${res.status})`); |
568 | 574 | } |
569 | 575 | this.saveStatus = 'saved'; |
| 576 | + // The server now holds these values; drop the drafts so they can't |
| 577 | + // shadow the saved data on the next visit. |
| 578 | + try { |
| 579 | + localStorage.removeItem(TAGLINE_DRAFT_KEY); |
| 580 | + localStorage.removeItem(BIO_DRAFT_KEY); |
| 581 | + } catch (_) {} |
570 | 582 | } catch (err) { |
571 | 583 | console.error('Profile save failed:', err); |
572 | 584 | this.saveStatus = 'error'; |
|
0 commit comments