Skip to content

Commit 9372f79

Browse files
committed
Release 3.0.3.5 - 2/4/2024
1 parent 9d192ef commit 9372f79

File tree

16 files changed

+314
-352
lines changed

16 files changed

+314
-352
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,23 @@ Today, on March 18, 2024, this repository has undergone a significant update. Ev
6565
<details>
6666
<summary>Whats new!</summary>
6767

68+
## Changelog - 2/4/2024
69+
Significant optimizations and bug fixes have been implemented. Detailed changes are as follows:
70+
71+
- Manifest updated to version 3.0.3.5.
72+
- JavaScript file structure and codebase streamlined:
73+
- The `options` folder has been removed; `settingsDown.js` is now located in the `settings` folder.
74+
- Consolidated `toggle.js` and contents of the `shared` folder into a single file `themeToggles.js` within the `settings` folder.
75+
- Enhanced theme settings functionality, particularly the 'Auto' feature, and resolved related bugs.
76+
- Refined the extension's enabled state logic for improved performance.
77+
- Resolved an issue in `import.js` to ensure reliable importing of user settings.
78+
- Conducted code optimization for `settingsOptions.js`, `settings.js`, `search.js`, `locals.js`, and `background.js`.
79+
- Corrected a defect affecting the lyrics color display.
80+
- Improved code formatting across several files for better readability and maintenance.
81+
- Addressed various minor bugs to enhance overall stability.
82+
83+
84+
---
6885

6986
28/3/2024: Removed `declarativeContent` as indicated in the below email (thanks, Chrome); fixed some minor padding issues and corrected some minor coloring issues as well.
7087

SpotOn/background.js

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
164164
sendResponse({ status: themeLocked ? "theme_locked" : "theme_unlocked" });
165165
}
166166
});
167-
//
168167

