-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLSaver.js
More file actions
385 lines (348 loc) · 12.9 KB
/
LSaver.js
File metadata and controls
385 lines (348 loc) · 12.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
// ==UserScript==
// @name WME Layer Saver
// @author HBiede
// @namespace hbiede.com
// @description Save the state of different combinations of layer display settings.settings
// @match https://www.waze.com/editor*
// @match https://beta.waze.com/editor*
// @match https://www.waze.com/*/editor*
// @match https://beta.waze.com/*/editor*
// @require https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
// @version 2026.01.01.004
// @grant none
// @copyright 2026 HBiede
// @downloadURL https://update.greasyfork.org/scripts/383384/WME%20Layer%20Saver.user.js
// @updateURL https://update.greasyfork.org/scripts/383384/WME%20Layer%20Saver.meta.js
// ==/UserScript==
/* global W */
/* global WazeWrap */
const DEBUG = true;
const UPDATE_DESCRIPTION =
"<h4 style='margin-bottom: 5px;'>Bug Fixes:</h4><ul><li>Rework loading</li></ul>";
const DEFAULT_SETTINGS = { settings: [] };
const SCRIPT_STRING = "LSaver";
const SCRIPT_NAME = "Layer Saver";
const LAYER_SELECTION_TYPES = "wz-toggle-switch,wz-checkbox";
const LAYER_CONTAINER = "layer-switcher-region";
const DELIMITER = "::";
const settings = DEFAULT_SETTINGS;
let sdk = null;
const logPrint = (...message) => {
if (DEBUG) console.log(...message);
};
// clear the alert text
function setAlertParagraph(message) {
if (typeof message === "string")
document.getElementById("LSaverAlertText").innerText = message;
}
// load the settings.settings from the local and server sources
async function loadSettings() {
let local;
try {
local = JSON.parse(localStorage.getItem(SCRIPT_STRING));
} catch (e) {
local = DEFAULT_SETTINGS;
}
try {
let returnValue = { ...DEFAULT_SETTINGS, ...(local ?? {}) };
const serverSettings = await WazeWrap.Remote.RetrieveSettings(
SCRIPT_STRING
);
if (serverSettings && serverSettings.time > returnValue.time) {
returnValue = { ...returnValue, ...(serverSettings ?? {}) }
}
return returnValue;
} catch (e) {
logPrint(`${e.message}`);
return DEFAULT_SETTINGS;
}
}
// save settings.settings locally/to the server
function saveSettings() {
settings.time = Date.now();
WazeWrap.Remote.SaveSettings(SCRIPT_STRING, settings);
localStorage.setItem(SCRIPT_STRING, JSON.stringify(settings));
}
// load all the settings.settings groups
async function loadLayerSaverSettings() {
const returnValue = await loadSettings(SCRIPT_STRING);
logPrint(returnValue);
if (returnValue.settings.every((s) => s.includes(`${DELIMITER}[`))) {
settings.settings = returnValue.settings;
} else {
settings.settings = returnValue.settings.map((s) => {
const [title, string] = s.split(DELIMITER);
const list = string
.split("layer-switcher-group_")
.map((t) => `layer-switcher-group_${t}`);
return `${title}${DELIMITER}${JSON.stringify(list)}`;
});
}
saveSettings(SCRIPT_STRING);
logPrint(await WazeWrap.Remote.RetrieveSettings(SCRIPT_STRING));
}
// save all the settings groups
function saveLayerSaverSettings() {
setAlertParagraph("");
let arrayBuilder = [];
const currentSettings = document.getElementById("LSaverSelector").children;
for (let i = 0; i < currentSettings.length; i++) {
arrayBuilder = arrayBuilder.concat([
`${currentSettings[i].textContent}${DELIMITER}${JSON.stringify(
currentSettings[i].settingsList
)}`,
]);
logPrint(`${currentSettings[i].textContent}`);
}
settings.settings = arrayBuilder;
logPrint(settings.settings);
saveSettings(SCRIPT_STRING);
}
// load the selected settings.settings group
async function loadLayerSettings() {
setAlertParagraph("");
const settingsList = JSON.parse(
document.getElementById("LSaverSelector").selectedOptions[0].settingsList
);
const selected = new Set(settingsList);
logPrint(`Loading according to: ${JSON.stringify([...selected])}`);
const toggleSelectorList = (toggles) => {
let hasChanged = false;
for (let i = 0; i < toggles.length; i++) {
const id = identifierForToggle(toggles[i]);
// if the input is in the group and not checked, or not in the group and checked, click the input
if ((id && selected.has(id)) !== toggles[i].checked) {
logPrint(`Toggling ${id}`);
toggles[i].click();
hasChanged = true;
}
}
return hasChanged;
};
LAYER_SELECTION_TYPES.split(",").forEach((type) => {
return toggleSelectorList(
document.getElementById(LAYER_CONTAINER).querySelectorAll(type)
);
});
logPrint(
`Loaded Group: ${
document.getElementById("LSaverSelector").selectedOptions[0].textContent
}`
);
}
// delete the selected settings.settings group
function deleteLayerSettings() {
setAlertParagraph("");
const name =
document.getElementById("LSaverSelector").children[
document.getElementById("LSaverSelector").selectedIndex
].textContent;
document
.getElementById("LSaverSelector")
.children[document.getElementById("LSaverSelector").selectedIndex].remove();
saveLayerSaverSettings();
logPrint(`Deleted Group: ${name}`);
updateDisabledStates();
}
function identifierForToggle(toggle) {
return toggle.id || toggle.name || toggle.innerText;
}
// turn the currently selected inputs into a usable string
function getCurrentLayerSettings() {
const toggles = document
.getElementById(LAYER_CONTAINER)
.querySelectorAll(LAYER_SELECTION_TYPES);
const res = [...toggles].filter((t) => t.checked).map(identifierForToggle);
logPrint(res);
return res;
}
// save the selected settings.settings group
function saveLayerSettings() {
setAlertParagraph("");
const layerSettingSelector = document.createElement("option");
layerSettingSelector.textContent = prompt(
"Name Your New Layer Settings Group",
""
);
if (layerSettingSelector.textContent != null) {
layerSettingSelector.settingsList = JSON.stringify(
getCurrentLayerSettings()
);
document.getElementById("LSaverSelector").appendChild(layerSettingSelector);
saveLayerSaverSettings();
logPrint(`Created Group: ${layerSettingSelector.textContent}`);
updateDisabledStates();
return;
}
logPrint("Save Aborted");
}
function populateSelector() {
// build the selector options
if (settings.settings.length > 0) {
for (let i = 0; i < settings.settings.length; i++) {
const setting = settings.settings[i].split(DELIMITER);
const layerSettingSelector = document.createElement("option");
layerSettingSelector.textContent = setting[0];
layerSettingSelector.value = setting[0];
layerSettingSelector.settingsList = setting[1] || "";
document
.getElementById("LSaverSelector")
.appendChild(layerSettingSelector);
}
}
updateDisabledStates();
}
// build the selector on the script tab
function selectorInit() {
console.log("Loading Layer Settings");
populateSelector();
// add button listeners
document
.getElementById("LSaverLoadBtn")
.addEventListener("click", async () => {
await loadLayerSettings();
});
document.getElementById("LSaverDeleteBtn").addEventListener("click", () => {
deleteLayerSettings();
});
document.getElementById("LSaverSaveBtn").addEventListener("click", () => {
saveLayerSettings();
});
document
.getElementById("LSaverSetDefaultBtn")
.addEventListener("click", () => {
document
.getElementById("LSaverSelector")
.add(
document.getElementById("LSaverSelector").children[
document.getElementById("LSaverSelector").selectedIndex
],
0
);
saveLayerSaverSettings();
});
document.getElementById("LSaverImportBtn").addEventListener("click", () => {
importSettingsList();
});
document.getElementById("LSaverExportBtn").addEventListener("click", () => {
exportSettingsList();
});
document
.getElementById("LSaverExportAllBtn")
.addEventListener("click", () => {
exportAllSettingsString();
});
console.log("Layer Settings Loaded");
}
// import a settings array in the from of a base64 encoded stringified version of the settings array
function importSettingsList() {
try {
const [title, settingsList] = window
.atob(prompt("Import settings text:", ""))
.split(DELIMITER);
if (settingsList) {
const importedArray = JSON.parse(settingsList);
if (!Array.isArray(importedArray)) {
setAlertParagraph("Invalid Input String");
return;
}
settings.settings = settings.settings.concat(`${title}${DELIMITER}${JSON.stringify(settingsList)}`);
saveSettings("LSaver");
const selector = document.getElementById("LSaverSelector");
while (selector.firstChild) {
selector.removeChild(selector.firstChild);
}
populateSelector();
setAlertParagraph("Loaded");
}
} catch (e) {
setAlertParagraph(e.message);
}
}
function copyToClipboard(text) {
if (text === "") {
setAlertParagraph("Cannot export no settings.");
return;
}
const ta = document.createElement("textarea");
ta.value = text;
document.body.appendChild(ta);
ta.select();
document.execCommand("copy");
document.body.removeChild(ta);
setAlertParagraph("Copied all groups' settings text to clipboard");
}
// export the selected settings string
function exportSettingsList() {
const selectedSetting =
document.getElementById("LSaverSelector").selectedOptions[0];
if (selectedSetting) {
copyToClipboard(
window.btoa(
JSON.stringify([
`${selectedSetting.textContent}${DELIMITER}${JSON.stringify(
selectedSetting.settingsList
)}`,
])
)
);
} else {
setAlertParagraph("Select a group");
}
}
// export a settings array in the form of a base64 encoded stringified version of the settings array
function exportAllSettingsString() {
copyToClipboard(window.btoa(JSON.stringify(settings.settings)));
}
function updateDisabledStates() {
const hasSettings = settings.settings.length > 0;
const hasSelection =
hasSettings && !!document.getElementById("LSaverSelector").value;
document.getElementById("LSaverLoadBtn").disabled = !hasSelection;
document.getElementById("LSaverDeleteBtn").disabled = !hasSelection;
document.getElementById("LSaverSetDefaultBtn").disabled = !hasSelection;
document.getElementById("LSaverExportBtn").disabled = !hasSelection;
document.getElementById("LSaverExportAllBtn").disabled = !hasSettings;
}
// Create the tab in the sidebar via WazeWrap
function createTab() {
sdk.Sidebar.registerScriptTab().then(({ tabLabel, tabPane }) => {
tabLabel.innerText = "Layer Saver";
tabPane.innerHTML = `<h3><b>WME Layer Saver</b></h3><p><i>${GM_info.script.version} by ${GM_info.script.author}</i></p><div id="LSaverSelectorDiv"><label>Groups</label><br><select id="LSaverSelector" style="width:90%; margin-bottom: 8px;"></select></div><div id="LSaverInteractionDiv"></div><button class="btn btn-primary" id="LSaverLoadBtn" title="Load" style="margin: 8px 8px auto auto;">Load</button><button class="btn btn-primary" id="LSaverDeleteBtn" title="Delete Selected" style="margin: 8px 8px auto auto;">Delete Selected</button><br><button class="btn btn-primary" id="LSaverSaveBtn" title="Save New Group" style="margin: 8px 8px auto auto;">Save New Group</button><br><button class="btn btn-primary" id="LSaverSetDefaultBtn" title="Set As Default" style="margin: 8px 8px auto auto;">Set As Default</button><br><button class="btn btn-primary" id="LSaverImportBtn" title="Import" style="margin: 8px 8px auto auto;">Import</button><button class="btn btn-primary" id="LSaverExportBtn" title="Export" style="margin: 8px 8px auto auto;">Export</button><button class="btn btn-primary" id="LSaverExportAllBtn" title="Export All" style="margin: 8px 8px auto auto;">Export All</button><p style="padding-top: 10px; font-weight: bold;" id="LSaverAlertText"></p></div>`;
tabPane.id = "WMELayerSaver";
selectorInit();
});
}
// main function
async function initLayerSaver(attempts = 1) {
sdk = window.getWmeSdk({ scriptId: SCRIPT_STRING, scriptName: SCRIPT_NAME });
if (attempts <= 1000) {
if (
!WazeWrap.Ready ||
typeof W === "undefined" ||
typeof W.map === "undefined" ||
typeof W.loginManager === "undefined" ||
!document.getElementById(LAYER_CONTAINER)
) {
logPrint("Layer Saver: retry");
setTimeout(() => {
initLayerSaver(attempts++);
}, 800);
} else {
logPrint("Starting Layer Saver");
await loadLayerSaverSettings();
createTab();
WazeWrap.Interface.ShowScriptUpdate(
GM_info.script.name,
GM_info.script.version,
UPDATE_DESCRIPTION,
"https://greasyfork.org/en/scripts/383384-wme-layer-saver",
"https://www.waze.com/forum/viewtopic.php?f=819&t=283513"
);
}
}
}
// start
window.SDK_INITIALIZED.then(() => {
setTimeout(initLayerSaver, 1000);
});