diff --git a/assets/controllers/color_scheme_controller.js b/assets/controllers/color_scheme_controller.js index 65779fb..7479026 100644 --- a/assets/controllers/color_scheme_controller.js +++ b/assets/controllers/color_scheme_controller.js @@ -7,7 +7,6 @@ export default class extends Controller { connect() { this.link = document.getElementById('theme-magazine-stylesheet'); - this._syncFromDom(); this._refreshIcons(); } @@ -50,11 +49,6 @@ export default class extends Controller { this._refreshIcons(); } - _syncFromDom() { - /* Link href was set by inline script; icons follow current scheme. */ - this._refreshIcons(); - } - _refreshIcons() { const dark = document.documentElement.getAttribute('data-color-scheme') === 'dark'; if (this.hasMoonTarget) { diff --git a/assets/controllers/comment_reply_controller.js b/assets/controllers/comment_reply_controller.js index 7d0b62f..3465ed3 100644 --- a/assets/controllers/comment_reply_controller.js +++ b/assets/controllers/comment_reply_controller.js @@ -11,7 +11,6 @@ export default class extends Controller { csrf: String, expectedCoordinate: String, articleEventId: String, - fragmentUrl: String, refreshAfter: { type: Boolean, default: true }, expectedTags: Array, parentKind: Number, diff --git a/assets/controllers/hello_controller.js b/assets/controllers/hello_controller.js deleted file mode 100644 index e847027..0000000 --- a/assets/controllers/hello_controller.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Controller } from '@hotwired/stimulus'; - -/* - * This is an example Stimulus controller! - * - * Any element with a data-controller="hello" attribute will cause - * this controller to be executed. The name "hello" comes from the filename: - * hello_controller.js -> "hello" - * - * Delete this file or adapt it for your use! - */ -export default class extends Controller { - connect() { - this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js'; - } -} diff --git a/assets/controllers/magazine_hierarchy_editor_controller.js b/assets/controllers/magazine_hierarchy_editor_controller.js index 332fe79..17a3560 100644 --- a/assets/controllers/magazine_hierarchy_editor_controller.js +++ b/assets/controllers/magazine_hierarchy_editor_controller.js @@ -15,7 +15,7 @@ const LONGFORM_KINDS = new Set([KIND_LONGFORM, KIND_LONGFORM_DRAFT, KIND_WIKI]); const DTAG_PATTERN = /^[a-zA-Z0-9_-]+$/; export default class MagazineHierarchyEditorController extends Controller { - static targets = ['status', 'publishBtn', 'node', 'nodes', 'newNodeTemplate', 'aRowTemplate']; + static targets = ['status', 'publishBtn', 'nodes', 'newNodeTemplate', 'aRowTemplate']; static values = { publishUrl: String, @@ -1241,29 +1241,6 @@ function lineMatches30040Child(line, ownerHexLower, childD) { return parts.identifier.trim() === childD; } -/** - * @param {HTMLElement} el - * @returns {{ dTag: string, title: string, summary: string, content: string, aText: string, preserved: unknown[] }} - */ -function readFieldsForBuild(el) { - const dTag = readDTag(el); - const title = el.querySelector('[data-magazine-hierarchy-editor-target="title"]')?.value ?? ''; - const summary = el.querySelector('[data-magazine-hierarchy-editor-target="summary"]')?.value ?? ''; - const content = el.querySelector('[data-magazine-hierarchy-editor-target="content"]')?.value ?? ''; - const aText = readJoinedALinesFromNode(el); - const preservedRaw = el.querySelector('[data-magazine-hierarchy-editor-target="preservedJson"]')?.value ?? '[]'; - let preserved; - try { - preserved = JSON.parse(preservedRaw); - } catch { - throw new Error(`Invalid preserved-tags JSON for #d ${dTag}.`); - } - if (!Array.isArray(preserved)) { - throw new Error(`Preserved tags must be a JSON array for #d ${dTag}.`); - } - return { dTag, title, summary, content, aText, preserved }; -} - /** * @param {string} coord * @returns {{ kind: string, pubkey: string, identifier: string } | null} diff --git a/assets/controllers/user_highlight_tooltip_controller.js b/assets/controllers/user_highlight_tooltip_controller.js index a2b94e7..30aad46 100644 --- a/assets/controllers/user_highlight_tooltip_controller.js +++ b/assets/controllers/user_highlight_tooltip_controller.js @@ -74,7 +74,7 @@ export default class extends Controller { const m = t.nodeType === 1 ? /** @type {Element} */ (t).closest('mark.user-highlight__marker[data-hl]') - : null; + : t.parentElement?.closest('mark.user-highlight__marker[data-hl]') ?? null; if (m) { const to = e.relatedTarget; if (to && (m.contains(to) || (to instanceof Node && this.tip.contains(/** @type {Node} */(to))))) { diff --git a/assets/theme/default/theme-dark.css b/assets/theme/default/theme-dark.css index 96341ed..1b2eb8b 100644 --- a/assets/theme/default/theme-dark.css +++ b/assets/theme/default/theme-dark.css @@ -60,3 +60,16 @@ html[data-color-scheme="dark"] .home-aside-highlights__item-inner:hover, html[data-color-scheme="dark"] .home-aside-highlights__item-inner:has(.home-aside-highlights__hit:focus-visible) { background: #2f2b27; } + +/* Reply toasts: base article.css uses hardcoded light greens/reds; override for dark. */ +html[data-color-scheme="dark"] .reply-toast--success { + border-color: #3a8a55; + background: color-mix(in srgb, var(--color-bg) 70%, #2f7a4b 30%); + color: var(--color-text); +} + +html[data-color-scheme="dark"] .reply-toast--error { + border-color: #b03030; + background: color-mix(in srgb, var(--color-bg) 70%, #a12b2b 30%); + color: var(--color-text); +} diff --git a/assets/theme/default/theme.css b/assets/theme/default/theme.css index 7eef11b..dfaad81 100644 --- a/assets/theme/default/theme.css +++ b/assets/theme/default/theme.css @@ -1,12 +1,40 @@ -[data-theme="light"] { +/* + * imwald / magazine light color scheme. + * Loaded when data-color-scheme="light". Mirror of theme-dark.css: selector must match + * html[data-color-scheme="..."] because data-theme is set to the magazine name ("imwald"), + * not "light". Previously used [data-theme="light"] which never matched. + */ +html[data-color-scheme="light"] { + /* Backgrounds */ --color-bg: #f4f1ee; --color-bg-light: #e8e4df; + --color-bg-primary: #e0dbd4; + /* Text */ --color-text: #2a2a2a; --color-text-mid: #3d3a36; - --color-text-contrast: #f4f1ee; - --brand-color: black; + --color-text-contrast: #f4f1ee; /* cream on filled surfaces (buttons, badges) */ + /* Accent greens tuned for ≥4.5:1 on #f4f1ee / #e8e4df: + primary #3d5c38 → 6.8:1 on cream ✓ + secondary #4d6847 → 5.7:1 on cream ✓ */ + --color-primary: #3d5c38; + --color-secondary: #4d6847; + --color-primary-strong: #2e4729; + --color-border: #c8c3bd; + --color-border-soft: #d9d4cf; + /* Links */ --color-link: #3a342f; --color-link-hover: #1a1a1a; --color-focus-ring: #1a1a1a; + /* Footer */ + --color-footer-bg: var(--color-bg-light); + --color-footer-text: var(--color-text); + --color-footer-link: var(--color-secondary); + /* Misc */ --color-shadow: color-mix(in srgb, var(--color-text) 10%, transparent); + --brand-color: black; + --accent-color: var(--color-secondary); + --color-highlight-mark-fg: #1a1a1a; + /* Reading pane: light mix produces a warm off-white (not pure white) */ + --article-reading-pane-bg: color-mix(in srgb, var(--color-bg) 70%, #ffffff 30%); + --article-reading-prose-color: color-mix(in srgb, var(--color-text-mid) 35%, var(--color-text) 65%); } diff --git a/src/Repository/ArticleRepository.php b/src/Repository/ArticleRepository.php index 4b40839..3374e10 100644 --- a/src/Repository/ArticleRepository.php +++ b/src/Repository/ArticleRepository.php @@ -212,20 +212,6 @@ class ArticleRepository extends ServiceEntityRepository ->getOneOrNullResult(); } - /** - * Find articles by author's public key - */ - public function findByPubkey(string $pubkey, int $limit = 25): array - { - return $this->createQueryBuilder('a') - ->where('a.pubkey = :pubkey') - ->setParameter('pubkey', $pubkey) - ->orderBy('a.createdAt', 'DESC') - ->setMaxResults($limit) - ->getQuery() - ->getResult(); - } - public function findByPubkeyPaginated(string $pubkey, int $limit, int $offset): array { return $this->createQueryBuilder('a') diff --git a/src/Repository/UserEntityRepository.php b/src/Repository/UserEntityRepository.php index 0cdac14..e1e5492 100644 --- a/src/Repository/UserEntityRepository.php +++ b/src/Repository/UserEntityRepository.php @@ -4,25 +4,12 @@ namespace App\Repository; use App\Entity\User; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; -use Doctrine\ORM\EntityManagerInterface; use Doctrine\Persistence\ManagerRegistry; class UserEntityRepository extends ServiceEntityRepository { - public function __construct(ManagerRegistry $registry, private readonly EntityManagerInterface $entityManager) + public function __construct(ManagerRegistry $registry) { parent::__construct($registry, User::class); } - public function findOrCreateByUniqueField(User $user): User - { - $entity = $this->findOneBy(['npub' => $user->getNpub()]); - - if ($entity !== null) { - $user->setId($entity->getId()); - } else { - $this->entityManager->persist($user); - } - - return $user; - } } diff --git a/src/Service/ArticleWorkflowService.php b/src/Service/ArticleWorkflowService.php deleted file mode 100644 index f781c1a..0000000 --- a/src/Service/ArticleWorkflowService.php +++ /dev/null @@ -1,9 +0,0 @@ -key->convertPublicKeyToBech32($key); } - public function convertPrivateKeyToBech32(string $key): string - { - return $this->key->convertPrivateKeyToBech32($key); - } - - public function generatePrivateKey(): string - { - return $this->key->generatePrivateKey(); - } }