Browse Source

bug-fixes

gitcitadel
Silberengel 2 weeks ago
parent
commit
171ef52acf
  1. 6
      assets/controllers/color_scheme_controller.js
  2. 1
      assets/controllers/comment_reply_controller.js
  3. 16
      assets/controllers/hello_controller.js
  4. 25
      assets/controllers/magazine_hierarchy_editor_controller.js
  5. 2
      assets/controllers/user_highlight_tooltip_controller.js
  6. 13
      assets/theme/default/theme-dark.css
  7. 34
      assets/theme/default/theme.css
  8. 14
      src/Repository/ArticleRepository.php
  9. 15
      src/Repository/UserEntityRepository.php
  10. 9
      src/Service/ArticleWorkflowService.php
  11. 11
      src/Service/MetadataRetrievalException.php
  12. 9
      src/Service/NostrKeyHelper.php

6
assets/controllers/color_scheme_controller.js

@ -7,7 +7,6 @@ export default class extends Controller {
connect() { connect() {
this.link = document.getElementById('theme-magazine-stylesheet'); this.link = document.getElementById('theme-magazine-stylesheet');
this._syncFromDom();
this._refreshIcons(); this._refreshIcons();
} }
@ -50,11 +49,6 @@ export default class extends Controller {
this._refreshIcons(); this._refreshIcons();
} }
_syncFromDom() {
/* Link href was set by inline script; icons follow current scheme. */
this._refreshIcons();
}
_refreshIcons() { _refreshIcons() {
const dark = document.documentElement.getAttribute('data-color-scheme') === 'dark'; const dark = document.documentElement.getAttribute('data-color-scheme') === 'dark';
if (this.hasMoonTarget) { if (this.hasMoonTarget) {

1
assets/controllers/comment_reply_controller.js

@ -11,7 +11,6 @@ export default class extends Controller {
csrf: String, csrf: String,
expectedCoordinate: String, expectedCoordinate: String,
articleEventId: String, articleEventId: String,
fragmentUrl: String,
refreshAfter: { type: Boolean, default: true }, refreshAfter: { type: Boolean, default: true },
expectedTags: Array, expectedTags: Array,
parentKind: Number, parentKind: Number,

16
assets/controllers/hello_controller.js

@ -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';
}
}

25
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_-]+$/; const DTAG_PATTERN = /^[a-zA-Z0-9_-]+$/;
export default class MagazineHierarchyEditorController extends Controller { export default class MagazineHierarchyEditorController extends Controller {
static targets = ['status', 'publishBtn', 'node', 'nodes', 'newNodeTemplate', 'aRowTemplate']; static targets = ['status', 'publishBtn', 'nodes', 'newNodeTemplate', 'aRowTemplate'];
static values = { static values = {
publishUrl: String, publishUrl: String,
@ -1241,29 +1241,6 @@ function lineMatches30040Child(line, ownerHexLower, childD) {
return parts.identifier.trim() === 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 * @param {string} coord
* @returns {{ kind: string, pubkey: string, identifier: string } | null} * @returns {{ kind: string, pubkey: string, identifier: string } | null}

2
assets/controllers/user_highlight_tooltip_controller.js

@ -74,7 +74,7 @@ export default class extends Controller {
const m = const m =
t.nodeType === 1 t.nodeType === 1
? /** @type {Element} */ (t).closest('mark.user-highlight__marker[data-hl]') ? /** @type {Element} */ (t).closest('mark.user-highlight__marker[data-hl]')
: null; : t.parentElement?.closest('mark.user-highlight__marker[data-hl]') ?? null;
if (m) { if (m) {
const to = e.relatedTarget; const to = e.relatedTarget;
if (to && (m.contains(to) || (to instanceof Node && this.tip.contains(/** @type {Node} */(to))))) { if (to && (m.contains(to) || (to instanceof Node && this.tip.contains(/** @type {Node} */(to))))) {

13
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) { html[data-color-scheme="dark"] .home-aside-highlights__item-inner:has(.home-aside-highlights__hit:focus-visible) {
background: #2f2b27; 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);
}

34
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: #f4f1ee;
--color-bg-light: #e8e4df; --color-bg-light: #e8e4df;
--color-bg-primary: #e0dbd4;
/* Text */
--color-text: #2a2a2a; --color-text: #2a2a2a;
--color-text-mid: #3d3a36; --color-text-mid: #3d3a36;
--color-text-contrast: #f4f1ee; --color-text-contrast: #f4f1ee; /* cream on filled surfaces (buttons, badges) */
--brand-color: black; /* 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: #3a342f;
--color-link-hover: #1a1a1a; --color-link-hover: #1a1a1a;
--color-focus-ring: #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); --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%);
} }

14
src/Repository/ArticleRepository.php

@ -212,20 +212,6 @@ class ArticleRepository extends ServiceEntityRepository
->getOneOrNullResult(); ->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 public function findByPubkeyPaginated(string $pubkey, int $limit, int $offset): array
{ {
return $this->createQueryBuilder('a') return $this->createQueryBuilder('a')

15
src/Repository/UserEntityRepository.php

@ -4,25 +4,12 @@ namespace App\Repository;
use App\Entity\User; use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry; use Doctrine\Persistence\ManagerRegistry;
class UserEntityRepository extends ServiceEntityRepository class UserEntityRepository extends ServiceEntityRepository
{ {
public function __construct(ManagerRegistry $registry, private readonly EntityManagerInterface $entityManager) public function __construct(ManagerRegistry $registry)
{ {
parent::__construct($registry, User::class); 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;
}
} }

9
src/Service/ArticleWorkflowService.php

@ -1,9 +0,0 @@
<?php
namespace App\Service;
class ArticleWorkflowService
{
}

11
src/Service/MetadataRetrievalException.php

@ -1,11 +0,0 @@
<?php
namespace App\Service;
class MetadataRetrievalException extends \Exception
{
public function __construct(string $message = "Failed to retrieve metadata", int $code = 0, ?\Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}

9
src/Service/NostrKeyHelper.php

@ -29,13 +29,4 @@ final readonly class NostrKeyHelper
return $this->key->convertPublicKeyToBech32($key); return $this->key->convertPublicKeyToBech32($key);
} }
public function convertPrivateKeyToBech32(string $key): string
{
return $this->key->convertPrivateKeyToBech32($key);
}
public function generatePrivateKey(): string
{
return $this->key->generatePrivateKey();
}
} }

Loading…
Cancel
Save