card opacity + padding

This commit is contained in:
Guy Sandler 2026-08-25 16:48:15 -07:00
parent 6c1bc9dc98
commit 1a484e726b
6 changed files with 157 additions and 53678 deletions

View File

@ -60,13 +60,16 @@
"message": "Quiz Safe Mode" "message": "Quiz Safe Mode"
}, },
"quiz_safe_mode_desc": { "quiz_safe_mode_desc": {
"message": "Turns off most Canvas Refined features on quiz pages so you get the default Canvas quiz experience." "message": "Turns off most Canvas Refined features on quiz pages so you get the default Canvas quiz experience"
}, },
"opacity_options": { "opacity_options": {
"message": "Opacity & Blur" "message": "Opacity & Blur"
}, },
"opacity_only_background": { "opacity_only_background": {
"message": "Only available with a custom background. Lower opacity to let the background show through; add blur for a glass effect." "message": "Only available with a custom background"
},
"card_transparency": {
"message": "Card transparency"
}, },
"background_opacity": { "background_opacity": {
"message": "Background opacity" "message": "Background opacity"
@ -80,6 +83,12 @@
"sidebar_blur": { "sidebar_blur": {
"message": "Sidebar blur" "message": "Sidebar blur"
}, },
"card_opacity": {
"message": "Card opacity"
},
"card_blur": {
"message": "Card blur"
},
"sidebar_opacity_auto": { "sidebar_opacity_auto": {
"message": "Applies to the Better Sidebar when it's on, otherwise the normal sidebar." "message": "Applies to the Better Sidebar when it's on, otherwise the normal sidebar."
}, },

View File

@ -21,8 +21,8 @@ h2 {font-size:24px;}
.header {font-size: 16px;display: flex;align-items: center;gap:12px; margin-bottom:14px;} .header {font-size: 16px;display: flex;align-items: center;gap:12px; margin-bottom:14px;}
.header h1 { font-weight: 600; font-size:24px; } .header h1 { font-weight: 600; font-size:24px; }
#bclogo {height: 30px;width:30px;filter: none} #bclogo {height: 30px;width:30px;filter: none}
#numAssignmentsSlider, #numTodoItemsSlider, #sidebarScaleSlider, #customBackgroundScale, #bgOpacitySlider, #sidebarOpacitySlider, #bgBlurSlider, #sidebarBlurSlider {display: block;margin-top: 14px;width: 100%;-webkit-appearance: none; appearance: none;background:var(--inputbg);outline: none;height:6px;border-radius:20px;} #numAssignmentsSlider, #numTodoItemsSlider, #sidebarScaleSlider, #customBackgroundScale, #bgOpacitySlider, #sidebarOpacitySlider, #bgBlurSlider, #sidebarBlurSlider, #cardOpacitySlider, #cardBlurSlider {display: block;margin-top: 14px;width: 100%;-webkit-appearance: none; appearance: none;background:var(--inputbg);outline: none;height:6px;border-radius:20px;}
#numAssignmentsSlider::-webkit-slider-thumb, #numTodoItemsSlider::-webkit-slider-thumb, #sidebarScaleSlider::-webkit-slider-thumb, #customBackgroundScale::-webkit-slider-thumb, #bgOpacitySlider::-webkit-slider-thumb, #sidebarOpacitySlider::-webkit-slider-thumb, #bgBlurSlider::-webkit-slider-thumb, #sidebarBlurSlider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none;height: 18px; width: 18px;background: #727272;cursor: pointer;border-radius:30px;} #numAssignmentsSlider::-webkit-slider-thumb, #numTodoItemsSlider::-webkit-slider-thumb, #sidebarScaleSlider::-webkit-slider-thumb, #customBackgroundScale::-webkit-slider-thumb, #bgOpacitySlider::-webkit-slider-thumb, #sidebarOpacitySlider::-webkit-slider-thumb, #bgBlurSlider::-webkit-slider-thumb, #sidebarBlurSlider::-webkit-slider-thumb, #cardOpacitySlider::-webkit-slider-thumb, #cardBlurSlider::-webkit-slider-thumb {-webkit-appearance: none; appearance: none;height: 18px; width: 18px;background: #727272;cursor: pointer;border-radius:30px;}
.option-container {font-size: 14px; margin-top: 8px;background: var(--containerbg);padding: 18px;border-radius: 14px;box-sizing:border-box} .option-container {font-size: 14px; margin-top: 8px;background: var(--containerbg);padding: 18px;border-radius: 14px;box-sizing:border-box}
.options .option-container {padding: 14px;} .options .option-container {padding: 14px;}
a.option-container {display: block;color:#5ca5f6;font-size: 14px;} a.option-container {display: block;color:#5ca5f6;font-size: 14px;}

View File

@ -592,7 +592,7 @@
</div> </div>
<div class="sub-option"> <div class="sub-option">
<input type="checkbox" id="export-background" /> <input type="checkbox" id="export-background" />
<span>Background image</span> <span>Background &amp; opacity</span>
</div> </div>
</div> </div>
<div style="flex: 1"> <div style="flex: 1">
@ -851,6 +851,13 @@
<span class="sub-text">px</span> <span class="sub-text">px</span>
</div> </div>
</div> </div>
<div class="sub-option">
<div style="margin-top: 5px;display: flex;gap: 8px;align-items: center">
<span class="sub-text" style="width:75px;">Card Padding</span>
<input type="number" id="cardPadding" class="card-input" min="0" max="100" value="0" style="width: 80px;">
<span class="sub-text">px</span>
</div>
</div>
</div> </div>
</div> </div>
@ -1051,6 +1058,10 @@
<input type="checkbox" id="fitImageToScreen" name="fitImageToScreen"> <input type="checkbox" id="fitImageToScreen" name="fitImageToScreen">
<label for="fitImageToScreen" class="sub-text">Fit image to screen</label> <label for="fitImageToScreen" class="sub-text">Fit image to screen</label>
</div> </div>
<div class="sub-option" style="margin-top:8px;">
<input type="checkbox" id="card_transparency" name="card_transparency">
<label for="card_transparency" class="sub-text" data-i18n="card_transparency">Card transparency</label>
</div>
</div> </div>
<div class="option-container" id="opacity-options" style="display:none;"> <div class="option-container" id="opacity-options" style="display:none;">
<h3 class="header-small" data-i18n="opacity_options">Opacity &amp; Blur</h3> <h3 class="header-small" data-i18n="opacity_options">Opacity &amp; Blur</h3>
@ -1095,6 +1106,26 @@
</div> </div>
<input type="range" min="0" max="30" step="1" id="sidebarBlurSlider"> <input type="range" min="0" max="30" step="1" id="sidebarBlurSlider">
</div> </div>
<div class="opacity-slider-row" id="card-transparency-options" style="display:none;">
<div style="display:flex;justify-content:space-between;gap:10px;align-items:center;margin-top:10px;">
<span class="sub-text" style="font-weight:600;color:#e2e2e2;" data-i18n="card_opacity">Card opacity</span>
<div style="display:flex;align-items:center;gap:6px;">
<button class="opacity-reset-btn" id="cardOpacityReset" type="button" title="Reset to default" data-i18n-title="reset_default"><svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg></button>
<span class="sub-text" id="cardOpacityValue">80%</span>
</div>
</div>
<input type="range" min="0" max="100" step="1" id="cardOpacitySlider">
</div>
<div class="opacity-slider-row" id="card-transparency-blur-row" style="display:none;">
<div style="display:flex;justify-content:space-between;gap:10px;align-items:center;margin-top:10px;">
<span class="sub-text" style="font-weight:600;color:#e2e2e2;" data-i18n="card_blur">Card blur</span>
<div style="display:flex;align-items:center;gap:6px;">
<button class="opacity-reset-btn" id="cardBlurReset" type="button" title="Reset to default" data-i18n-title="reset_default"><svg viewBox="0 0 24 24" width="11" height="11" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg></button>
<span class="sub-text" id="cardBlurValue">8px</span>
</div>
</div>
<input type="range" min="0" max="30" step="1" id="cardBlurSlider">
</div>
</div> </div>
</div> </div>

View File

@ -758,8 +758,14 @@ function applyOptionsChanges(changes) {
case "cardSpacing": case "cardSpacing":
case "cardWidth": case "cardWidth":
case "cardHeight": case "cardHeight":
case "cardPadding":
case "customCardStyles": case "customCardStyles":
applyAestheticChanges(); // Coalesce rapid card-style edits (e.g. holding the arrow keys on a
// number input) into a single applyAestheticChanges() call. Each
// storage onChanged event would otherwise re-run the dashboard style
// pass immediately; a ~150ms cooldown is barely noticeable but keeps
// the page from thrashing while the user is still adjusting values.
debouncedApplyAestheticChanges();
break; break;
case "customBackgroundLink": case "customBackgroundLink":
applyCustomBackground(); applyCustomBackground();
@ -774,6 +780,11 @@ function applyOptionsChanges(changes) {
break; break;
case "sidebar_opacity": case "sidebar_opacity":
case "sidebar_blur": case "sidebar_blur":
applyCustomBackground();
break;
case "card_transparency":
case "card_opacity":
case "card_blur":
applyCustomBackground(); applyCustomBackground();
break; break;
case "better_todo": case "better_todo":
@ -899,6 +910,14 @@ async function applyCustomBackground() {
// the previous dashboard-header glass look; sidebar defaults to none. // the previous dashboard-header glass look; sidebar defaults to none.
const bgBlur = Math.max(0, Math.min(30, Number(options.bg_blur ?? 8))); const bgBlur = Math.max(0, Math.min(30, Number(options.bg_blur ?? 8)));
const sidebarBlur = Math.max(0, Math.min(30, Number(options.sidebar_blur ?? 0))); const sidebarBlur = Math.max(0, Math.min(30, Number(options.sidebar_blur ?? 0)));
// Card transparency mirrors the content-panel glass effect (bg_opacity/
// bg_blur) but applies it to dashboard course cards (.ic-DashboardCard).
// Only active when the user explicitly enables it, since transparent cards
// over a busy background can hurt legibility.
const cardTransparency = options.card_transparency === true;
const cardOpacity = Math.max(0, Math.min(100, Number(options.card_opacity ?? 80)));
const cardBlur = Math.max(0, Math.min(30, Number(options.card_blur ?? 8)));
const cardTransparent = 100 - cardOpacity;
style.textContent = ` style.textContent = `
#wrapper { #wrapper {
background-image: url(${backgroundUrl}) !important; background-image: url(${backgroundUrl}) !important;
@ -1147,7 +1166,11 @@ async function applyCustomBackground() {
.canvasrefined-gpa-card, .canvasrefined-gpa-card,
.canvasrefined-gpa, .canvasrefined-gpa,
.ic-DashboardCard { .ic-DashboardCard {
background: var(--bcbackground-0) !important; ${cardTransparency
? `background: color-mix(in srgb, var(--bcbackground-0), transparent ${cardTransparent}%) !important;
backdrop-filter: blur(${cardBlur}px) saturate(120%) !important;
-webkit-backdrop-filter: blur(${cardBlur}px) saturate(120%) !important;`
: `background: var(--bcbackground-0) !important;`}
} }
tr.student_assignment.assignment_graded.editable > * { tr.student_assignment.assignment_graded.editable > * {
border:none!important border:none!important
@ -5205,6 +5228,18 @@ function loadCustomFont() {
Smaller features Smaller features
*/ */
// Debounced wrapper around applyAestheticChanges for card-style options that
// can fire many storage onChanged events in quick succession (number inputs).
// See the "cardPadding"/"imageSize"/etc. cases in applyOptionsChanges.
let aestheticDebounceTimer = null;
function debouncedApplyAestheticChanges(delay = 150) {
if (aestheticDebounceTimer) clearTimeout(aestheticDebounceTimer);
aestheticDebounceTimer = setTimeout(() => {
aestheticDebounceTimer = null;
applyAestheticChanges();
}, delay);
}
function applyAestheticChanges() { function applyAestheticChanges() {
// Quiz safe mode: don't inject custom layout/aesthetic CSS on quiz pages. // Quiz safe mode: don't inject custom layout/aesthetic CSS on quiz pages.
if (quizSafeModeActive()) return; if (quizSafeModeActive()) return;
@ -5239,6 +5274,13 @@ function applyAestheticChanges() {
// visible and interactive when card assignments are shown. // visible and interactive when card assignments are shown.
if (options.assignments_due === true) style.textContent += `.ic-DashboardCard {overflow: visible!important;}`; if (options.assignments_due === true) style.textContent += `.ic-DashboardCard {overflow: visible!important;}`;
} }
// Inner card padding. Applied to the whole .ic-DashboardCard box (the
// element that holds the hero header, title, and action buttons) so the
// colored hero header and its content all get consistent breathing room
// from the card's edges. Guarded by !== 0 (default).
if (options.cardPadding !== undefined && Number(options.cardPadding) > 0) {
style.textContent += `.ic-DashboardCard {padding: ${options.cardPadding}px!important;}`;
}
} }
style.textContent += ".ic-app-nav-toggle-and-crumbs{display:none!important}"; style.textContent += ".ic-app-nav-toggle-and-crumbs{display:none!important}";

View File

@ -31,6 +31,7 @@ const syncedSubOptions = [
"cardSpacing", "cardSpacing",
"cardWidth", "cardWidth",
"cardHeight", "cardHeight",
"cardPadding",
"customBackgroundLink", "customBackgroundLink",
"customBackgroundScale", "customBackgroundScale",
"customBackgroundDaily", "customBackgroundDaily",
@ -41,18 +42,20 @@ const syncedSubOptions = [
"sidebar_opacity", "sidebar_opacity",
"bg_blur", "bg_blur",
"sidebar_blur", "sidebar_blur",
"card_opacity",
"card_blur",
]; ];
const localSwitches = []; const localSwitches = [];
// Theme export only carries visual settings, never personal productivity data. // Theme export only carries visual settings, never personal productivity data.
const exportDarkSchedule = ["auto_dark", "auto_dark_start", "auto_dark_end", "device_dark"]; const exportDarkSchedule = ["auto_dark", "auto_dark_start", "auto_dark_end", "device_dark"];
const exportCardColorToggles = ["gradient_cards", "disable_color_overlay"]; const exportCardColorToggles = ["gradient_cards", "disable_color_overlay"];
const exportCardStyles = ["customCardStyles", "imageSize", "cardRoundness", "cardSpacing", "cardWidth", "cardHeight"]; const exportCardStyles = ["customCardStyles", "imageSize", "cardRoundness", "cardSpacing", "cardWidth", "cardHeight", "cardPadding"];
const exportLayout = ["full_width", "center_cards", "condensed_cards", "equal_height_cards", "remlogo", "hide_new_canvas", "hide_feedback", "tab_icons"]; const exportLayout = ["full_width", "center_cards", "condensed_cards", "equal_height_cards", "remlogo", "hide_new_canvas", "hide_feedback", "tab_icons"];
const exportSidebar = ["better_sidebar", "sidebar_scale"]; const exportSidebar = ["better_sidebar", "sidebar_scale"];
const exportTodo = ["better_todo", "todo_hide_feedback", "todo_full_height", "todo_confetti", "todo_progress_rings", "todo_timeframe", "todo_hr24", "todo_separate_scrollbar", "todo_alternate_colors", "hover_preview"]; const exportTodo = ["better_todo", "todo_hide_feedback", "todo_full_height", "todo_confetti", "todo_progress_rings", "todo_timeframe", "todo_hr24", "todo_separate_scrollbar", "todo_alternate_colors", "hover_preview"];
const exportGpa = ["gpa_calc", "gpa_calc_prepend", "gpa_calc_cumulative", "gpa_calc_weighted"]; const exportGpa = ["gpa_calc", "gpa_calc_prepend", "gpa_calc_cumulative", "gpa_calc_weighted"];
const exportBackground = ["customBackgroundLink", "customBackgroundScale", "customBackgroundDaily", "customBackgroundNasaDaily", "fitImageToScreen", "bg_opacity", "sidebar_opacity", "bg_blur", "sidebar_blur"]; const exportBackground = ["customBackgroundLink", "customBackgroundScale", "customBackgroundDaily", "customBackgroundNasaDaily", "fitImageToScreen", "card_transparency", "bg_opacity", "sidebar_opacity", "bg_blur", "sidebar_blur", "card_opacity", "card_blur"];
// Master "On/off toggles" = every visual toggle (no GPA, no dark-mode schedule, // Master "On/off toggles" = every visual toggle (no GPA, no dark-mode schedule,
// no personal productivity features). // no personal productivity features).
const exportToggles = ["dark_mode", "quiz_safe_mode"].concat(exportCardColorToggles, exportLayout, exportSidebar, exportTodo); const exportToggles = ["dark_mode", "quiz_safe_mode"].concat(exportCardColorToggles, exportLayout, exportSidebar, exportTodo);
@ -103,6 +106,9 @@ const defaultOptions = {
"sidebar_opacity": 100, "sidebar_opacity": 100,
"bg_blur": 8, "bg_blur": 8,
"sidebar_blur": 0, "sidebar_blur": 0,
"card_transparency": false,
"card_opacity": 80,
"card_blur": 8,
"todo_hr24": false, "todo_hr24": false,
"todo_separate_scrollbar": false, "todo_separate_scrollbar": false,
"todo_alternate_colors": false, "todo_alternate_colors": false,
@ -161,6 +167,7 @@ const defaultOptions = {
"cardSpacing": 0, "cardSpacing": 0,
"cardWidth": 262, "cardWidth": 262,
"cardHeight": 250, "cardHeight": 250,
"cardPadding": 0,
"customCardStyles": false, "customCardStyles": false,
"customBackgroundLink": "", "customBackgroundLink": "",
"customBackgroundScale": 100, "customBackgroundScale": 100,
@ -354,11 +361,26 @@ function setupDashboardMethod(initial) {
}); });
} }
// Custom card style inputs (image size, roundness, spacing, width, height,
// padding) fire `chrome.storage.sync.set` on every keystroke/arrow press.
// chrome.storage.sync caps writes at MAX_WRITE_OPERATIONS_PER_MINUTE (120/min),
// so rapidly adjusting these number inputs used to hit the quota and surface
// a "quota exceeded" error. Coalesce rapid edits into a single write with a
// short (200ms) debounce — barely noticeable to the user, but stays well
// under the write quota even when dragging arrows or typing fast.
const cardStyleSetTimers = {};
function debouncedCardStyleSet(key, value, delay = 200) {
if (cardStyleSetTimers[key]) clearTimeout(cardStyleSetTimers[key]);
cardStyleSetTimers[key] = setTimeout(() => {
chrome.storage.sync.set({ [key]: value });
}, delay);
}
function setupImageSizeInput(initial) { function setupImageSizeInput(initial) {
let el = document.querySelector("#imageSize"); let el = document.querySelector("#imageSize");
el.value = initial; el.value = initial;
el.addEventListener("input", (e) => { el.addEventListener("input", (e) => {
chrome.storage.sync.set({ "imageSize": e.target.value }); debouncedCardStyleSet("imageSize", e.target.value);
}); });
} }
@ -366,7 +388,7 @@ function setupCardRoundnessInput(initial) {
let el = document.querySelector("#cardRoundness"); let el = document.querySelector("#cardRoundness");
el.value = initial; el.value = initial;
el.addEventListener("input", (e) => { el.addEventListener("input", (e) => {
chrome.storage.sync.set({ "cardRoundness": e.target.value }); debouncedCardStyleSet("cardRoundness", e.target.value);
}); });
} }
@ -374,7 +396,7 @@ function setupCardSpacingInput(initial) {
let el = document.querySelector("#cardSpacing"); let el = document.querySelector("#cardSpacing");
el.value = initial; el.value = initial;
el.addEventListener("input", (e) => { el.addEventListener("input", (e) => {
chrome.storage.sync.set({ "cardSpacing": e.target.value }); debouncedCardStyleSet("cardSpacing", e.target.value);
}); });
} }
@ -382,7 +404,7 @@ function setupCardWidthInput(initial) {
let el = document.querySelector("#cardWidth"); let el = document.querySelector("#cardWidth");
el.value = initial; el.value = initial;
el.addEventListener("input", (e) => { el.addEventListener("input", (e) => {
chrome.storage.sync.set({ "cardWidth": e.target.value }); debouncedCardStyleSet("cardWidth", e.target.value);
}); });
} }
@ -390,7 +412,15 @@ function setupCardHeightInput(initial) {
let el = document.querySelector("#cardHeight"); let el = document.querySelector("#cardHeight");
el.value = initial; el.value = initial;
el.addEventListener("input", (e) => { el.addEventListener("input", (e) => {
chrome.storage.sync.set({ "cardHeight": e.target.value }); debouncedCardStyleSet("cardHeight", e.target.value);
});
}
function setupCardPaddingInput(initial) {
let el = document.querySelector("#cardPadding");
el.value = initial;
el.addEventListener("input", (e) => {
debouncedCardStyleSet("cardPadding", e.target.value);
}); });
} }
@ -514,6 +544,17 @@ function customBackgroundActive() {
function toggleOpacityOptions() { function toggleOpacityOptions() {
const el = document.getElementById("opacity-options"); const el = document.getElementById("opacity-options");
if (el) el.style.display = customBackgroundActive() ? "" : "none"; if (el) el.style.display = customBackgroundActive() ? "" : "none";
toggleCardTransparencyOptions();
}
// Card opacity/blur sliders only show when both a custom background is active
// (so #opacity-options is visible) and the "Card transparency" checkbox is on.
function toggleCardTransparencyOptions() {
const on = document.getElementById("card_transparency")?.checked === true;
const opacityRow = document.getElementById("card-transparency-options");
const blurRow = document.getElementById("card-transparency-blur-row");
if (opacityRow) opacityRow.style.display = on ? "" : "none";
if (blurRow) blurRow.style.display = on ? "" : "none";
} }
// Hide the standalone feedback toggle when Better Todo's own sub-option replaces it. // Hide the standalone feedback toggle when Better Todo's own sub-option replaces it.
@ -865,6 +906,7 @@ function setup() {
"customBackgroundDaily", "customBackgroundDaily",
"customBackgroundNasaDaily", "customBackgroundNasaDaily",
"fitImageToScreen", "fitImageToScreen",
"card_transparency",
"customCardStyles", "customCardStyles",
], ],
tabs: { tabs: {
@ -933,6 +975,14 @@ function setup() {
{ {
identifier: "sidebar_blur", identifier: "sidebar_blur",
setup: (initial) => setupRangeSlider("sidebar_blur", "sidebarBlurSlider", "sidebarBlurValue", "sidebarBlurReset", 0, 30, "px", initial), setup: (initial) => setupRangeSlider("sidebar_blur", "sidebarBlurSlider", "sidebarBlurValue", "sidebarBlurReset", 0, 30, "px", initial),
},
{
identifier: "card_opacity",
setup: (initial) => setupRangeSlider("card_opacity", "cardOpacitySlider", "cardOpacityValue", "cardOpacityReset", 80, 100, "%", initial),
},
{
identifier: "card_blur",
setup: (initial) => setupRangeSlider("card_blur", "cardBlurSlider", "cardBlurValue", "cardBlurReset", 8, 30, "px", initial),
}, },
{ {
identifier: "card_limit", identifier: "card_limit",
@ -966,6 +1016,10 @@ function setup() {
identifier: "cardHeight", identifier: "cardHeight",
setup: (initial) => setupCardHeightInput(initial), setup: (initial) => setupCardHeightInput(initial),
}, },
{
identifier: "cardPadding",
setup: (initial) => setupCardPaddingInput(initial),
},
{ {
identifier: "customBackgroundLink", identifier: "customBackgroundLink",
setup: (initial) => setupCustomBackgroundLink(initial), setup: (initial) => setupCustomBackgroundLink(initial),
@ -1446,31 +1500,12 @@ function setup() {
}); });
}); });
document.getElementById("imageSize").addEventListener("input", (e) => { // Note: the card-style number inputs (imageSize, cardRoundness, cardSpacing,
const value = e.target.value; // cardWidth, cardHeight, cardPadding) are wired via their setup*Input
chrome.storage.sync.set({ "imageSize": value }); // handlers in menu.special above, which debounce the storage writes. The
document.querySelector("#imageSizeValue").textContent = value + "%"; // duplicate listeners that used to live here referenced nonexistent
}) // #*Value spans (threw on every input) and double-wrote to storage, which
document.getElementById("cardRoundness").addEventListener("input", (e) => { // is what blew the sync write quota when adjusting card styles quickly.
const value = e.target.value;
chrome.storage.sync.set({ "cardRoundness": value });
document.querySelector("#cardRoundnessValue").textContent = value + "px";
})
document.getElementById("cardSpacing").addEventListener("input", (e) => {
const value = e.target.value;
chrome.storage.sync.set({ "cardSpacing": value });
document.querySelector("#cardSpacingValue").textContent = value + "px";
})
document.getElementById("cardWidth").addEventListener("input", (e) => {
const value = e.target.value;
chrome.storage.sync.set({ "cardWidth": value });
document.querySelector("#cardWidthValue").textContent = value + "%";
});
document.getElementById("cardHeight").addEventListener("input", (e) => {
const value = e.target.value;
chrome.storage.sync.set({ "cardHeight": value });
document.querySelector("#cardHeightValue").textContent = value + "%";
});
document.getElementById("clearCustomBackground").addEventListener("click", () => { document.getElementById("clearCustomBackground").addEventListener("click", () => {
chrome.storage.sync.set({ "customBackgroundLink": "", "customBackgroundScale": 100 }); chrome.storage.sync.set({ "customBackgroundLink": "", "customBackgroundScale": 100 });

File diff suppressed because one or more lines are too long