diff --git a/src/assets/helene.png b/src/assets/helene.png new file mode 100644 index 0000000..15cf717 Binary files /dev/null and b/src/assets/helene.png differ diff --git a/src/components/blog/BlogEntry.svelte b/src/components/blog/BlogEntry.svelte index 8f425d5..230f87a 100644 --- a/src/components/blog/BlogEntry.svelte +++ b/src/components/blog/BlogEntry.svelte @@ -16,6 +16,7 @@ import { renderDisplayName } from '$lib/util/html' import { routeTo } from '$lib/router.svelte' import { quoteReferenceOf, quotesCountOf } from '$lib/util/status' + import { accountForStatus } from '$lib/util/heleneposting' import { isoDate, longDate, stampDate } from '$lib/util/time' import { extractYouTubeVideoIds } from '$lib/util/youtube' import Avatar from '../common/Avatar.svelte' @@ -42,12 +43,12 @@ let { status, onupdate, ondelete, compact = false, longFormDate = false }: Props = $props() - const { endpoints, session } = useAppServices() + const { endpoints, session, preferences } = useAppServices() /** The status actually being displayed; a boost renders its target. */ const entry = $derived(status.reblog ?? status) const booster = $derived(status.reblog ? status.account : null) - const author = $derived(entry.account) + const author = $derived(accountForStatus(entry, preferences.heleneposting)) const authorName = $derived(renderDisplayName(displayNameOf(author), author.emojis)) const handle = $derived(fullHandle(author, session.host)) const permalink = $derived(`#/blog/${entry.id}`) diff --git a/src/components/blog/BlogEntry.test.ts b/src/components/blog/BlogEntry.test.ts index 515ceda..dbe4df5 100644 --- a/src/components/blog/BlogEntry.test.ts +++ b/src/components/blog/BlogEntry.test.ts @@ -1,7 +1,7 @@ import { fireEvent, render, waitFor } from '@testing-library/svelte' import { describe, expect, it, vi } from 'vitest' import { APP_SERVICES } from '$lib/app-services' -import { account, session, status, testServices } from '$test/fixtures' +import { account, preferences, session, status, testServices } from '$test/fixtures' import BlogEntry from './BlogEntry.svelte' function renderEntry(overrides: Parameters[0]) { @@ -67,6 +67,40 @@ describe('BlogEntry MFM rendering', () => { }) }) +describe('BlogEntry Heleneposting', () => { + it('replaces only the displayed author name and avatar when enabled', () => { + const original = account({ + acct: 'actual-author', + display_name: 'Actual Author', + avatar: 'https://example.test/actual.png', + avatar_static: 'https://example.test/actual.png', + }) + const services = testServices({ + preferences: preferences({ heleneposting: true }), + }) + const view = render(BlogEntry, { + props: { + status: status({ + account: original, + content: '

Signed through HTML
— Helene

', + }), + }, + context: new Map([[APP_SERVICES, services]]), + }) + + expect(view.container.querySelector('.blog-entry-author')).toHaveAttribute( + 'href', + '#/@actual-author', + ) + expect(view.queryByText('Actual Author')).not.toBeInTheDocument() + expect(view.container.querySelector('.blog-entry-avatar img')).toHaveAttribute( + 'src', + expect.stringContaining('helene'), + ) + expect(view.getByText('@actual-author@example.test')).toBeInTheDocument() + }) +}) + describe('BlogEntry quote posts', () => { it('renders a Pleroma quote and links to quote composition and the quote list', () => { const quoted = status({ diff --git a/src/components/blog/QuoteCard.svelte b/src/components/blog/QuoteCard.svelte index 477dafc..466d364 100644 --- a/src/components/blog/QuoteCard.svelte +++ b/src/components/blog/QuoteCard.svelte @@ -6,6 +6,7 @@ import { useAppServices } from '$lib/app-services' import { displayNameOf, fullHandle, profilePath } from '$lib/util/profile' import { stampDate } from '$lib/util/time' + import { accountForStatus } from '$lib/util/heleneposting' import Avatar from '../common/Avatar.svelte' import EmojiText from '../common/EmojiText.svelte' import MfmContent from '../common/MfmContent.svelte' @@ -18,12 +19,13 @@ } let { quote }: Props = $props() - const { endpoints, session } = useAppServices() + const { endpoints, session, preferences } = useAppServices() let loadedStatus = $state(untrack(() => quote.status)) let loading = $state(false) let loadError = $state(false) let loadGeneration = 0 const status = $derived((loadedStatus ?? quote.status)?.reblog ?? loadedStatus ?? quote.status) + const author = $derived(status ? accountForStatus(status, preferences.heleneposting) : null) $effect(() => { const supplied = quote.status @@ -69,10 +71,13 @@

Loading quoted entry…

{:else if status}
- + diff --git a/src/components/chrome/NotificationToasts.svelte b/src/components/chrome/NotificationToasts.svelte index 6dd79e8..840451f 100644 --- a/src/components/chrome/NotificationToasts.svelte +++ b/src/components/chrome/NotificationToasts.svelte @@ -7,6 +7,8 @@ import type { ApiClient } from '$lib/api/client' import type { Notification } from '$lib/api/types' import { useAppServices } from '$lib/app-services' + import { accountForNotification } from '$lib/util/heleneposting' + import { displayNameOf } from '$lib/util/profile' import { NOTIFICATION_DISMISS_AFTER_MS, NOTIFICATION_POLL_INTERVAL_MS, @@ -35,7 +37,7 @@ maxToasts = 4, }: Props = $props() - const { endpoints, session } = useAppServices() + const { endpoints, session, preferences } = useAppServices() const tracker = new NotificationTracker() const dismissTimers = new Map() @@ -141,6 +143,7 @@