Compare commits
4 Commits
c0a0c157f5
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
dc31d21104
|
|||
|
00507fe87c
|
|||
|
80689c6f8d
|
|||
|
e4093935b3
|
18
LICENSE
18
LICENSE
@@ -2,20 +2,8 @@ MIT License
|
|||||||
|
|
||||||
Copyright (c) 2026 cottongin (cottongin@cottongin.xyz)
|
Copyright (c) 2026 cottongin (cottongin@cottongin.xyz)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|||||||
13
README.md
13
README.md
@@ -14,6 +14,19 @@ A Firefox extension that reskins [old.reddit.com](https://old.reddit.com) with a
|
|||||||
- **Color customization** — per-subreddit badge colors via an inline HSV picker
|
- **Color customization** — per-subreddit badge colors via an inline HSV picker
|
||||||
- **Theming** — separate light/dark palettes with automatic RES night-mode detection
|
- **Theming** — separate light/dark palettes with automatic RES night-mode detection
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> Extension menu (left), standard old.reddit.com (top right), with extension enabled (bottom right).
|
||||||
|
> RES (Reddit Enhancement Suite) was enabled during capture.
|
||||||
|
|
||||||
|
| View | Full-size image |
|
||||||
|
|---|---|
|
||||||
|
| Extension menu | [reddit-extension-popup.png](docs/reddit-extension-popup.png) |
|
||||||
|
| Without extension | [reddit-extension-disabled.png](docs/reddit-extension-disabled.png) |
|
||||||
|
| With extension | [reddit-extension-enabled.png](docs/reddit-extension-enabled.png) |
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Clone or download this repo
|
1. Clone or download this repo
|
||||||
|
|||||||
42
chat-summaries/2026-08-28_00-27-summary.md
Normal file
42
chat-summaries/2026-08-28_00-27-summary.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Chat Summary — 2026-08-28 00:27
|
||||||
|
|
||||||
|
## Task
|
||||||
|
|
||||||
|
Add project housekeeping files: LICENSE, README, VERSION, .editorconfig, expanded .gitignore. Sync manifest version. Set remote and push.
|
||||||
|
|
||||||
|
## Preceded by
|
||||||
|
|
||||||
|
- Sensitive information audit (no issues found beyond expected `cottongin` in git history)
|
||||||
|
- Plan mode discussion to scope housekeeping items and branding conventions
|
||||||
|
|
||||||
|
## Changes Made
|
||||||
|
|
||||||
|
| File | Action | Details |
|
||||||
|
|------|--------|---------|
|
||||||
|
| `LICENSE` | Created | MIT license, copyright cottongin 2026 |
|
||||||
|
| `README.md` | Created | Terse/casual, Cursor/Claude notice, personal project disclaimer, features, install via about:debugging |
|
||||||
|
| `VERSION` | Created | `0.1.0` |
|
||||||
|
| `.gitignore` | Expanded | Added .DS_Store, *.xpi, web-ext-artifacts/, node_modules/, .env* |
|
||||||
|
| `.editorconfig` | Created | 2-space indent for JS/CSS/JSON/HTML, UTF-8, LF, trim whitespace |
|
||||||
|
| `manifest.json` | Modified | Version synced from 1.0.0 to 0.1.0 |
|
||||||
|
|
||||||
|
## Commit
|
||||||
|
|
||||||
|
`c0a0c15` — `chore: add LICENSE, README, VERSION, .editorconfig, expand .gitignore`
|
||||||
|
|
||||||
|
Also staged 6 previously untracked files (4 chat summaries, 2 score-ratio docs).
|
||||||
|
|
||||||
|
## Remote
|
||||||
|
|
||||||
|
Set origin to `git@code.cottongin.xyz:cottongin/reddit-tweaks-ffe.git` and pushed master.
|
||||||
|
|
||||||
|
## Branding Reference
|
||||||
|
|
||||||
|
- Full: "Reddit Tweaks Firefox Extension"
|
||||||
|
- Abbreviation: "RTFFE"
|
||||||
|
- Short: "Reddit Tweaks FFE"
|
||||||
|
- Casual: "Reddit Tweaks" / "the extension"
|
||||||
|
|
||||||
|
## Follow-up Items
|
||||||
|
|
||||||
|
- None
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# Thermo-Nuclear Code Quality Review — Reddit Tweaks Extension
|
||||||
|
|
||||||
|
**Date:** 2026-08-28 01:08
|
||||||
|
**Task:** Deep code quality audit of the full codebase using thermo-nuclear review criteria
|
||||||
|
|
||||||
|
## Verdict
|
||||||
|
|
||||||
|
Not approved — several structural regressions and missed simplification opportunities identified.
|
||||||
|
|
||||||
|
## Key Findings
|
||||||
|
|
||||||
|
### Critical
|
||||||
|
|
||||||
|
1. **~200 lines of CSS duplicated** between `content/styles/badges.css` (lines 409–611) and `popup/popup.css` (lines 287–489). Color picker widget and preset badge styles are copy-pasted verbatim. Fix: extract shared `color-picker.css`.
|
||||||
|
|
||||||
|
2. **`badges.css` (611 lines) conflates three concerns** — badge styling (~85 lines), color popover chrome (~230 lines), and color picker widget (~150 lines). Should be decomposed into separate files.
|
||||||
|
|
||||||
|
### High
|
||||||
|
|
||||||
|
3. **Preset management logic duplicated** across `popup.js` (`renderPopupPresets`, `addPopupPreset`, `deletePopupPreset`) and `color-popover.js` (`renderPresets`, `saveAsPreset`, `removePreset`). Nearly identical CRUD pattern. Fix: extract shared `presets.js` module.
|
||||||
|
|
||||||
|
4. **`colorToHex` identity function duplicated** in both `popup.js` and `color-popover.js`.
|
||||||
|
|
||||||
|
### Medium
|
||||||
|
|
||||||
|
5. **Dark mode class management scattered** across 4 files with inconsistent scoping — `cards.js` targets `<html>`, `badges.js` targets each container, `color-popover.js` targets itself. Code-judo: apply `rt-dark` once on `<html>` and let CSS cascade handle the rest.
|
||||||
|
|
||||||
|
6. **DOM expando properties** (`entry._colorState`, `entry._nameInput`, etc.) used as state management in `popup.js`. Should use plain objects.
|
||||||
|
|
||||||
|
7. **Stale closure** in `startPostObserver` — line 47 uses captured `settings` instead of freshly-loaded `updated`.
|
||||||
|
|
||||||
|
### Low
|
||||||
|
|
||||||
|
8. **Dead exports** (`isDarkMode`, `getColorPrefix`) on `badgeTweak` object.
|
||||||
|
9. **Verbose storage change listener** — four repetitive conditions should be data-driven.
|
||||||
|
10. **`getHelpers()` wrapper** in `color-popover.js` adds pointless indirection.
|
||||||
|
|
||||||
|
## Recommended Priority Order
|
||||||
|
|
||||||
|
1. Extract shared `color-picker.css` (~200 lines deleted)
|
||||||
|
2. Split `badges.css` into badges, popover, picker
|
||||||
|
3. Extract shared preset module
|
||||||
|
4. Unify dark mode to single `html.rt-dark` class
|
||||||
|
5. Fix stale closure bug
|
||||||
|
6. Clean up dead exports, verbose conditions, and unnecessary wrappers
|
||||||
|
|
||||||
|
## Lessons Learned
|
||||||
|
|
||||||
|
- The thermo-nuclear review skill is useful for catching CSS duplication that would otherwise grow silently — CSS files don't get the same refactoring attention as JS.
|
||||||
|
- Browser extension architecture (content scripts vs popup) makes code sharing harder since there's no module system, but shared files loaded via both manifest.json and popup.html `<script>`/`<link>` tags work fine.
|
||||||
|
- IIFE-scoped modules on a global namespace are a reasonable pattern for small extensions but make duplication easy to miss since there's no import graph to inspect.
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# Thermo-Nuclear Code Quality Refactor — Reddit Tweaks Extension
|
||||||
|
|
||||||
|
**Date:** 2026-08-28 01:23
|
||||||
|
**Task:** Implement all 10 findings from the thermo-nuclear code quality review
|
||||||
|
|
||||||
|
## Changes Made
|
||||||
|
|
||||||
|
### 1. CSS Deduplication — Extracted shared `color-picker.css` (NEW FILE)
|
||||||
|
- Created `content/styles/color-picker.css` (259 lines) containing color picker widget styles and preset badge styles
|
||||||
|
- This file is now shared between the content script (via manifest.json) and the popup (via `<link>` tag)
|
||||||
|
- Eliminated ~200 lines of identical CSS that was previously duplicated between `badges.css` and `popup.css`
|
||||||
|
|
||||||
|
### 2. CSS Decomposition — Extracted `color-popover.css` (NEW FILE)
|
||||||
|
- Created `content/styles/color-popover.css` (256 lines) with popover chrome, buttons, dark mode
|
||||||
|
- Trimmed `badges.css` from 611 lines to 85 lines (badges-only)
|
||||||
|
- Trimmed `popup.css` from 489 lines to 220 lines (popup-specific only)
|
||||||
|
- Updated dark mode selectors from `.rt-color-popover.rt-dark` to `.rt-dark .rt-color-popover` (ancestor form)
|
||||||
|
|
||||||
|
### 3. Shared Preset Module — Extracted `lib/presets.js` (NEW FILE)
|
||||||
|
- Created `lib/presets.js` (57 lines) with `render()`, `save()`, `delete()` functions
|
||||||
|
- Refactored `popup.js` and `color-popover.js` to use shared module
|
||||||
|
- Eliminated ~60 lines of duplicated preset rendering and CRUD logic
|
||||||
|
|
||||||
|
### 4. Dark Mode Unification
|
||||||
|
- Added `applyDarkModeClass(settings)` to `lib/settings.js`
|
||||||
|
- Removed per-container dark class toggling from `badges.js` `applyColorsToContainer()`
|
||||||
|
- Removed `applyDarkMode()` from `cards.js` (was redundant with shared function)
|
||||||
|
- Removed `applyDarkModeToPopover()` and `refreshTheme()` from `color-popover.js`
|
||||||
|
- `main.js` now calls `applyDarkModeClass()` centrally in init, dark-mode observer, and storage listener
|
||||||
|
|
||||||
|
### 5. Stale Closure Fix
|
||||||
|
- Fixed `startPostObserver` in `main.js` to use freshly-loaded `updated` settings instead of stale captured `settings`
|
||||||
|
|
||||||
|
### 6. Data-Driven Storage Listener
|
||||||
|
- Replaced 4 verbose `changes.X && changes.X.newValue !== ...` conditions with `RELOAD_KEYS.some()`
|
||||||
|
|
||||||
|
### 7. Dead Export Cleanup
|
||||||
|
- Removed `isDarkMode` and `getColorPrefix` re-exports from `badgeTweak` object in `badges.js`
|
||||||
|
|
||||||
|
### 8. Deleted `getHelpers()` Wrapper
|
||||||
|
- Removed unnecessary indirection in `color-popover.js`, replaced with direct `window.RedditTweaks.*` calls
|
||||||
|
|
||||||
|
### 9. Inlined `colorToHex`
|
||||||
|
- Removed duplicated `colorToHex` function from both `popup.js` and `color-popover.js`
|
||||||
|
- Replaced all call sites with inline `val || "#ffffff"`
|
||||||
|
|
||||||
|
### 10. DOM Expando Refactor
|
||||||
|
- Replaced `entry._colorState`, `entry._nameInput`, etc. DOM expando pattern in `popup.js`
|
||||||
|
- Introduced `subredditEntries` array of plain state objects
|
||||||
|
- `collectSubredditOverrides()` now iterates the state array instead of querying the DOM
|
||||||
|
|
||||||
|
## Files Changed
|
||||||
|
- `content/main.js` — stale closure fix, data-driven reload keys, central dark mode calls
|
||||||
|
- `content/tweaks/badges.js` — removed dark class toggle, dead exports, refreshTheme call
|
||||||
|
- `content/tweaks/cards.js` — removed applyDarkMode, use shared function
|
||||||
|
- `content/tweaks/color-popover.js` — removed getHelpers, colorToHex, applyDarkModeToPopover, refreshTheme, preset duplication
|
||||||
|
- `lib/settings.js` — added applyDarkModeClass
|
||||||
|
- `popup/popup.js` — inlined colorToHex, used shared presets, state array instead of expandos
|
||||||
|
- `popup/popup.css` — trimmed to popup-only styles
|
||||||
|
- `content/styles/badges.css` — trimmed to badge-only styles (611 → 85 lines)
|
||||||
|
- `manifest.json` — added new CSS and JS files
|
||||||
|
- `popup/popup.html` — added links to new CSS and JS files
|
||||||
|
|
||||||
|
## New Files
|
||||||
|
- `content/styles/color-picker.css` — shared picker + preset badge styles
|
||||||
|
- `content/styles/color-popover.css` — popover chrome styles
|
||||||
|
- `lib/presets.js` — shared preset CRUD module
|
||||||
|
|
||||||
|
## Net Impact
|
||||||
|
- **Before:** 3,180 lines across 12 source files
|
||||||
|
- **After:** 2,862 lines across 15 source files
|
||||||
|
- **Deleted:** ~318 lines of duplication and dead code
|
||||||
|
- No file exceeds 401 lines (previously badges.css was 611)
|
||||||
|
- Dark mode is now managed from a single source instead of 4 scattered functions
|
||||||
|
|
||||||
|
## Lessons Learned
|
||||||
|
- CSS duplication across content script and popup contexts is easy to miss because there's no import graph. Shared CSS files referenced by both manifest.json and popup.html `<link>` work well.
|
||||||
|
- Dark mode class management is a natural candidate for centralization — scattered per-element toggling creates CSS selector complexity that cascading from a single ancestor eliminates.
|
||||||
|
- DOM expando properties work but are an anti-pattern that makes code harder to reason about. A separate state array with DOM references is only marginally more code but significantly clearer.
|
||||||
|
- The `colorToHex` "conversion" function was really just null-coalescing — renaming or inlining it makes the intent obvious.
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# README Screenshots
|
||||||
|
|
||||||
|
## Task
|
||||||
|
|
||||||
|
Add a Screenshots section to the README featuring a composed collage hero image and links to each full-size original screenshot.
|
||||||
|
|
||||||
|
## Changes Made
|
||||||
|
|
||||||
|
### New files
|
||||||
|
- `docs/make_collage.py` -- Python/Pillow script that composes the three source screenshots into an 800x600 collage image (popup left, disabled top-right, enabled bottom-right, light gray background, 4px gaps).
|
||||||
|
- `docs/reddit-extension-collage.png` -- the generated collage output.
|
||||||
|
|
||||||
|
### Modified files
|
||||||
|
- `README.md` -- added a "Screenshots" section between "What it does" and "Installation" containing the collage image, a blockquote caption describing the layout and noting RES was active during capture, and a table linking to each full-size original.
|
||||||
|
|
||||||
|
## Source screenshots
|
||||||
|
- `docs/reddit-extension-popup.png` (645x2757) -- captured by user by opening `moz-extension://<uuid>/popup/popup.html` in a Firefox tab
|
||||||
|
- `docs/reddit-extension-disabled.png` (2794x1671) -- old.reddit.com without extension
|
||||||
|
- `docs/reddit-extension-enabled.png` (2794x1671) -- old.reddit.com with extension
|
||||||
|
|
||||||
|
## Lessons Learned
|
||||||
|
- Firefox extension popups close on focus loss. Opening the popup HTML directly via `moz-extension://` URL in a regular tab is the simplest workaround for full-page captures.
|
||||||
|
- GitHub-flavored markdown cannot crop images, does not honor `rowspan`, and strips most CSS. A pre-composed collage image is the only way to get a multi-panel layout.
|
||||||
|
- Pillow's `Image.LANCZOS` resampling produces clean downscaled screenshots even at significant reduction ratios (e.g., 2794px down to ~546px).
|
||||||
|
|
||||||
|
## Follow-up
|
||||||
|
- The `docs/make_collage.py` script can be re-run if source screenshots are updated.
|
||||||
|
- Consider adding the collage script or output to `.gitignore` if the generated image shouldn't be tracked separately from sources.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# README Screenshots -- Final
|
||||||
|
|
||||||
|
## Task
|
||||||
|
|
||||||
|
Add a Screenshots section to the README with a composed collage hero image and links to full-size originals.
|
||||||
|
|
||||||
|
## Changes Made
|
||||||
|
|
||||||
|
### New files
|
||||||
|
- `docs/reddit-extension-collage.png` -- 1200x900 (4:3) composed collage of all three screenshots.
|
||||||
|
- `docs/make_collage.py` -- Pillow script that generates the collage. Configurable aspect ratio, max dimension, gradient, borders, and drop shadows.
|
||||||
|
- `docs/reddit-extension-popup.png` -- full-page capture of the extension popup (captured manually via `moz-extension://` URL in a tab).
|
||||||
|
- `docs/reddit-extension-disabled.png` -- old.reddit.com without the extension.
|
||||||
|
- `docs/reddit-extension-enabled.png` -- old.reddit.com with the extension active.
|
||||||
|
|
||||||
|
### Modified files
|
||||||
|
- `README.md` -- added Screenshots section between "What it does" and "Installation". Contains the collage hero image, a blockquote caption, and a table linking to each full-size original.
|
||||||
|
|
||||||
|
## Collage Details
|
||||||
|
|
||||||
|
Final collage configuration after iterating through multiple options:
|
||||||
|
- **Layout**: popup on left, disabled screenshot top-right, enabled screenshot bottom-right
|
||||||
|
- **Aspect ratio**: 4:3, clamped to 1200px max dimension (chosen from 5:4, 4:3, 3:2, 16:10, 16:9, 6:5, 7:6 variants)
|
||||||
|
- **Background**: 45-degree linear gradient from `#888888` to `#575757`
|
||||||
|
- **Panel borders**: `#111111`, 1px, 4px corner radius
|
||||||
|
- **Drop shadows**: offset (4,4), blur 8, rgba(0,0,0,0.43), cast bottom-right to complement the gradient angle
|
||||||
|
- **Padding**: 20px outer, 14px gaps between panels (scaled proportionally when clamped)
|
||||||
|
|
||||||
|
## Lessons Learned
|
||||||
|
- Firefox extension popups close on focus loss. Opening `moz-extension://<uuid>/popup/popup.html` in a regular tab is the simplest workaround for full-page captures.
|
||||||
|
- GitHub-flavored markdown cannot crop images, strips `rowspan`, and removes CSS. A pre-composed collage image is the only way to get a multi-panel layout in a README.
|
||||||
|
- Iterating on visual output (colors, ratios, effects) works well as a rapid generate-and-review loop with Pillow.
|
||||||
|
- Generating multiple aspect ratio variants at once and letting the user compare side-by-side is faster than guessing one at a time.
|
||||||
|
|
||||||
|
## Follow-up
|
||||||
|
- Run `python docs/make_collage.py` to regenerate the collage if source screenshots are updated.
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
var observer = new MutationObserver(function () {
|
var observer = new MutationObserver(function () {
|
||||||
window.RedditTweaks.loadSettings().then(function (updated) {
|
window.RedditTweaks.loadSettings().then(function (updated) {
|
||||||
if (updated.darkMode === "auto") {
|
if (updated.darkMode === "auto") {
|
||||||
|
window.RedditTweaks.applyDarkModeClass(updated);
|
||||||
if (updated.badgeLayout) {
|
if (updated.badgeLayout) {
|
||||||
window.RedditTweaks.badgeTweak.updateColors(updated);
|
window.RedditTweaks.badgeTweak.updateColors(updated);
|
||||||
}
|
}
|
||||||
@@ -44,10 +45,10 @@
|
|||||||
}
|
}
|
||||||
if (hasNewPosts) {
|
if (hasNewPosts) {
|
||||||
window.RedditTweaks.loadSettings().then(function (updated) {
|
window.RedditTweaks.loadSettings().then(function (updated) {
|
||||||
if (settings.badgeLayout) {
|
if (updated.badgeLayout) {
|
||||||
window.RedditTweaks.badgeTweak.processNewPosts(updated);
|
window.RedditTweaks.badgeTweak.processNewPosts(updated);
|
||||||
}
|
}
|
||||||
if (settings.cardLayout) {
|
if (updated.cardLayout) {
|
||||||
window.RedditTweaks.cardTweak.processNewPosts(updated);
|
window.RedditTweaks.cardTweak.processNewPosts(updated);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -62,6 +63,8 @@
|
|||||||
var settings = await window.RedditTweaks.loadSettings();
|
var settings = await window.RedditTweaks.loadSettings();
|
||||||
if (!settings.enabled) return;
|
if (!settings.enabled) return;
|
||||||
|
|
||||||
|
window.RedditTweaks.applyDarkModeClass(settings);
|
||||||
|
|
||||||
if (settings.badgeLayout) {
|
if (settings.badgeLayout) {
|
||||||
document.documentElement.classList.add("rt-badges-enabled");
|
document.documentElement.classList.add("rt-badges-enabled");
|
||||||
window.RedditTweaks.badgeTweak.apply(settings);
|
window.RedditTweaks.badgeTweak.apply(settings);
|
||||||
@@ -80,18 +83,19 @@
|
|||||||
startDarkModeObserver(settings);
|
startDarkModeObserver(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var RELOAD_KEYS = ["enabled", "badgeLayout", "fontOverride", "cardLayout"];
|
||||||
|
|
||||||
browser.storage.onChanged.addListener(function (changes) {
|
browser.storage.onChanged.addListener(function (changes) {
|
||||||
if (
|
var needsReload = RELOAD_KEYS.some(function (key) {
|
||||||
(changes.enabled && changes.enabled.newValue !== changes.enabled.oldValue) ||
|
return changes[key] && changes[key].newValue !== changes[key].oldValue;
|
||||||
(changes.badgeLayout && changes.badgeLayout.newValue !== changes.badgeLayout.oldValue) ||
|
});
|
||||||
(changes.fontOverride && changes.fontOverride.newValue !== changes.fontOverride.oldValue) ||
|
if (needsReload) {
|
||||||
(changes.cardLayout && changes.cardLayout.newValue !== changes.cardLayout.oldValue)
|
|
||||||
) {
|
|
||||||
location.reload();
|
location.reload();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.RedditTweaks.loadSettings().then(function (updated) {
|
window.RedditTweaks.loadSettings().then(function (updated) {
|
||||||
|
window.RedditTweaks.applyDarkModeClass(updated);
|
||||||
if (updated.badgeLayout) {
|
if (updated.badgeLayout) {
|
||||||
window.RedditTweaks.badgeTweak.updateColors(updated);
|
window.RedditTweaks.badgeTweak.updateColors(updated);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,529 +83,3 @@ html.rt-badges-enabled .thing.link .flat-list li:has(> .comments) {
|
|||||||
.rt-badge-gear:hover {
|
.rt-badge-gear:hover {
|
||||||
opacity: 1 !important;
|
opacity: 1 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Color popover --- */
|
|
||||||
.rt-color-popover {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 10000;
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 6px;
|
|
||||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
|
|
||||||
padding: 12px;
|
|
||||||
width: 260px;
|
|
||||||
overflow-y: auto;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
||||||
font-size: 13px;
|
|
||||||
color: #1a1a1a;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-popover-visible {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
padding-bottom: 6px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-title {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 13px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
max-width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-close {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
font-size: 16px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #999;
|
|
||||||
padding: 0 2px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-close:hover {
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-mode {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-mode select {
|
|
||||||
width: 100%;
|
|
||||||
padding: 3px 6px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-row-label {
|
|
||||||
font-size: 12px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-row-inputs {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-row .rt-color-swatch {
|
|
||||||
width: 28px;
|
|
||||||
height: 20px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-row input[type="text"] {
|
|
||||||
width: 70px;
|
|
||||||
padding: 2px 4px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-row input[type="text"].rt-input-error {
|
|
||||||
border-color: #d9534f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-preview {
|
|
||||||
margin: 8px 0;
|
|
||||||
padding: 6px 0;
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-footer {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 8px;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-popover-footer-right {
|
|
||||||
display: flex;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-btn-save {
|
|
||||||
background: #4a90d9;
|
|
||||||
color: #fff;
|
|
||||||
border: 1px solid #3a7bc8;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 4px 12px;
|
|
||||||
font-size: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-btn-save:hover {
|
|
||||||
background: #3a7bc8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-btn-cancel {
|
|
||||||
background: #f0f0f0;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 4px 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-btn-cancel:hover {
|
|
||||||
background: #e0e0e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-btn-reset {
|
|
||||||
background: none;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 4px 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-btn-reset:hover {
|
|
||||||
background: #f5f5f5;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Popover dark mode --- */
|
|
||||||
.rt-color-popover.rt-dark {
|
|
||||||
background: #2a2a2a;
|
|
||||||
border-color: #555;
|
|
||||||
color: #e0e0e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-popover-header {
|
|
||||||
border-bottom-color: #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-popover-close {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-popover-close:hover {
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-popover-mode select {
|
|
||||||
background: #333;
|
|
||||||
border-color: #555;
|
|
||||||
color: #e0e0e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-popover-row .rt-color-swatch {
|
|
||||||
border-color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-popover-row input[type="text"] {
|
|
||||||
background: #333;
|
|
||||||
border-color: #555;
|
|
||||||
color: #e0e0e0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-popover-preview {
|
|
||||||
border-top-color: #444;
|
|
||||||
border-bottom-color: #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-btn-save {
|
|
||||||
background: #4a90d9;
|
|
||||||
border-color: #3a7bc8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-btn-cancel {
|
|
||||||
background: #444;
|
|
||||||
border-color: #555;
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-btn-reset {
|
|
||||||
border-color: #555;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-btn-reset:hover {
|
|
||||||
background: #333;
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Preset badges --- */
|
|
||||||
.rt-popover-presets {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
padding: 8px 0;
|
|
||||||
border-top: 1px solid #eee;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-list {
|
|
||||||
display: flex;
|
|
||||||
gap: 4px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-badge {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
border: 1px solid;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 2px 6px;
|
|
||||||
font-size: 10px;
|
|
||||||
font-weight: bold;
|
|
||||||
cursor: pointer;
|
|
||||||
line-height: 1.4;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-badge:hover {
|
|
||||||
filter: brightness(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-delete {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
top: -6px;
|
|
||||||
right: -6px;
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
background: #d9534f;
|
|
||||||
color: white;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 14px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-badge:hover .rt-preset-delete {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-add {
|
|
||||||
width: 22px;
|
|
||||||
height: 22px;
|
|
||||||
border: 1px dashed #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
background: none;
|
|
||||||
color: #999;
|
|
||||||
font-size: 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex-shrink: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-add:hover {
|
|
||||||
border-color: #999;
|
|
||||||
color: #666;
|
|
||||||
background: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-popover-presets {
|
|
||||||
border-top-color: #444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-preset-add {
|
|
||||||
border-color: #555;
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-color-popover.rt-dark .rt-preset-add:hover {
|
|
||||||
border-color: #888;
|
|
||||||
color: #ccc;
|
|
||||||
background: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Color Picker Widget --- */
|
|
||||||
.rt-color-picker {
|
|
||||||
margin: 8px 0;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-tabs {
|
|
||||||
display: flex;
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-tab {
|
|
||||||
flex: 1;
|
|
||||||
padding: 4px 8px;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
border-bottom: 2px solid transparent;
|
|
||||||
font-size: 11px;
|
|
||||||
font-family: inherit;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-tab:hover {
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-tab--active {
|
|
||||||
color: #1a1a1a;
|
|
||||||
border-bottom-color: #4a90d9;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-panel {
|
|
||||||
max-height: 180px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-grid--palette {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-grid-row {
|
|
||||||
display: flex;
|
|
||||||
gap: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-swatch {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
border-radius: 2px;
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
||||||
cursor: pointer;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-swatch:hover {
|
|
||||||
border-color: rgba(0, 0, 0, 0.4);
|
|
||||||
transform: scale(1.2);
|
|
||||||
z-index: 1;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-swatch--selected {
|
|
||||||
border: 2px solid #1a1a1a;
|
|
||||||
box-shadow: 0 0 0 1px white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-grid--named {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 4px;
|
|
||||||
padding: 2px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-named-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
width: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-named-item .rt-picker-swatch {
|
|
||||||
width: 24px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-named-label {
|
|
||||||
font-size: 8px;
|
|
||||||
color: #888;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 100%;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-panel--custom {
|
|
||||||
max-height: none;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-sv-wrap {
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-sv {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
cursor: crosshair;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-sv-cursor {
|
|
||||||
position: absolute;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
border: 2px solid white;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
|
|
||||||
pointer-events: none;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-hue {
|
|
||||||
position: relative;
|
|
||||||
height: 14px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
background: linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
|
|
||||||
cursor: crosshair;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-hue-indicator {
|
|
||||||
position: absolute;
|
|
||||||
top: -1px;
|
|
||||||
width: 2px;
|
|
||||||
height: calc(100% + 2px);
|
|
||||||
background: white;
|
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
|
|
||||||
pointer-events: none;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Picker dark mode */
|
|
||||||
.rt-dark .rt-picker-tabs,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-tabs {
|
|
||||||
border-bottom-color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-tab,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-tab {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-tab:hover,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-tab:hover {
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-tab--active,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-tab--active {
|
|
||||||
color: #e0e0e0;
|
|
||||||
border-bottom-color: #4a90d9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-swatch,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-swatch {
|
|
||||||
border-color: rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-swatch:hover,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-swatch:hover {
|
|
||||||
border-color: rgba(255, 255, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-swatch--selected,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-swatch--selected {
|
|
||||||
border-color: #e0e0e0;
|
|
||||||
box-shadow: 0 0 0 1px #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-named-label,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-named-label {
|
|
||||||
color: #777;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-sv,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-sv {
|
|
||||||
border-color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-hue,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-hue {
|
|
||||||
border-color: #555;
|
|
||||||
}
|
|
||||||
|
|||||||
259
content/styles/color-picker.css
Normal file
259
content/styles/color-picker.css
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
/* --- Color Picker Widget --- */
|
||||||
|
.rt-color-picker {
|
||||||
|
margin: 8px 0;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-tabs {
|
||||||
|
display: flex;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-tab {
|
||||||
|
flex: 1;
|
||||||
|
padding: 4px 8px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
font-size: 11px;
|
||||||
|
font-family: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-tab:hover {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-tab--active {
|
||||||
|
color: #1a1a1a;
|
||||||
|
border-bottom-color: #4a90d9;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-panel {
|
||||||
|
max-height: 180px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-grid--palette {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-grid-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-swatch {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 2px;
|
||||||
|
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||||
|
cursor: pointer;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-swatch:hover {
|
||||||
|
border-color: rgba(0, 0, 0, 0.4);
|
||||||
|
transform: scale(1.2);
|
||||||
|
z-index: 1;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-swatch--selected {
|
||||||
|
border: 2px solid #1a1a1a;
|
||||||
|
box-shadow: 0 0 0 1px white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-grid--named {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px;
|
||||||
|
padding: 2px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-named-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-named-item .rt-picker-swatch {
|
||||||
|
width: 24px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-named-label {
|
||||||
|
font-size: 8px;
|
||||||
|
color: #888;
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
width: 100%;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-panel--custom {
|
||||||
|
max-height: none;
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-sv-wrap {
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-sv {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-sv-cursor {
|
||||||
|
position: absolute;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border: 2px solid white;
|
||||||
|
border-radius: 50%;
|
||||||
|
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-hue {
|
||||||
|
position: relative;
|
||||||
|
height: 14px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-picker-hue-indicator {
|
||||||
|
position: absolute;
|
||||||
|
top: -1px;
|
||||||
|
width: 2px;
|
||||||
|
height: calc(100% + 2px);
|
||||||
|
background: white;
|
||||||
|
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Preset badges --- */
|
||||||
|
.rt-preset-list {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-preset-badge {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 1.4;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-preset-badge:hover {
|
||||||
|
filter: brightness(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-preset-delete {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
right: -6px;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
background: #d9534f;
|
||||||
|
color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 14px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-preset-badge:hover .rt-preset-delete {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-preset-add {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
border: 1px dashed #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
background: none;
|
||||||
|
color: #999;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-preset-add:hover {
|
||||||
|
border-color: #999;
|
||||||
|
color: #666;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Picker dark mode --- */
|
||||||
|
.rt-dark .rt-picker-tabs {
|
||||||
|
border-bottom-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-picker-tab {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-picker-tab:hover {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-picker-tab--active {
|
||||||
|
color: #e0e0e0;
|
||||||
|
border-bottom-color: #4a90d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-picker-swatch {
|
||||||
|
border-color: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-picker-swatch:hover {
|
||||||
|
border-color: rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-picker-swatch--selected {
|
||||||
|
border-color: #e0e0e0;
|
||||||
|
box-shadow: 0 0 0 1px #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-picker-named-label {
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-picker-sv {
|
||||||
|
border-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-picker-hue {
|
||||||
|
border-color: #555;
|
||||||
|
}
|
||||||
256
content/styles/color-popover.css
Normal file
256
content/styles/color-popover.css
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
/* --- Color popover --- */
|
||||||
|
.rt-color-popover {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10000;
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
|
||||||
|
padding: 12px;
|
||||||
|
width: 260px;
|
||||||
|
overflow-y: auto;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #1a1a1a;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-color-popover.rt-popover-visible {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding-bottom: 6px;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-title {
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 13px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
max-width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-close {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #999;
|
||||||
|
padding: 0 2px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-close:hover {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-mode {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-mode select {
|
||||||
|
width: 100%;
|
||||||
|
padding: 3px 6px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-row-label {
|
||||||
|
font-size: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-row-inputs {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-row .rt-color-swatch {
|
||||||
|
width: 28px;
|
||||||
|
height: 20px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-row input[type="text"] {
|
||||||
|
width: 70px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-row input[type="text"].rt-input-error {
|
||||||
|
border-color: #d9534f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-preview {
|
||||||
|
margin: 8px 0;
|
||||||
|
padding: 6px 0;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 8px;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-popover-footer-right {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-btn-save {
|
||||||
|
background: #4a90d9;
|
||||||
|
color: #fff;
|
||||||
|
border: 1px solid #3a7bc8;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 4px 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-btn-save:hover {
|
||||||
|
background: #3a7bc8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-btn-cancel {
|
||||||
|
background: #f0f0f0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-btn-cancel:hover {
|
||||||
|
background: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-btn-reset {
|
||||||
|
background: none;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-btn-reset:hover {
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Popover preset container --- */
|
||||||
|
.rt-popover-presets {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 8px 0;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Popover dark mode --- */
|
||||||
|
.rt-dark .rt-color-popover {
|
||||||
|
background: #2a2a2a;
|
||||||
|
border-color: #555;
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-popover-header {
|
||||||
|
border-bottom-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-popover-close {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-popover-close:hover {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-popover-mode select {
|
||||||
|
background: #333;
|
||||||
|
border-color: #555;
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-popover-row .rt-color-swatch {
|
||||||
|
border-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-popover-row input[type="text"] {
|
||||||
|
background: #333;
|
||||||
|
border-color: #555;
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-popover-preview {
|
||||||
|
border-top-color: #444;
|
||||||
|
border-bottom-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-btn-save {
|
||||||
|
background: #4a90d9;
|
||||||
|
border-color: #3a7bc8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-btn-cancel {
|
||||||
|
background: #444;
|
||||||
|
border-color: #555;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-btn-reset {
|
||||||
|
border-color: #555;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-btn-reset:hover {
|
||||||
|
background: #333;
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-popover-presets {
|
||||||
|
border-top-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-preset-add {
|
||||||
|
border-color: #555;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rt-dark .rt-preset-add:hover {
|
||||||
|
border-color: #888;
|
||||||
|
color: #ccc;
|
||||||
|
background: #333;
|
||||||
|
}
|
||||||
@@ -6,12 +6,6 @@
|
|||||||
function applyColorsToContainer(container, settings, subredditName) {
|
function applyColorsToContainer(container, settings, subredditName) {
|
||||||
const prefix = window.RedditTweaks.getColorPrefix(settings);
|
const prefix = window.RedditTweaks.getColorPrefix(settings);
|
||||||
|
|
||||||
if (window.RedditTweaks.isDarkMode(settings)) {
|
|
||||||
container.classList.add("rt-dark");
|
|
||||||
} else {
|
|
||||||
container.classList.remove("rt-dark");
|
|
||||||
}
|
|
||||||
|
|
||||||
const entry = subredditName && settings.subredditColors[subredditName];
|
const entry = subredditName && settings.subredditColors[subredditName];
|
||||||
const overrides = entry && entry[prefix];
|
const overrides = entry && entry[prefix];
|
||||||
|
|
||||||
@@ -98,10 +92,6 @@
|
|||||||
const subredditName = container.getAttribute("data-rt-subreddit");
|
const subredditName = container.getAttribute("data-rt-subreddit");
|
||||||
applyColorsToContainer(container, settings, subredditName);
|
applyColorsToContainer(container, settings, subredditName);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (window.RedditTweaks.colorPopover && window.RedditTweaks.colorPopover.refreshTheme) {
|
|
||||||
window.RedditTweaks.colorPopover.refreshTheme(settings);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function apply(settings) {
|
function apply(settings) {
|
||||||
@@ -113,8 +103,6 @@
|
|||||||
window.RedditTweaks.badgeTweak = {
|
window.RedditTweaks.badgeTweak = {
|
||||||
apply: apply,
|
apply: apply,
|
||||||
updateColors: updateColors,
|
updateColors: updateColors,
|
||||||
isDarkMode: window.RedditTweaks.isDarkMode,
|
|
||||||
getColorPrefix: window.RedditTweaks.getColorPrefix,
|
|
||||||
processNewPosts: processPosts,
|
processNewPosts: processPosts,
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -19,14 +19,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyDarkMode(settings) {
|
|
||||||
if (window.RedditTweaks.isDarkMode(settings)) {
|
|
||||||
document.documentElement.classList.add("rt-dark");
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove("rt-dark");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyBackground(settings) {
|
function applyBackground(settings) {
|
||||||
if (settings.cardBackground === "shadcn") {
|
if (settings.cardBackground === "shadcn") {
|
||||||
document.documentElement.classList.add("rt-card-bg-shadcn");
|
document.documentElement.classList.add("rt-card-bg-shadcn");
|
||||||
@@ -68,7 +60,6 @@
|
|||||||
|
|
||||||
function apply(settings) {
|
function apply(settings) {
|
||||||
document.documentElement.classList.add("rt-card-enabled");
|
document.documentElement.classList.add("rt-card-enabled");
|
||||||
applyDarkMode(settings);
|
|
||||||
applyBackground(settings);
|
applyBackground(settings);
|
||||||
applyDensity(settings);
|
applyDensity(settings);
|
||||||
applyGap(settings);
|
applyGap(settings);
|
||||||
@@ -77,7 +68,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateSettings(settings) {
|
function updateSettings(settings) {
|
||||||
applyDarkMode(settings);
|
|
||||||
applyBackground(settings);
|
applyBackground(settings);
|
||||||
applyDensity(settings);
|
applyDensity(settings);
|
||||||
applyGap(settings);
|
applyGap(settings);
|
||||||
|
|||||||
@@ -13,22 +13,10 @@
|
|||||||
|
|
||||||
var els = {};
|
var els = {};
|
||||||
|
|
||||||
function getHelpers() {
|
|
||||||
return {
|
|
||||||
isDarkMode: window.RedditTweaks.isDarkMode,
|
|
||||||
getColorPrefix: window.RedditTweaks.getColorPrefix,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function hexValid(val) {
|
function hexValid(val) {
|
||||||
return /^#[0-9a-f]{6}$/i.test(val);
|
return /^#[0-9a-f]{6}$/i.test(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
function colorToHex(val) {
|
|
||||||
if (!val) return "#ffffff";
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
function createPopover() {
|
function createPopover() {
|
||||||
var el = document.createElement("div");
|
var el = document.createElement("div");
|
||||||
el.className = "rt-color-popover";
|
el.className = "rt-color-popover";
|
||||||
@@ -233,7 +221,7 @@
|
|||||||
var props = ["bg", "border", "text"];
|
var props = ["bg", "border", "text"];
|
||||||
for (var i = 0; i < props.length; i++) {
|
for (var i = 0; i < props.length; i++) {
|
||||||
var prop = props[i];
|
var prop = props[i];
|
||||||
var val = colorToHex(colors[prop]);
|
var val = colors[prop] || "#ffffff";
|
||||||
els.rows[prop].swatch.style.backgroundColor = val;
|
els.rows[prop].swatch.style.backgroundColor = val;
|
||||||
els.rows[prop].hex.value = val;
|
els.rows[prop].hex.value = val;
|
||||||
els.rows[prop].hex.classList.remove("rt-input-error");
|
els.rows[prop].hex.classList.remove("rt-input-error");
|
||||||
@@ -250,32 +238,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderPresets(presets) {
|
function renderPresets(presets) {
|
||||||
els.presetList.innerHTML = "";
|
window.RedditTweaks.presets.render(
|
||||||
for (var i = 0; i < presets.length; i++) {
|
els.presetList,
|
||||||
(function (index) {
|
presets,
|
||||||
var p = presets[index];
|
applyPreset,
|
||||||
var badge = document.createElement("span");
|
function (index) {
|
||||||
badge.className = "rt-preset-badge";
|
window.RedditTweaks.presets.delete(index, renderPresets);
|
||||||
badge.style.background = p.bg;
|
|
||||||
badge.style.borderColor = p.border;
|
|
||||||
badge.style.color = p.text;
|
|
||||||
badge.textContent = "Aa";
|
|
||||||
badge.title = "Click to apply";
|
|
||||||
badge.addEventListener("click", function () {
|
|
||||||
applyPreset(p);
|
|
||||||
});
|
|
||||||
|
|
||||||
var del = document.createElement("span");
|
|
||||||
del.className = "rt-preset-delete";
|
|
||||||
del.textContent = "\u00d7";
|
|
||||||
del.addEventListener("click", function (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
removePreset(index);
|
|
||||||
});
|
|
||||||
badge.appendChild(del);
|
|
||||||
els.presetList.appendChild(badge);
|
|
||||||
})(i);
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyPreset(p) {
|
function applyPreset(p) {
|
||||||
@@ -293,27 +263,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveAsPreset() {
|
function saveAsPreset() {
|
||||||
var preset = {
|
window.RedditTweaks.presets.save(
|
||||||
|
{
|
||||||
bg: els.rows.bg.hex.value,
|
bg: els.rows.bg.hex.value,
|
||||||
border: els.rows.border.hex.value,
|
border: els.rows.border.hex.value,
|
||||||
text: els.rows.text.hex.value,
|
text: els.rows.text.hex.value,
|
||||||
};
|
},
|
||||||
var settings = await window.RedditTweaks.loadSettings();
|
renderPresets
|
||||||
var presets = settings.colorPresets || [];
|
);
|
||||||
presets.push(preset);
|
|
||||||
settings.colorPresets = presets;
|
|
||||||
await window.RedditTweaks.saveSettings(settings);
|
|
||||||
renderPresets(presets);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function removePreset(index) {
|
|
||||||
var settings = await window.RedditTweaks.loadSettings();
|
|
||||||
var presets = settings.colorPresets || [];
|
|
||||||
presets.splice(index, 1);
|
|
||||||
settings.colorPresets = presets;
|
|
||||||
await window.RedditTweaks.saveSettings(settings);
|
|
||||||
renderPresets(presets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function positionPopover(anchorEl) {
|
function positionPopover(anchorEl) {
|
||||||
@@ -354,15 +312,6 @@
|
|||||||
popoverEl.style.visibility = "";
|
popoverEl.style.visibility = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyDarkModeToPopover(settings) {
|
|
||||||
var helpers = getHelpers();
|
|
||||||
if (helpers.isDarkMode(settings)) {
|
|
||||||
popoverEl.classList.add("rt-dark");
|
|
||||||
} else {
|
|
||||||
popoverEl.classList.remove("rt-dark");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function open(badgeEl, subredditName, settings) {
|
function open(badgeEl, subredditName, settings) {
|
||||||
if (!popoverEl) createPopover();
|
if (!popoverEl) createPopover();
|
||||||
|
|
||||||
@@ -379,8 +328,7 @@
|
|||||||
hadOverride.light = !!(existingEntry && existingEntry.light);
|
hadOverride.light = !!(existingEntry && existingEntry.light);
|
||||||
hadOverride.dark = !!(existingEntry && existingEntry.dark);
|
hadOverride.dark = !!(existingEntry && existingEntry.dark);
|
||||||
|
|
||||||
var helpers = getHelpers();
|
selectedMode = window.RedditTweaks.getColorPrefix(settings);
|
||||||
selectedMode = helpers.getColorPrefix(settings);
|
|
||||||
|
|
||||||
editState.light = getColorsForMode(settings, subredditName, "light");
|
editState.light = getColorsForMode(settings, subredditName, "light");
|
||||||
editState.dark = getColorsForMode(settings, subredditName, "dark");
|
editState.dark = getColorsForMode(settings, subredditName, "dark");
|
||||||
@@ -390,7 +338,6 @@
|
|||||||
els.preview.textContent = "r/" + subredditName;
|
els.preview.textContent = "r/" + subredditName;
|
||||||
|
|
||||||
closePicker();
|
closePicker();
|
||||||
applyDarkModeToPopover(settings);
|
|
||||||
loadModeIntoInputs();
|
loadModeIntoInputs();
|
||||||
updatePreview();
|
updatePreview();
|
||||||
renderPresets(settings.colorPresets || []);
|
renderPresets(settings.colorPresets || []);
|
||||||
@@ -446,15 +393,9 @@
|
|||||||
updatePreview();
|
updatePreview();
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshTheme(settings) {
|
|
||||||
if (!popoverEl || !popoverEl.classList.contains("rt-popover-visible")) return;
|
|
||||||
applyDarkModeToPopover(settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.RedditTweaks = window.RedditTweaks || {};
|
window.RedditTweaks = window.RedditTweaks || {};
|
||||||
window.RedditTweaks.colorPopover = {
|
window.RedditTweaks.colorPopover = {
|
||||||
open: open,
|
open: open,
|
||||||
close: close,
|
close: close,
|
||||||
refreshTheme: refreshTheme,
|
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|||||||
186
docs/make_collage.py
Normal file
186
docs/make_collage.py
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
"""Compose a collage from three extension screenshots.
|
||||||
|
|
||||||
|
Layout (with padding and gaps):
|
||||||
|
+--padding--+---gap---+-----padding-----+
|
||||||
|
| | | |
|
||||||
|
| popup | | disabled (right) |
|
||||||
|
| (left) | +---------gap------+
|
||||||
|
| | | enabled (right) |
|
||||||
|
| | | |
|
||||||
|
+--padding--+---------+-----padding-----+
|
||||||
|
|
||||||
|
Usage: python docs/make_collage.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
import math
|
||||||
|
from pathlib import Path
|
||||||
|
from PIL import Image, ImageDraw, ImageFilter
|
||||||
|
|
||||||
|
DOCS = Path(__file__).parent
|
||||||
|
|
||||||
|
PAD = 20
|
||||||
|
GAP = 14
|
||||||
|
GRAD_START = (136, 136, 136)
|
||||||
|
GRAD_END = (87, 87, 87)
|
||||||
|
GRAD_ANGLE_DEG = 45
|
||||||
|
|
||||||
|
POPUP_COL_W = 230
|
||||||
|
|
||||||
|
BORDER_COLOR = (17, 17, 17)
|
||||||
|
BORDER_W = 1
|
||||||
|
CORNER_R = 4
|
||||||
|
|
||||||
|
SHADOW_OFFSET = (4, 4)
|
||||||
|
SHADOW_BLUR = 8
|
||||||
|
SHADOW_COLOR = (0, 0, 0, 110)
|
||||||
|
|
||||||
|
|
||||||
|
def scale_and_crop(img, target_w, target_h):
|
||||||
|
"""Scale image to cover target box, then crop from top-left."""
|
||||||
|
scale = max(target_w / img.width, target_h / img.height)
|
||||||
|
new_w = round(img.width * scale)
|
||||||
|
new_h = round(img.height * scale)
|
||||||
|
img = img.resize((new_w, new_h), Image.LANCZOS)
|
||||||
|
return img.crop((0, 0, target_w, target_h))
|
||||||
|
|
||||||
|
|
||||||
|
def make_gradient(w, h):
|
||||||
|
"""Create a linear gradient background at GRAD_ANGLE_DEG degrees."""
|
||||||
|
angle = math.radians(GRAD_ANGLE_DEG)
|
||||||
|
dx, dy = math.cos(angle), math.sin(angle)
|
||||||
|
pixels = []
|
||||||
|
for y in range(h):
|
||||||
|
for x in range(w):
|
||||||
|
t = (x * dx + y * dy) / (w * dx + h * dy)
|
||||||
|
t = max(0.0, min(1.0, t))
|
||||||
|
r = round(GRAD_START[0] + (GRAD_END[0] - GRAD_START[0]) * t)
|
||||||
|
g = round(GRAD_START[1] + (GRAD_END[1] - GRAD_START[1]) * t)
|
||||||
|
b = round(GRAD_START[2] + (GRAD_END[2] - GRAD_START[2]) * t)
|
||||||
|
pixels.append((r, g, b))
|
||||||
|
img = Image.new("RGB", (w, h))
|
||||||
|
img.putdata(pixels)
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
def round_corners(img, radius):
|
||||||
|
"""Apply rounded corners using an alpha mask."""
|
||||||
|
img = img.convert("RGBA")
|
||||||
|
mask = Image.new("L", img.size, 255)
|
||||||
|
draw = ImageDraw.Draw(mask)
|
||||||
|
draw.rectangle([0, 0, radius, radius], fill=0)
|
||||||
|
draw.rectangle([img.width - radius, 0, img.width, radius], fill=0)
|
||||||
|
draw.rectangle([0, img.height - radius, radius, img.height], fill=0)
|
||||||
|
draw.rectangle([img.width - radius, img.height - radius, img.width, img.height], fill=0)
|
||||||
|
draw.pieslice([0, 0, radius * 2, radius * 2], 180, 270, fill=255)
|
||||||
|
draw.pieslice([img.width - radius * 2, 0, img.width, radius * 2], 270, 360, fill=255)
|
||||||
|
draw.pieslice([0, img.height - radius * 2, radius * 2, img.height], 90, 180, fill=255)
|
||||||
|
draw.pieslice([img.width - radius * 2, img.height - radius * 2, img.width, img.height], 0, 90, fill=255)
|
||||||
|
img.putalpha(mask)
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
def add_border(img, color, width, radius):
|
||||||
|
"""Draw a rounded-rect border on an RGBA image."""
|
||||||
|
draw = ImageDraw.Draw(img)
|
||||||
|
draw.rounded_rectangle(
|
||||||
|
[0, 0, img.width - 1, img.height - 1],
|
||||||
|
radius=radius, outline=color, width=width,
|
||||||
|
)
|
||||||
|
return img
|
||||||
|
|
||||||
|
|
||||||
|
def make_shadow(w, h, radius):
|
||||||
|
"""Create a drop shadow image for a panel of size w x h."""
|
||||||
|
spread = SHADOW_BLUR * 2
|
||||||
|
sw = w + spread * 2
|
||||||
|
sh = h + spread * 2
|
||||||
|
shadow = Image.new("RGBA", (sw, sh), (0, 0, 0, 0))
|
||||||
|
draw = ImageDraw.Draw(shadow)
|
||||||
|
draw.rounded_rectangle(
|
||||||
|
[spread, spread, spread + w, spread + h],
|
||||||
|
radius=radius, fill=SHADOW_COLOR,
|
||||||
|
)
|
||||||
|
shadow = shadow.filter(ImageFilter.GaussianBlur(SHADOW_BLUR))
|
||||||
|
return shadow
|
||||||
|
|
||||||
|
|
||||||
|
def paste_panel(canvas, panel_img, x, y):
|
||||||
|
"""Paste a panel onto the canvas with rounded corners, border, and drop shadow."""
|
||||||
|
w, h = panel_img.size
|
||||||
|
panel = round_corners(panel_img, CORNER_R)
|
||||||
|
panel = add_border(panel, BORDER_COLOR, BORDER_W, CORNER_R)
|
||||||
|
|
||||||
|
shadow = make_shadow(w, h, CORNER_R)
|
||||||
|
spread = SHADOW_BLUR * 2
|
||||||
|
sx = x + SHADOW_OFFSET[0] - spread
|
||||||
|
sy = y + SHADOW_OFFSET[1] - spread
|
||||||
|
canvas.paste(shadow, (sx, sy), shadow)
|
||||||
|
|
||||||
|
canvas.paste(panel, (x, y), panel)
|
||||||
|
|
||||||
|
|
||||||
|
ASPECT_RATIO = (4, 3)
|
||||||
|
MAX_DIMENSION = 1200
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
popup = Image.open(DOCS / "reddit-extension-popup.png")
|
||||||
|
disabled = Image.open(DOCS / "reddit-extension-disabled.png")
|
||||||
|
enabled = Image.open(DOCS / "reddit-extension-enabled.png")
|
||||||
|
|
||||||
|
popup_scale = POPUP_COL_W / popup.width
|
||||||
|
popup_natural_h = round(popup.height * popup_scale)
|
||||||
|
|
||||||
|
right_col_w = 700
|
||||||
|
right_panel_h = (popup_natural_h - GAP) // 2
|
||||||
|
|
||||||
|
content_h = popup_natural_h
|
||||||
|
content_w = POPUP_COL_W + GAP + right_col_w
|
||||||
|
|
||||||
|
shadow_extra = max(SHADOW_OFFSET[0], SHADOW_OFFSET[1]) + SHADOW_BLUR
|
||||||
|
inner_w = content_w + 2 * PAD + shadow_extra
|
||||||
|
inner_h = content_h + 2 * PAD + shadow_extra
|
||||||
|
|
||||||
|
aspect_w, aspect_h = ASPECT_RATIO
|
||||||
|
target_w = max(inner_w, round(inner_h * aspect_w / aspect_h))
|
||||||
|
target_h = max(inner_h, round(target_w * aspect_h / aspect_w))
|
||||||
|
|
||||||
|
# Clamp to MAX_DIMENSION, scaling down proportionally
|
||||||
|
if max(target_w, target_h) > MAX_DIMENSION:
|
||||||
|
scale_down = MAX_DIMENSION / max(target_w, target_h)
|
||||||
|
target_w = round(target_w * scale_down)
|
||||||
|
target_h = round(target_h * scale_down)
|
||||||
|
inner_w = round(inner_w * scale_down)
|
||||||
|
inner_h = round(inner_h * scale_down)
|
||||||
|
popup_natural_h = round(popup_natural_h * scale_down)
|
||||||
|
right_col_w = round(right_col_w * scale_down)
|
||||||
|
right_panel_h = round(right_panel_h * scale_down)
|
||||||
|
popup_col_w = round(POPUP_COL_W * scale_down)
|
||||||
|
pad = round(PAD * scale_down)
|
||||||
|
gap = round(GAP * scale_down)
|
||||||
|
else:
|
||||||
|
popup_col_w = POPUP_COL_W
|
||||||
|
pad = PAD
|
||||||
|
gap = GAP
|
||||||
|
|
||||||
|
canvas = make_gradient(target_w, target_h).convert("RGBA")
|
||||||
|
|
||||||
|
x_off = (target_w - inner_w) // 2
|
||||||
|
y_off = (target_h - inner_h) // 2
|
||||||
|
|
||||||
|
popup_resized = popup.resize((popup_col_w, popup_natural_h), Image.LANCZOS)
|
||||||
|
paste_panel(canvas, popup_resized, x_off + pad, y_off + pad)
|
||||||
|
|
||||||
|
rx = x_off + pad + popup_col_w + gap
|
||||||
|
paste_panel(canvas, scale_and_crop(disabled, right_col_w, right_panel_h), rx, y_off + pad)
|
||||||
|
paste_panel(canvas, scale_and_crop(enabled, right_col_w, right_panel_h), rx, y_off + pad + right_panel_h + gap)
|
||||||
|
|
||||||
|
out = DOCS / "reddit-extension-collage.png"
|
||||||
|
canvas.convert("RGB").save(out, optimize=True)
|
||||||
|
print(f"Saved {out} ({target_w}x{target_h})")
|
||||||
|
print(f"Popup: {popup_col_w}x{popup_natural_h} (showing 100%)")
|
||||||
|
print(f"Right panels: {right_col_w}x{right_panel_h} each")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
BIN
docs/reddit-extension-collage.png
Normal file
BIN
docs/reddit-extension-collage.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 417 KiB |
BIN
docs/reddit-extension-disabled.png
Normal file
BIN
docs/reddit-extension-disabled.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 912 KiB |
BIN
docs/reddit-extension-enabled.png
Normal file
BIN
docs/reddit-extension-enabled.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 709 KiB |
BIN
docs/reddit-extension-popup.png
Normal file
BIN
docs/reddit-extension-popup.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 207 KiB |
57
lib/presets.js
Normal file
57
lib/presets.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function renderPresets(container, presets, onApply, onDelete) {
|
||||||
|
container.innerHTML = "";
|
||||||
|
for (var i = 0; i < presets.length; i++) {
|
||||||
|
(function (index) {
|
||||||
|
var p = presets[index];
|
||||||
|
var badge = document.createElement("span");
|
||||||
|
badge.className = "rt-preset-badge";
|
||||||
|
badge.style.background = p.bg;
|
||||||
|
badge.style.borderColor = p.border;
|
||||||
|
badge.style.color = p.text;
|
||||||
|
badge.textContent = "Aa";
|
||||||
|
badge.title = "Click to apply";
|
||||||
|
badge.addEventListener("click", function () {
|
||||||
|
onApply(p);
|
||||||
|
});
|
||||||
|
|
||||||
|
var del = document.createElement("span");
|
||||||
|
del.className = "rt-preset-delete";
|
||||||
|
del.textContent = "\u00d7";
|
||||||
|
del.addEventListener("click", function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
onDelete(index);
|
||||||
|
});
|
||||||
|
badge.appendChild(del);
|
||||||
|
container.appendChild(badge);
|
||||||
|
})(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function savePreset(preset, onDone) {
|
||||||
|
var settings = await window.RedditTweaks.loadSettings();
|
||||||
|
var presets = settings.colorPresets || [];
|
||||||
|
presets.push(preset);
|
||||||
|
settings.colorPresets = presets;
|
||||||
|
await window.RedditTweaks.saveSettings(settings);
|
||||||
|
onDone(presets);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deletePreset(index, onDone) {
|
||||||
|
var settings = await window.RedditTweaks.loadSettings();
|
||||||
|
var presets = settings.colorPresets || [];
|
||||||
|
presets.splice(index, 1);
|
||||||
|
settings.colorPresets = presets;
|
||||||
|
await window.RedditTweaks.saveSettings(settings);
|
||||||
|
onDone(presets);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.RedditTweaks = window.RedditTweaks || {};
|
||||||
|
window.RedditTweaks.presets = {
|
||||||
|
render: renderPresets,
|
||||||
|
save: savePreset,
|
||||||
|
delete: deletePreset,
|
||||||
|
};
|
||||||
|
})();
|
||||||
@@ -76,6 +76,14 @@
|
|||||||
return isDarkMode(settings) ? "dark" : "light";
|
return isDarkMode(settings) ? "dark" : "light";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyDarkModeClass(settings) {
|
||||||
|
if (isDarkMode(settings)) {
|
||||||
|
document.documentElement.classList.add("rt-dark");
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove("rt-dark");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.RedditTweaks = window.RedditTweaks || {};
|
window.RedditTweaks = window.RedditTweaks || {};
|
||||||
window.RedditTweaks.DEFAULTS = DEFAULTS;
|
window.RedditTweaks.DEFAULTS = DEFAULTS;
|
||||||
window.RedditTweaks.loadSettings = loadSettings;
|
window.RedditTweaks.loadSettings = loadSettings;
|
||||||
@@ -83,4 +91,5 @@
|
|||||||
window.RedditTweaks.resetSettings = resetSettings;
|
window.RedditTweaks.resetSettings = resetSettings;
|
||||||
window.RedditTweaks.isDarkMode = isDarkMode;
|
window.RedditTweaks.isDarkMode = isDarkMode;
|
||||||
window.RedditTweaks.getColorPrefix = getColorPrefix;
|
window.RedditTweaks.getColorPrefix = getColorPrefix;
|
||||||
|
window.RedditTweaks.applyDarkModeClass = applyDarkModeClass;
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
"content_scripts": [
|
"content_scripts": [
|
||||||
{
|
{
|
||||||
"matches": ["*://old.reddit.com/*", "*://www.reddit.com/*"],
|
"matches": ["*://old.reddit.com/*", "*://www.reddit.com/*"],
|
||||||
"css": ["content/styles/badges.css", "content/styles/cards.css", "content/styles/fonts.css"],
|
"css": ["content/styles/badges.css", "content/styles/color-popover.css", "content/styles/color-picker.css", "content/styles/cards.css", "content/styles/fonts.css"],
|
||||||
"js": [
|
"js": [
|
||||||
"lib/settings.js",
|
"lib/settings.js",
|
||||||
|
"lib/presets.js",
|
||||||
"content/tweaks/badges.js",
|
"content/tweaks/badges.js",
|
||||||
"content/tweaks/color-picker.js",
|
"content/tweaks/color-picker.js",
|
||||||
"content/tweaks/color-popover.js",
|
"content/tweaks/color-popover.js",
|
||||||
|
|||||||
271
popup/popup.css
271
popup/popup.css
@@ -210,7 +210,7 @@ fieldset input[type="text"] {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --- Preset badges --- */
|
/* --- Popup-specific preset bar --- */
|
||||||
.rt-preset-bar {
|
.rt-preset-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -218,272 +218,3 @@ fieldset input[type="text"] {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rt-preset-list {
|
|
||||||
display: flex;
|
|
||||||
gap: 4px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-badge {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
border: 1px solid;
|
|
||||||
border-radius: 3px;
|
|
||||||
padding: 2px 6px;
|
|
||||||
font-size: 10px;
|
|
||||||
font-weight: bold;
|
|
||||||
cursor: pointer;
|
|
||||||
line-height: 1.4;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-badge:hover {
|
|
||||||
filter: brightness(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-delete {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
top: -6px;
|
|
||||||
right: -6px;
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
background: #d9534f;
|
|
||||||
color: white;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 14px;
|
|
||||||
text-align: center;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-badge:hover .rt-preset-delete {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-add {
|
|
||||||
width: 22px;
|
|
||||||
height: 22px;
|
|
||||||
border: 1px dashed #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
background: none;
|
|
||||||
color: #999;
|
|
||||||
font-size: 14px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
flex-shrink: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-preset-add:hover {
|
|
||||||
border-color: #999;
|
|
||||||
color: #666;
|
|
||||||
background: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --- Color Picker Widget --- */
|
|
||||||
.rt-color-picker {
|
|
||||||
margin: 8px 0;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-tabs {
|
|
||||||
display: flex;
|
|
||||||
border-bottom: 1px solid #ccc;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-tab {
|
|
||||||
flex: 1;
|
|
||||||
padding: 4px 8px;
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
border-bottom: 2px solid transparent;
|
|
||||||
font-size: 11px;
|
|
||||||
font-family: inherit;
|
|
||||||
cursor: pointer;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-tab:hover {
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-tab--active {
|
|
||||||
color: #1a1a1a;
|
|
||||||
border-bottom-color: #4a90d9;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-panel {
|
|
||||||
max-height: 180px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-grid--palette {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-grid-row {
|
|
||||||
display: flex;
|
|
||||||
gap: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-swatch {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
border-radius: 2px;
|
|
||||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
||||||
cursor: pointer;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-swatch:hover {
|
|
||||||
border-color: rgba(0, 0, 0, 0.4);
|
|
||||||
transform: scale(1.2);
|
|
||||||
z-index: 1;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-swatch--selected {
|
|
||||||
border: 2px solid #1a1a1a;
|
|
||||||
box-shadow: 0 0 0 1px white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-grid--named {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 4px;
|
|
||||||
padding: 2px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-named-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
width: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-named-item .rt-picker-swatch {
|
|
||||||
width: 24px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-named-label {
|
|
||||||
font-size: 8px;
|
|
||||||
color: #888;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
width: 100%;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-panel--custom {
|
|
||||||
max-height: none;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-sv-wrap {
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-sv {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
cursor: crosshair;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-sv-cursor {
|
|
||||||
position: absolute;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
border: 2px solid white;
|
|
||||||
border-radius: 50%;
|
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
|
|
||||||
pointer-events: none;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-hue {
|
|
||||||
position: relative;
|
|
||||||
height: 14px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
background: linear-gradient(to right, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000);
|
|
||||||
cursor: crosshair;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-picker-hue-indicator {
|
|
||||||
position: absolute;
|
|
||||||
top: -1px;
|
|
||||||
width: 2px;
|
|
||||||
height: calc(100% + 2px);
|
|
||||||
background: white;
|
|
||||||
box-shadow: 0 0 2px rgba(0, 0, 0, 0.5);
|
|
||||||
pointer-events: none;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Picker dark mode */
|
|
||||||
.rt-dark .rt-picker-tabs,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-tabs {
|
|
||||||
border-bottom-color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-tab,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-tab {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-tab:hover,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-tab:hover {
|
|
||||||
color: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-tab--active,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-tab--active {
|
|
||||||
color: #e0e0e0;
|
|
||||||
border-bottom-color: #4a90d9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-swatch,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-swatch {
|
|
||||||
border-color: rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-swatch:hover,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-swatch:hover {
|
|
||||||
border-color: rgba(255, 255, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-swatch--selected,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-swatch--selected {
|
|
||||||
border-color: #e0e0e0;
|
|
||||||
box-shadow: 0 0 0 1px #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-named-label,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-named-label {
|
|
||||||
color: #777;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-sv,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-sv {
|
|
||||||
border-color: #555;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rt-dark .rt-picker-hue,
|
|
||||||
.rt-color-popover.rt-dark .rt-picker-hue {
|
|
||||||
border-color: #555;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="stylesheet" href="popup.css">
|
<link rel="stylesheet" href="popup.css">
|
||||||
|
<link rel="stylesheet" href="../content/styles/color-picker.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="popup-container">
|
<div class="popup-container">
|
||||||
@@ -118,6 +119,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="../lib/settings.js"></script>
|
<script src="../lib/settings.js"></script>
|
||||||
|
<script src="../lib/presets.js"></script>
|
||||||
<script src="../content/tweaks/color-picker.js"></script>
|
<script src="../content/tweaks/color-picker.js"></script>
|
||||||
<script src="popup.js"></script>
|
<script src="popup.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
161
popup/popup.js
161
popup/popup.js
@@ -4,6 +4,7 @@
|
|||||||
var picker = null;
|
var picker = null;
|
||||||
var activeSwatchEl = null;
|
var activeSwatchEl = null;
|
||||||
var saveDebounceTimer = null;
|
var saveDebounceTimer = null;
|
||||||
|
var subredditEntries = [];
|
||||||
|
|
||||||
var COLOR_KEYS = [
|
var COLOR_KEYS = [
|
||||||
"light.subredditBgColor",
|
"light.subredditBgColor",
|
||||||
@@ -20,11 +21,6 @@
|
|||||||
"dark.commentsTextColor",
|
"dark.commentsTextColor",
|
||||||
];
|
];
|
||||||
|
|
||||||
function colorToHex(val) {
|
|
||||||
if (!val) return "#ffffff";
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getColorValue(el) {
|
function getColorValue(el) {
|
||||||
return el.dataset.value || "#ffffff";
|
return el.dataset.value || "#ffffff";
|
||||||
}
|
}
|
||||||
@@ -78,7 +74,7 @@
|
|||||||
|
|
||||||
COLOR_KEYS.forEach(function (key) {
|
COLOR_KEYS.forEach(function (key) {
|
||||||
var el = document.getElementById(key);
|
var el = document.getElementById(key);
|
||||||
if (el) setColorValue(el, colorToHex(settings[key]));
|
if (el) setColorValue(el, settings[key] || "#ffffff");
|
||||||
});
|
});
|
||||||
|
|
||||||
renderSubredditOverrides(settings.subredditColors || {});
|
renderSubredditOverrides(settings.subredditColors || {});
|
||||||
@@ -87,6 +83,7 @@
|
|||||||
function renderSubredditOverrides(overrides) {
|
function renderSubredditOverrides(overrides) {
|
||||||
var list = document.getElementById("subredditList");
|
var list = document.getElementById("subredditList");
|
||||||
list.innerHTML = "";
|
list.innerHTML = "";
|
||||||
|
subredditEntries = [];
|
||||||
|
|
||||||
Object.entries(overrides).forEach(function (pair) {
|
Object.entries(overrides).forEach(function (pair) {
|
||||||
addSubredditEntry(pair[0], pair[1]);
|
addSubredditEntry(pair[0], pair[1]);
|
||||||
@@ -95,8 +92,8 @@
|
|||||||
|
|
||||||
function addSubredditEntry(name, modeColors) {
|
function addSubredditEntry(name, modeColors) {
|
||||||
var list = document.getElementById("subredditList");
|
var list = document.getElementById("subredditList");
|
||||||
var entry = document.createElement("div");
|
var el = document.createElement("div");
|
||||||
entry.className = "subreddit-entry";
|
el.className = "subreddit-entry";
|
||||||
|
|
||||||
var header = document.createElement("div");
|
var header = document.createElement("div");
|
||||||
header.className = "subreddit-entry-header";
|
header.className = "subreddit-entry-header";
|
||||||
@@ -106,17 +103,7 @@
|
|||||||
nameInput.placeholder = "subreddit";
|
nameInput.placeholder = "subreddit";
|
||||||
nameInput.value = name || "";
|
nameInput.value = name || "";
|
||||||
|
|
||||||
var removeBtn = document.createElement("button");
|
|
||||||
removeBtn.className = "btn-remove";
|
|
||||||
removeBtn.textContent = "\u00d7";
|
|
||||||
removeBtn.addEventListener("click", function () {
|
|
||||||
closePicker();
|
|
||||||
entry.remove();
|
|
||||||
saveFromControls();
|
|
||||||
});
|
|
||||||
|
|
||||||
header.appendChild(nameInput);
|
header.appendChild(nameInput);
|
||||||
header.appendChild(removeBtn);
|
|
||||||
|
|
||||||
var modeRow = document.createElement("div");
|
var modeRow = document.createElement("div");
|
||||||
modeRow.className = "subreddit-entry-mode";
|
modeRow.className = "subreddit-entry-mode";
|
||||||
@@ -134,39 +121,59 @@
|
|||||||
|
|
||||||
var bgSwatch = document.createElement("div");
|
var bgSwatch = document.createElement("div");
|
||||||
bgSwatch.className = "rt-color-swatch";
|
bgSwatch.className = "rt-color-swatch";
|
||||||
setColorValue(bgSwatch, colorToHex(lightColors.bg));
|
setColorValue(bgSwatch, lightColors.bg || "#ffffff");
|
||||||
bgSwatch.title = "Background";
|
bgSwatch.title = "Background";
|
||||||
|
|
||||||
var borderSwatch = document.createElement("div");
|
var borderSwatch = document.createElement("div");
|
||||||
borderSwatch.className = "rt-color-swatch";
|
borderSwatch.className = "rt-color-swatch";
|
||||||
setColorValue(borderSwatch, colorToHex(lightColors.border));
|
setColorValue(borderSwatch, lightColors.border || "#ffffff");
|
||||||
borderSwatch.title = "Border";
|
borderSwatch.title = "Border";
|
||||||
|
|
||||||
var textSwatch = document.createElement("div");
|
var textSwatch = document.createElement("div");
|
||||||
textSwatch.className = "rt-color-swatch";
|
textSwatch.className = "rt-color-swatch";
|
||||||
setColorValue(textSwatch, colorToHex(lightColors.text));
|
setColorValue(textSwatch, lightColors.text || "#ffffff");
|
||||||
textSwatch.title = "Text";
|
textSwatch.title = "Text";
|
||||||
|
|
||||||
colorsDiv.appendChild(bgSwatch);
|
colorsDiv.appendChild(bgSwatch);
|
||||||
colorsDiv.appendChild(borderSwatch);
|
colorsDiv.appendChild(borderSwatch);
|
||||||
colorsDiv.appendChild(textSwatch);
|
colorsDiv.appendChild(textSwatch);
|
||||||
|
|
||||||
entry._colorState = {
|
var state = {
|
||||||
|
nameInput: nameInput,
|
||||||
|
bgSwatch: bgSwatch,
|
||||||
|
borderSwatch: borderSwatch,
|
||||||
|
textSwatch: textSwatch,
|
||||||
|
modeSelect: modeSelect,
|
||||||
|
colorState: {
|
||||||
light: { bg: getColorValue(bgSwatch), border: getColorValue(borderSwatch), text: getColorValue(textSwatch) },
|
light: { bg: getColorValue(bgSwatch), border: getColorValue(borderSwatch), text: getColorValue(textSwatch) },
|
||||||
dark: { bg: colorToHex(darkColors.bg), border: colorToHex(darkColors.border), text: colorToHex(darkColors.text) },
|
dark: { bg: darkColors.bg || "#ffffff", border: darkColors.border || "#ffffff", text: darkColors.text || "#ffffff" },
|
||||||
};
|
},
|
||||||
entry._hadOverride = {
|
hadOverride: {
|
||||||
light: !!(modeColors && modeColors.light),
|
light: !!(modeColors && modeColors.light),
|
||||||
dark: !!(modeColors && modeColors.dark),
|
dark: !!(modeColors && modeColors.dark),
|
||||||
|
},
|
||||||
|
dirtyModes: { light: false, dark: false },
|
||||||
};
|
};
|
||||||
entry._dirtyModes = { light: false, dark: false };
|
subredditEntries.push(state);
|
||||||
|
|
||||||
|
var removeBtn = document.createElement("button");
|
||||||
|
removeBtn.className = "btn-remove";
|
||||||
|
removeBtn.textContent = "\u00d7";
|
||||||
|
removeBtn.addEventListener("click", function () {
|
||||||
|
closePicker();
|
||||||
|
var idx = subredditEntries.indexOf(state);
|
||||||
|
if (idx !== -1) subredditEntries.splice(idx, 1);
|
||||||
|
el.remove();
|
||||||
|
saveFromControls();
|
||||||
|
});
|
||||||
|
header.appendChild(removeBtn);
|
||||||
|
|
||||||
modeSelect.addEventListener("change", function () {
|
modeSelect.addEventListener("change", function () {
|
||||||
closePicker();
|
closePicker();
|
||||||
var prev = modeSelect.value === "dark" ? "light" : "dark";
|
var prev = modeSelect.value === "dark" ? "light" : "dark";
|
||||||
entry._dirtyModes[prev] = true;
|
state.dirtyModes[prev] = true;
|
||||||
entry._colorState[prev] = { bg: getColorValue(bgSwatch), border: getColorValue(borderSwatch), text: getColorValue(textSwatch) };
|
state.colorState[prev] = { bg: getColorValue(bgSwatch), border: getColorValue(borderSwatch), text: getColorValue(textSwatch) };
|
||||||
var next = entry._colorState[modeSelect.value];
|
var next = state.colorState[modeSelect.value];
|
||||||
setColorValue(bgSwatch, next.bg);
|
setColorValue(bgSwatch, next.bg);
|
||||||
setColorValue(borderSwatch, next.border);
|
setColorValue(borderSwatch, next.border);
|
||||||
setColorValue(textSwatch, next.text);
|
setColorValue(textSwatch, next.text);
|
||||||
@@ -175,7 +182,7 @@
|
|||||||
[bgSwatch, borderSwatch, textSwatch].forEach(function (swatch) {
|
[bgSwatch, borderSwatch, textSwatch].forEach(function (swatch) {
|
||||||
swatch.addEventListener("click", function () {
|
swatch.addEventListener("click", function () {
|
||||||
openPickerForSwatch(swatch, function () {
|
openPickerForSwatch(swatch, function () {
|
||||||
entry._dirtyModes[modeSelect.value] = true;
|
state.dirtyModes[modeSelect.value] = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -184,39 +191,32 @@
|
|||||||
saveFromControls();
|
saveFromControls();
|
||||||
});
|
});
|
||||||
|
|
||||||
entry.appendChild(header);
|
el.appendChild(header);
|
||||||
entry.appendChild(modeRow);
|
el.appendChild(modeRow);
|
||||||
entry.appendChild(colorsDiv);
|
el.appendChild(colorsDiv);
|
||||||
|
|
||||||
entry._nameInput = nameInput;
|
list.appendChild(el);
|
||||||
entry._bgSwatch = bgSwatch;
|
|
||||||
entry._borderSwatch = borderSwatch;
|
|
||||||
entry._textSwatch = textSwatch;
|
|
||||||
entry._modeSelect = modeSelect;
|
|
||||||
|
|
||||||
list.appendChild(entry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectSubredditOverrides() {
|
function collectSubredditOverrides() {
|
||||||
var overrides = {};
|
var overrides = {};
|
||||||
var entries = document.querySelectorAll(".subreddit-entry");
|
subredditEntries.forEach(function (state) {
|
||||||
entries.forEach(function (entry) {
|
var name = state.nameInput.value.trim().replace(/^r\//, "");
|
||||||
var name = entry._nameInput.value.trim().replace(/^r\//, "");
|
|
||||||
if (!name) return;
|
if (!name) return;
|
||||||
|
|
||||||
var currentMode = entry._modeSelect.value;
|
var currentMode = state.modeSelect.value;
|
||||||
entry._colorState[currentMode] = {
|
state.colorState[currentMode] = {
|
||||||
bg: getColorValue(entry._bgSwatch),
|
bg: getColorValue(state.bgSwatch),
|
||||||
border: getColorValue(entry._borderSwatch),
|
border: getColorValue(state.borderSwatch),
|
||||||
text: getColorValue(entry._textSwatch),
|
text: getColorValue(state.textSwatch),
|
||||||
};
|
};
|
||||||
|
|
||||||
var entryOverrides = {};
|
var entryOverrides = {};
|
||||||
if (entry._hadOverride.light || entry._dirtyModes.light) {
|
if (state.hadOverride.light || state.dirtyModes.light) {
|
||||||
entryOverrides.light = entry._colorState.light;
|
entryOverrides.light = state.colorState.light;
|
||||||
}
|
}
|
||||||
if (entry._hadOverride.dark || entry._dirtyModes.dark) {
|
if (state.hadOverride.dark || state.dirtyModes.dark) {
|
||||||
entryOverrides.dark = entry._colorState.dark;
|
entryOverrides.dark = state.colorState.dark;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entryOverrides.light || entryOverrides.dark) {
|
if (entryOverrides.light || entryOverrides.dark) {
|
||||||
@@ -227,60 +227,31 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderPopupPresets(presets) {
|
function renderPopupPresets(presets) {
|
||||||
var list = document.getElementById("presetList");
|
window.RedditTweaks.presets.render(
|
||||||
list.innerHTML = "";
|
document.getElementById("presetList"),
|
||||||
for (var i = 0; i < presets.length; i++) {
|
presets,
|
||||||
(function (index) {
|
function (p) {
|
||||||
var p = presets[index];
|
|
||||||
var badge = document.createElement("span");
|
|
||||||
badge.className = "rt-preset-badge";
|
|
||||||
badge.style.background = p.bg;
|
|
||||||
badge.style.borderColor = p.border;
|
|
||||||
badge.style.color = p.text;
|
|
||||||
badge.textContent = "Aa";
|
|
||||||
badge.title = "Click to apply to light subreddit colors";
|
|
||||||
badge.addEventListener("click", function () {
|
|
||||||
setColorValue(document.getElementById("light.subredditBgColor"), p.bg);
|
setColorValue(document.getElementById("light.subredditBgColor"), p.bg);
|
||||||
setColorValue(document.getElementById("light.subredditBorderColor"), p.border);
|
setColorValue(document.getElementById("light.subredditBorderColor"), p.border);
|
||||||
setColorValue(document.getElementById("light.subredditTextColor"), p.text);
|
setColorValue(document.getElementById("light.subredditTextColor"), p.text);
|
||||||
closePicker();
|
closePicker();
|
||||||
saveFromControls();
|
saveFromControls();
|
||||||
});
|
},
|
||||||
|
function (index) {
|
||||||
var del = document.createElement("span");
|
window.RedditTweaks.presets.delete(index, renderPopupPresets);
|
||||||
del.className = "rt-preset-delete";
|
|
||||||
del.textContent = "\u00d7";
|
|
||||||
del.addEventListener("click", function (e) {
|
|
||||||
e.stopPropagation();
|
|
||||||
deletePopupPreset(index);
|
|
||||||
});
|
|
||||||
badge.appendChild(del);
|
|
||||||
list.appendChild(badge);
|
|
||||||
})(i);
|
|
||||||
}
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addPopupPreset() {
|
function addPopupPreset() {
|
||||||
var preset = {
|
window.RedditTweaks.presets.save(
|
||||||
|
{
|
||||||
bg: getColorValue(document.getElementById("light.subredditBgColor")),
|
bg: getColorValue(document.getElementById("light.subredditBgColor")),
|
||||||
border: getColorValue(document.getElementById("light.subredditBorderColor")),
|
border: getColorValue(document.getElementById("light.subredditBorderColor")),
|
||||||
text: getColorValue(document.getElementById("light.subredditTextColor")),
|
text: getColorValue(document.getElementById("light.subredditTextColor")),
|
||||||
};
|
},
|
||||||
var settings = await window.RedditTweaks.loadSettings();
|
renderPopupPresets
|
||||||
var presets = settings.colorPresets || [];
|
);
|
||||||
presets.push(preset);
|
|
||||||
settings.colorPresets = presets;
|
|
||||||
await window.RedditTweaks.saveSettings(settings);
|
|
||||||
renderPopupPresets(presets);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function deletePopupPreset(index) {
|
|
||||||
var settings = await window.RedditTweaks.loadSettings();
|
|
||||||
var presets = settings.colorPresets || [];
|
|
||||||
presets.splice(index, 1);
|
|
||||||
settings.colorPresets = presets;
|
|
||||||
await window.RedditTweaks.saveSettings(settings);
|
|
||||||
renderPopupPresets(presets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveFromControls() {
|
async function saveFromControls() {
|
||||||
|
|||||||
Reference in New Issue
Block a user