From 29e37cbf97bbe9c0645c3721a4eee8e156567105 Mon Sep 17 00:00:00 2001
From: imdj <69906094+imdj@users.noreply.github.com>
Date: Thu, 1 Jun 2023 16:33:58 +0300
Subject: [PATCH] Add preferences support
---
css/popup.css | 183 +++++++++++++++++++++++++++++++++++++++++++++++
manifest.v2.json | 12 +++-
manifest.v3.json | 14 +++-
popup.html | 56 +++++++++++++++
scripts/dom.js | 4 +-
scripts/main.js | 31 +++++---
scripts/popup.js | 55 ++++++++++++++
7 files changed, 342 insertions(+), 13 deletions(-)
create mode 100644 css/popup.css
create mode 100644 popup.html
create mode 100644 scripts/popup.js
diff --git a/css/popup.css b/css/popup.css
new file mode 100644
index 0000000..aff4b30
--- /dev/null
+++ b/css/popup.css
@@ -0,0 +1,183 @@
+html, body {
+ font-family: system-ui, sans-serif;
+}
+
+html {
+ max-height: 600px;
+ overflow-y: auto;
+}
+body {
+ width: 350px;
+ max-width: 100%;
+}
+
+.relative {
+ position: relative;
+}
+
+.flex {
+ display: flex;
+}
+
+.h-full {
+ height: 100%;
+}
+
+.w-full {
+ width: 100%;
+}
+
+.flex-col {
+ flex-direction: column;
+}
+
+.flex-row {
+ flex-direction: row;
+}
+
+.justify-center {
+ justify-content: center;
+}
+
+.justify-between {
+ justify-content: space-between;
+}
+
+.items-baseline {
+ align-items: baseline;
+}
+
+.items-center {
+ align-items: center;
+}
+
+[class~="top-0.5"] {
+ top: 0.125rem;
+}
+
+.ml-2 {
+ margin-left: 0.5rem;
+}
+
+.ml-4 {
+ margin-left: 1rem;
+}
+
+.ml-8 {
+ margin-left: 2rem;
+}
+
+.mt-2 {
+ margin-top: 0.5rem;
+}
+
+.mt-3 {
+ margin-top: 0.75rem;
+}
+
+.mt-8 {
+ margin-top: 2rem;
+}
+
+.mb-auto {
+ margin-bottom: auto;
+}
+
+.mb-0 {
+ margin-bottom: 0;
+}
+
+.mb-2 {
+ margin-bottom: 0.5rem;
+}
+
+.mb-4 {
+ margin-bottom: 1rem;
+}
+
+.my-2 {
+ margin: 0.5rem 0;
+}
+
+.my-4 {
+ margin: 1rem 0;
+}
+
+.my-8 {
+ margin: 2rem 0;
+}
+
+.mt-auto {
+ margin-top: auto;
+}
+
+[class~="p-0.5"] {
+ padding: 0.125rem;
+}
+
+p {
+ margin: unset;
+ color: rgba(0, 0, 0, .6);
+}
+
+.btn {
+ display: flex;
+ align-items: center;
+ flex-direction: row;
+ padding: 0.25rem 0.5rem;
+ border-radius: 0.5rem;
+ border: 3px solid #E3E3E3;
+ cursor: pointer;
+ font-size: smaller;
+ color: #000;
+ background: #fff;
+ transition: 0.5s;
+ margin: 0 0.5rem;
+}
+
+a.btn {
+ text-decoration: none;
+}
+
+.btn:hover,
+.btn:focus {
+ background: #E3E3E3;
+}
+
+.btn svg {
+ margin-left: 10px;
+}
+
+input[type="checkbox"] {
+ position: relative;
+ width: 40px;
+ height: 20px;
+ -webkit-appearance: none;
+ appearance: none;
+ background: red;
+ outline: none;
+ border-radius: 2rem;
+ cursor: pointer;
+ box-shadow: inset 0 0 5px rgb(0 0 0 / 50%);
+}
+
+input[type="checkbox"]::before {
+ content: "";
+ width: 18px;
+ height: 18px;
+ border-radius: 50%;
+ background: #fff;
+ position: absolute;
+ top: 1px;
+ left: 1px;
+ transition: 0.5s;
+}
+
+input[type="checkbox"]:checked::before {
+ transform: translateX(100%);
+ background: #fff;
+}
+
+input[type="checkbox"]:checked {
+ background: #00ed64;
+}
\ No newline at end of file
diff --git a/manifest.v2.json b/manifest.v2.json
index cd11ae0..021f71c 100644
--- a/manifest.v2.json
+++ b/manifest.v2.json
@@ -9,6 +9,7 @@
"128": "/assets/images/icon-128.png"
},
"permissions": [
+ "storage",
"https://hn.algolia.com/api/*"
],
"applications": {
@@ -28,5 +29,14 @@
"./scripts/main.js"
]
}
- ]
+ ],
+ "browser_action": {
+ "default_icon": {
+ "16": "/assets/images/icon-16.png",
+ "48": "/assets/images/icon-48.png",
+ "128": "/assets/images/icon-128.png"
+ },
+ "default_popup": "./popup.html",
+ "default_title": "HNRelevant"
+ }
}
diff --git a/manifest.v3.json b/manifest.v3.json
index de8b136..729017f 100644
--- a/manifest.v3.json
+++ b/manifest.v3.json
@@ -22,5 +22,17 @@
"./scripts/main.js"
]
}
- ]
+ ],
+ "permissions": [
+ "storage"
+ ],
+ "action": {
+ "default_icon": {
+ "16": "/assets/images/icon-16.png",
+ "48": "/assets/images/icon-48.png",
+ "128": "/assets/images/icon-128.png"
+ },
+ "default_popup": "./popup.html",
+ "default_title": "HNRelevant"
+ }
}
\ No newline at end of file
diff --git a/popup.html b/popup.html
new file mode 100644
index 0000000..23e3b13
--- /dev/null
+++ b/popup.html
@@ -0,0 +1,56 @@
+
+
+
+
+ HNRelevant Popup
+
+
+
+
+
+
+
+
Select mode
+
+
+
+
+
Fetch results automatically on every submission (no interaction required)
+
+
+
+
+
+
+
Fetch results only when requested by user manually
+
+
+
+
+
Results
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/scripts/dom.js b/scripts/dom.js
index 5a0a948..c71a6df 100644
--- a/scripts/dom.js
+++ b/scripts/dom.js
@@ -46,7 +46,7 @@ queryCustomizationInput.placeholder = 'Customize: ' + HN_SubmissionTitle;
queryCustomizationInput.value = HN_SubmissionTitle;
// Allow user to submit query by pressing enter
-queryCustomizationInput.addEventListener('keydown', function(event) {
+queryCustomizationInput.addEventListener('keydown', function (event) {
if (event.code === 'Enter' && queryCustomizationInput === document.activeElement) {
submitCustomizationButton.click();
}
@@ -62,7 +62,7 @@ const numOfResultsDropdown = document.createElement('select');
numOfResultsDropdown.style.marginLeft = '5px';
numOfResultsDropdown.id = 'numOfResultsDropdown';
['5', '10', '15', '20', '30'].forEach(num => {
- numOfResultsDropdown.add(new Option(num));
+ numOfResultsDropdown.add(new Option(num, num));
});
sidebarOptionsContainer.appendChild(numberOfResultsLabel);
diff --git a/scripts/main.js b/scripts/main.js
index ad6918c..44b1851 100644
--- a/scripts/main.js
+++ b/scripts/main.js
@@ -14,14 +14,27 @@ sidebar.appendChild(sidebarOptionsContainer);
sidebar.appendChild(sidebarResults);
HN_Content.appendChild(sidebar);
-// Make sure to run this after the page has loaded
-if(document.readyState !== 'complete') {
- window.addEventListener('load',updateSidebarResults);
-} else {
- updateSidebarResults();
-}
+(async () => {
+ // Get preferences from storage
+ // Mode: manual or automatic
+ const mode = await (chrome.storage.sync ? chrome.storage.sync.get('mode') : browser.storage.sync.get('mode'));
+
+ // Number of results: default to 5
+ const numOfResults = await (chrome.storage.sync ? chrome.storage.sync.get('results') : browser.storage.sync.get('results'));
+ numOfResultsDropdown.value = numOfResults ? numOfResults.results : '5';
+
+ // Don't run if mode is set to `manual`
+ if (mode.mode !== 'manual') {
+ // Make sure to run this after the page has loaded
+ if (document.readyState !== 'complete') {
+ window.addEventListener('load', updateSidebarResults);
+ } else {
+ updateSidebarResults();
+ }
+ }
// Run on dropdown change (changing num of results: 5, 10, 15, 20, 30)
-numOfResultsDropdown.addEventListener('change', () =>
- updateSidebarResults()
-);
\ No newline at end of file
+ numOfResultsDropdown.addEventListener('change', () =>
+ updateSidebarResults()
+ );
+})();
\ No newline at end of file
diff --git a/scripts/popup.js b/scripts/popup.js
new file mode 100644
index 0000000..1c8a8af
--- /dev/null
+++ b/scripts/popup.js
@@ -0,0 +1,55 @@
+const isChrome = chrome.storage.sync ? true : false;
+
+// get references to the input elements
+const modeRadioButtons = document.getElementsByName("mode");
+const resultsDropdown = document.getElementsByName("results")[0];
+
+if (isChrome) { // load saved settings from storage in Chrome
+ chrome.storage.sync.get(["mode", "results"], function (settings) {
+ // set the input elements to the saved values
+ if (settings.mode) {
+ for (const radioButton of modeRadioButtons) {
+ if (radioButton.value === settings.mode) {
+ radioButton.checked = true;
+ break;
+ }
+ }
+ }
+ if (settings.results) {
+ resultsDropdown.value = settings.results;
+ }
+ });
+} else { // load saved settings from storage in Firefox
+ browser.storage.sync.get(["mode", "results"], function (settings) {
+ // set the input elements to the saved values
+ if (settings.mode) {
+ for (const radioButton of modeRadioButtons) {
+ if (radioButton.value === settings.mode) {
+ radioButton.checked = true;
+ break;
+ }
+ }
+ }
+ if (settings.results) {
+ resultsDropdown.value = settings.results;
+ }
+ });
+}
+
+// add event listeners to the input elements
+for (const radioButton of modeRadioButtons) {
+ radioButton.addEventListener("change", function () {
+ if (isChrome) { // save the selected mode to storage in Chrome
+ chrome.storage.sync.set({mode: this.value});
+ } else { // save the selected mode to storage in Firefox
+ browser.storage.sync.set({mode: this.value});
+ }
+ });
+}
+resultsDropdown.addEventListener("change", function () {
+ if (isChrome) { // save the selected results to storage in Chrome
+ chrome.storage.sync.set({results: this.value});
+ } else { // save the selected results to storage in Firefox
+ browser.storage.sync.set({results: this.value});
+ }
+});
\ No newline at end of file