1import { Preferences } from "/js/preferences.js"; 2import { Signal } from "/js/signals.js"; 3import { showToast } from "/js/toasts.js"; 4import { wait } from "/js/utils.js"; 5 6const RETRY_DELAY_MS = 1000; 7 8export class PreferencesProvider { 9 constructor(api) { 10 this.api = api; 11 this._preferences = null; 12 this._pendingFetch = null; 13 this.$preferences = new Signal.State(null); 14 } 15 16 async requirePreferences() { 17 if (this._preferences) return this._preferences; 18 this._pendingFetch ??= this.fetchPreferences().finally(() => { 19 this._pendingFetch = null; 20 }); 21 await this._pendingFetch; 22 return this._preferences; 23 } 24 25 // Fetching preferences sometimes fails, so try it twice. 26 async fetchPreferences() { 27 try { 28 await this._fetchPreferences(); 29 } catch (error) { 30 console.warn("Error fetching preferences, retrying:", error); 31 await wait(RETRY_DELAY_MS); 32 await this._fetchPreferences(); 33 } 34 } 35 36 async _fetchPreferences() { 37 if (!this.api.isAuthenticated) { 38 this._setPreferences(Preferences.createLoggedOutPreferences()); 39 return; 40 } 41 const preferencesObj = await this.api.getPreferences(); 42 const labelerDids = 43 Preferences.getLabelerDidsFromPreferences(preferencesObj); 44 // A labeler service outage shouldn't prevent the app from starting: without 45 // definitions, labels from those labelers simply don't render. 46 let labelerDefs = []; 47 try { 48 labelerDefs = await this.api.getLabelers(labelerDids); 49 } catch (error) { 50 console.warn("Could not load labeler definitions:", error); 51 showToast( 52 "Failed to fetch moderation labels - unmoderated content may be visible", 53 { style: "warning", timeout: 6000 }, 54 ); 55 } 56 this._setPreferences(new Preferences(preferencesObj, labelerDefs)); 57 } 58 59 async updatePreferences(preferences) { 60 if (preferences.persist) { 61 await this.api.updatePreferences(preferences.obj); 62 } 63 this._setPreferences(preferences); 64 } 65 66 _setPreferences(preferences) { 67 this._preferences = preferences; 68 this.$preferences.set(preferences); 69 } 70}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.