1/** 2 * CitrusOS persisted preferences â widgets and in-shell app windows. 3 * 4 * Widgets: auto-key citrusos_widget_prefs_<type> unless persistSettings: false. 5 * Apps: citrusos_app_prefs_<route> (e.g. noisegenerator from noisegenerator.html). 6 */ 7(function (global) { 8 'use strict'; 9 10 var WIDGET_PREFIX = 'citrusos_widget_prefs_'; 11 var APP_PREFIX = 'citrusos_app_prefs_'; 12 13 function normalizeAppId(routeId) { 14 if (!routeId) return ''; 15 return String(routeId).replace(/\.html$/i, '').toLowerCase(); 16 } 17 18 function widgetPrefsKey(defOrType) { 19 var type = typeof defOrType === 'string' ? defOrType : (defOrType && defOrType.type); 20 return type ? WIDGET_PREFIX + type : ''; 21 } 22 23 function appPrefsKey(routeId) { 24 var id = normalizeAppId(routeId); 25 return id ? APP_PREFIX + id : ''; 26 } 27 28 function shouldPersistWidget(def) { 29 if (!def || !def.type) return false; 30 if (def.persistSettings === false) return false; 31 if (def.globalPrefsKey) return true; 32 return def.persistSettings !== false; 33 } 34 35 function resolveWidgetPrefsKey(def) { 36 if (!shouldPersistWidget(def)) return ''; 37 if (def.globalPrefsKey) return def.globalPrefsKey; 38 return widgetPrefsKey(def); 39 } 40 41 function load(key) { 42 if (!key) return {}; 43 try { 44 var raw = global.localStorage.getItem(key); 45 if (!raw) return {}; 46 var parsed = JSON.parse(raw); 47 return parsed && typeof parsed === 'object' ? parsed : {}; 48 } catch (e) { 49 return {}; 50 } 51 } 52 53 function save(key, partial) { 54 if (!key || !partial) return load(key); 55 var next = Object.assign({}, load(key), partial || {}); 56 try { 57 global.localStorage.setItem(key, JSON.stringify(next)); 58 } catch (e) { /* ignore */ } 59 return next; 60 } 61 62 function createWidgetContext(def, instanceSettings) { 63 var key = resolveWidgetPrefsKey(def); 64 var settings = key 65 ? Object.assign({}, load(key), instanceSettings || {}) 66 : Object.assign({}, instanceSettings || {}); 67 68 return { 69 key: key, 70 settings: settings, 71 save: function (partial) { 72 if (!partial) return settings; 73 settings = Object.assign({}, settings, partial); 74 if (key) save(key, partial); 75 return settings; 76 } 77 }; 78 } 79 80 function createAppContext(routeId, defaults) { 81 var key = appPrefsKey(routeId); 82 var settings = key 83 ? Object.assign({}, defaults || {}, load(key)) 84 : Object.assign({}, defaults || {}); 85 86 return { 87 key: key, 88 routeId: routeId || null, 89 settings: settings, 90 save: function (partial) { 91 if (!partial) return settings; 92 settings = Object.assign({}, settings, partial); 93 if (key) save(key, partial); 94 return settings; 95 }, 96 load: function () { 97 if (!key) return settings; 98 settings = Object.assign({}, defaults || {}, load(key)); 99 return settings; 100 } 101 }; 102 } 103 104 global.CitrusPrefs = { 105 widgetPrefsKey: widgetPrefsKey, 106 appPrefsKey: appPrefsKey, 107 shouldPersistWidget: shouldPersistWidget, 108 resolveWidgetPrefsKey: resolveWidgetPrefsKey, 109 load: load, 110 save: save, 111 createWidgetContext: createWidgetContext, 112 createAppContext: createAppContext 113 }; 114})(typeof window !== 'undefined' ? window : this);
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.