169168
// Checkbox functions for the settings.html
170169
const defaultOptions = {
@@ -244,40 +243,27 @@ function handleOption(option, tabId, options) {
244243
addLyricsButton: "addLyrics.js",
245244
};
246245

247-
if (optionScripts[option]) {
248-
if (options[option]) {
249-
chrome.scripting.executeScript({
250-
target: { tabId: tabId },
251-
files: [`./options/${optionScripts[option]}`],
252-
});
253-
}
254-
} else {
255-
const fileName = `./options/${option}.css`;
256-
if (options[option]) {
257-
chrome.scripting.insertCSS({
258-
target: { tabId: tabId },
259-
files: [fileName],
260-
});
261-
}
246+
const fileToInject = optionScripts[option] ? `./options/${optionScripts[option]}` : `./options/${option}.css`;
247+
const method = optionScripts[option] ? 'executeScript' : 'insertCSS';
248+
249+
if (options[option]) {
250+
chrome.scripting[method]({
251+
target: { tabId },
252+
files: [fileToInject],
253+
});
262254
}
263255
}
264256

265-
chrome.runtime.onInstalled.addListener((details) => {
266-
if (details.reason === "install") {
267-
chrome.storage.sync.set({
268-
...defaultOptions,
269-
extensionEnabled: true,
270-
}, () => console.log("Default options and extensionEnabled set."));
271-
// chrome.tabs.create({ url: "SITE-HERE" });
257+
chrome.runtime.onInstalled.addListener(({ reason }) => {
258+
if (reason === "install") {
259+
chrome.storage.sync.set({ ...defaultOptions, extensionEnabled: true });
272260
}
273261
});
274262

275-
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
276-
if (changeInfo.status === "complete" && tab.url.startsWith("https://open.spotify.com/")) {
277-
chrome.storage.sync.get(null, (options) => {
278-
for (const option of Object.keys(options)) {
279-
handleOption(option, tabId, options);
280-
}
263+
chrome.tabs.onUpdated.addListener((tabId, { status }, tab) => {
264+
if (status === "complete" && tab.url.startsWith("https://open.spotify.com/")) {
265+
chrome.storage.sync.get(null, options => {
266+
Object.keys(options).forEach(option => handleOption(option, tabId, options));
281267
});
282268
}
283269
});
@@ -320,7 +306,8 @@ function generateColorCSS(customColor) {
320306
.AzO2ondhaHJntbGy_3_S,
321307
.Nw1INlIyra3LT1JjvoqH,
322308
#main > div.Root.encore-dark-theme > div.ZQftYELq0aOsg6tPbVbV > div.JG5J9NWJkaUO9fiKECMA,
323-
.pGU_qEtNT1qWKjrRbvan {
309+
.pGU_qEtNT1qWKjrRbvan,
310+
.EZFyDnuQnx5hw78phLqP {
324311
background-color: ${customColor} !important;
325312
background: ${customColor} !important;
326313
background: var(${customColor}) !important;

SpotOn/js/settings/import.js

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
function triggerDownload(dataURL, filename) {
1+
function triggerDownload(jsonData, filename) {
2+
const blob = new Blob([jsonData], { type: 'application/json' });
3+
const url = URL.createObjectURL(blob);
24
const a = document.createElement("a");
3-
a.href = dataURL;
5+
a.href = url;
46
a.download = filename;
5-
a.style.display = 'none';
67
document.body.appendChild(a);
78
a.click();
89
document.body.removeChild(a);
10+
URL.revokeObjectURL(url); // Clean up the object URL
911
}
1012

1113
async function exportOptions() {
@@ -15,8 +17,7 @@ async function exportOptions() {
1517
chrome.storage.local.get()
1618
]);
1719
const allOptions = { sync: syncOptions, local: localOptions };
18-
const dataStr = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(allOptions))}`;
19-
triggerDownload(dataStr, "SpotOn_Options.json");
20+
triggerDownload(JSON.stringify(allOptions), "SpotOn_Options.json");
2021
} catch (error) {
2122
console.error("Error during export:", error);
2223
alert("Error exporting options.");
@@ -33,22 +34,24 @@ async function importOptions(event) {
3334
try {
3435
const text = await file.text();
3536
const importedOptions = JSON.parse(text);
36-
await Promise.all([
37-
importedOptions.sync ? chrome.storage.sync.set(importedOptions.sync) : null,
38-
importedOptions.local ? chrome.storage.local.set(importedOptions.local) : null
39-
]);
37+
const promises = [];
38+
if (importedOptions.sync) {
39+
promises.push(chrome.storage.sync.set(importedOptions.sync));
40+
}
41+
if (importedOptions.local) {
42+
promises.push(chrome.storage.local.set(importedOptions.local));
43+
}
44+
await Promise.all(promises);
4045
alert("All options imported successfully!");
46+
window.location.reload();
4147
} catch (error) {
4248
console.error("Error during import:", error);
43-
alert("Error importing options. Please ensure the selected file is a valid JSON file.");
49+
alert("Error importing options. Please check the console for more details.");
4450
}
4551
}
4652

47-
document.getElementById('exportOptionsButton')?.addEventListener('click', exportOptions);
48-
document.getElementById('importOptionsButton')?.addEventListener('click', () => {
49-
const importInput = document.getElementById('importOptionsInput');
50-
if (importInput) {
51-
importInput.click();
52-
}
53+
document.getElementById('exportOptionsButton').addEventListener('click', exportOptions);
54+
document.getElementById('importOptionsButton').addEventListener('click', () => {
55+
document.getElementById('importOptionsInput').click();
5356
});
54-
document.getElementById('importOptionsInput')?.addEventListener('change', importOptions);
57+
document.getElementById('importOptionsInput').addEventListener('change', importOptions);

SpotOn/js/settings/search.js

Lines changed: 38 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,63 @@
1-
const addHighlightClass = () => {
2-
const style = document.createElement('style');
3-
style.type = 'text/css';
4-
style.innerHTML = '.highlight { background-color: var(--highlight); }';
5-
document.head.appendChild(style);
6-
};
7-
8-
const hideOptionGroups = () => {
9-
const optionGroups = document.querySelectorAll(".option-group:not(#default-content)");
10-
optionGroups.forEach(group => group.style.display = "none");
11-
};
12-
13-
const highlightMatchingText = (option, searchInput) => {
14-
const regex = new RegExp(`(${searchInput})`, 'gi');
15-
option.innerHTML = option.textContent.replace(regex, "<span class='highlight'>$1</span>");
16-
};
17-
181
const searchInput = document.getElementById("search-input");
192
const defaultContent = document.getElementById("default-content");
203
const matchCountElement = document.getElementById('match-count');
214

22-
const handleNoResultsFound = () => {
23-
searchInput.placeholder = "Try another word";
24-
defaultContent.style.display = "block";
25-
};
26-
27-
const displayMatchCount = matchCount => {
28-
matchCountElement.textContent = `Matches found: ${matchCount}`;
5+
const toggleDisplay = (element, show) => {
6+
element.style.display = show ? "block" : "none";
297
};
308

31-
const resetSearchInput = () => {
32-
searchInput.placeholder = "Search...";
9+
const createHighlightStyle = () => {
10+
if (!document.querySelector('#highlight-style')) {
11+
const style = document.createElement('style');
12+
style.id = 'highlight-style';
13+
style.type = 'text/css';
14+
style.textContent = '.highlight { background-color: var(--highlight); }';
15+
document.head.appendChild(style);
16+
}
3317
};
3418

35-
const removeExistingHighlights = () => {
36-
const highlighted = document.querySelectorAll(".highlight");
37-
highlighted.forEach(highlight => highlight.outerHTML = highlight.innerHTML);
19+
const updatePlaceholder = (placeholder) => {
20+
searchInput.placeholder = placeholder;
3821
};
3922

40-
const showDefaultContent = () => {
41-
defaultContent.style.display = "block";
23+
const updateMatchCount = (count) => {
24+
matchCountElement.textContent = count ? `Matches found: ${count}` : "";
4225
};
4326

44-
const removeMatchCount = () => {
45-
matchCountElement.textContent = "";
27+
const highlightMatchingText = (text, term) => {
28+
const regex = new RegExp(`(${term})`, 'gi');
29+
return text.replace(regex, "<span class='highlight'>$1</span>");
4630
};
4731

4832
searchInput.addEventListener("input", () => {
49-
const searchInputValue = searchInput.value.toLowerCase();
33+
const term = searchInput.value.trim().toLowerCase();
5034
let matchCount = 0;
5135

52-
hideOptionGroups();
53-
54-
if (searchInputValue.trim() !== "") {
55-
const options = document.querySelectorAll(".option label");
56-
options.forEach(option => {
57-
if (option.textContent.toLowerCase().includes(searchInputValue)) {
58-
option.closest(".option-group").style.display = "block";
59-
highlightMatchingText(option, searchInputValue);
36+
document.querySelectorAll(".option-group").forEach(group => {
37+
toggleDisplay(group, group.id === "default-content");
38+
});
39+
40+
if (term) {
41+
document.querySelectorAll(".option label").forEach(label => {
42+
const text = label.textContent.toLowerCase();
43+
if (text.includes(term)) {
44+
const optionGroup = label.closest(".option-group");
45+
toggleDisplay(optionGroup, true);
46+
label.innerHTML = highlightMatchingText(label.textContent, term);
6047
matchCount++;
48+
} else {
49+
label.innerHTML = label.textContent; // Remove any previous highlights
6150
}
6251
});
6352

64-
const visibleGroups = document.querySelectorAll('.option-group[style="display: block;"]');
65-
visibleGroups.length === 0 ? handleNoResultsFound() : null;
66-
displayMatchCount(matchCount);
53+
updatePlaceholder("Try another word");
54+
updateMatchCount(matchCount);
55+
toggleDisplay(defaultContent, matchCount === 0);
6756
} else {
68-
resetSearchInput();
69-
removeExistingHighlights();
70-
showDefaultContent();
71-
removeMatchCount();
57+
updatePlaceholder("Search...");
58+
updateMatchCount();
59+
toggleDisplay(defaultContent, true);
7260
}
7361
});
7462

75-
addHighlightClass();
63+
createHighlightStyle();

SpotOn/js/settings/settings.js

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
const saveButton = document.getElementById("save");
55
const settingsButton = document.getElementById("settingsButton");
6-
const checkboxElements = {};
76
const countElements = {
87
onCount: document.getElementById("on-count"),
98
offCount: document.getElementById("off-count"),
@@ -76,55 +75,59 @@
7675
youwontlike: false,
7776
};
7877

78+
const defaultOptionsKeys = Object.keys(defaultOptions);
79+
const totalCount = defaultOptionsKeys.length;
80+
countElements.totalCount.textContent = totalCount;
81+
82+
const checkboxElements = defaultOptionsKeys.reduce((elements, id) => {
83+
elements[id] = document.getElementById(id);
84+
return elements;
85+
}, {});
86+
7987
function updateToggleCounts() {
80-
const onCount = Object.values(checkboxElements).filter(el => el.checked).length;
81-
const totalCount = Object.keys(defaultOptions).length;
88+
const onCount = defaultOptionsKeys.reduce((count, id) => count + (checkboxElements[id].checked ? 1 : 0), 0);
8289
const offCount = totalCount - onCount;
8390

8491
countElements.onCount.textContent = onCount;
8592
countElements.offCount.textContent = offCount;
86-
countElements.totalCount.textContent = totalCount;
87-
countElements.onPercentage.textContent = calculatePercentage(onCount, totalCount) + '%';
88-
countElements.offPercentage.textContent = calculatePercentage(offCount, totalCount) + '%';
93+
countElements.onPercentage.textContent = `${calculatePercentage(onCount)}%`;
94+
countElements.offPercentage.textContent = `${calculatePercentage(offCount)}%`;
8995
}
9096

91-
function calculatePercentage(part, total) {
92-
return ((part / total) * 100).toFixed(2);
97+
function calculatePercentage(part) {
98+
return ((part / totalCount) * 100).toFixed(2);
9399
}
94100

95-
async function saveOptions() {
96-
try {
97-
const options = gatherOptions();
98-
await chrome.storage.sync.set(options);
99-
await restoreOptions();
100-
updateToggleCounts();
101-
openSpotifyTab();
102-
} catch (error) {
103-
console.error('Error saving options:', error);
104-
}
101+
function saveOptions() {
102+
const options = gatherOptions();
103+
chrome.storage.sync.set(options, () => {
104+
if (chrome.runtime.lastError) {
105+
console.error('Error saving options:', chrome.runtime.lastError);
106+
} else {
107+
updateToggleCounts();
108+
openSpotifyTab();
109+
}
110+
});
105111
}
106112

107113
function gatherOptions() {
108-
return Object.keys(defaultOptions).reduce((acc, id) => {
109-
acc[id] = checkboxElements[id].checked;
110-
return acc;
114+
return defaultOptionsKeys.reduce((options, id) => {
115+
options[id] = checkboxElements[id].checked;
116+
return options;
111117
}, {});
112118
}
113119

114-
async function restoreOptions() {
115-
try {
116-
const items = await chrome.storage.sync.get(defaultOptions);
117-
for (const [id, value] of Object.entries(items)) {
118-
const checkbox = checkboxElements[id] || document.getElementById(id);
119-
if (checkbox) {
120-
checkboxElements[id] = checkbox;
121-
checkbox.checked = value;
122-
}
120+
function restoreAndUpdateOptions() {
121+
chrome.storage.sync.get(defaultOptions, (items) => {
122+
if (chrome.runtime.lastError) {
123+
console.error('Error restoring options:', chrome.runtime.lastError);
124+
} else {
125+
defaultOptionsKeys.forEach(id => {
126+
checkboxElements[id].checked = items[id];
127+
});
128+
updateToggleCounts();
123129
}
124-
updateToggleCounts();
125-
} catch (error) {
126-
console.error('Error restoring options:', error);
127-
}
130+
});
128131
}
129132

130133
function openSpotifyTab() {
@@ -137,7 +140,7 @@
137140
});
138141
}
139142

140-
document.addEventListener("DOMContentLoaded", restoreOptions);
143+
document.addEventListener("DOMContentLoaded", restoreAndUpdateOptions);
141144
saveButton.addEventListener("click", saveOptions);
142145
settingsButton.addEventListener("click", openSpotifyTab);
143146
})();

0 commit comments

Comments
 (0)