+23
-5
src/components/organisms/grain-engagement-bar.js
+23
-5
src/components/organisms/grain-engagement-bar.js
···
73
73
if (!auth.isAuthenticated || this._loading || !this.galleryUri) return;
74
74
75
75
this._loading = true;
76
+
77
+
// Store previous state for rollback
78
+
const previousState = {
79
+
viewerHasFavorited: this.viewerHasFavorited,
80
+
viewerFavoriteUri: this.viewerFavoriteUri,
81
+
favoriteCount: this.favoriteCount
82
+
};
83
+
84
+
// Optimistic update - apply immediately
85
+
this.viewerHasFavorited = !this.viewerHasFavorited;
86
+
this.favoriteCount += this.viewerHasFavorited ? 1 : -1;
87
+
if (!this.viewerHasFavorited) {
88
+
this.viewerFavoriteUri = null;
89
+
}
90
+
76
91
try {
77
92
const update = await mutations.toggleFavorite(
78
93
this.galleryUri,
79
-
this.viewerHasFavorited,
80
-
this.viewerFavoriteUri,
81
-
this.favoriteCount
94
+
previousState.viewerHasFavorited,
95
+
previousState.viewerFavoriteUri,
96
+
previousState.favoriteCount
82
97
);
83
-
this.viewerHasFavorited = update.viewerHasFavorited;
98
+
// Update with real URI from server (needed for future deletes)
84
99
this.viewerFavoriteUri = update.viewerFavoriteUri;
85
-
this.favoriteCount = update.favoriteCount;
86
100
} catch (err) {
101
+
// Rollback on failure
87
102
console.error('Failed to toggle favorite:', err);
103
+
this.viewerHasFavorited = previousState.viewerHasFavorited;
104
+
this.viewerFavoriteUri = previousState.viewerFavoriteUri;
105
+
this.favoriteCount = previousState.favoriteCount;
88
106
this.shadowRoot.querySelector('grain-toast').show('Failed to update');
89
107
} finally {
90
108
this._loading = false;