mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-09-14 00:55:08 +00:00
fix(library): name nested directory entries, and read the schema.org spelling
Two things a real bookshelf turned up. **A nested directory read "Untitled section".** `Library.kt` reuses `PublicationSectionRow`, whose title `when` knew only the publication kinds, so a directory listing another directory fell to `else -> null` and then to the section placeholder -- both the wrong name and the wrong noun. A directory lists whatever it likes, so the row now names the library kinds too, learning resources and piece indexes included. **A learning resource read as its `d` slug.** `title()` looked only at `title`, but publishers that tag themselves `type: LearningResource` follow schema.org and emit `name`/`description`. Both spellings are accepted now, `title`/`summary` winning where an event carries both, so nothing that renders today changes. Not a bug, checked and left alone: Laeserin's directory shows `my-book-collection` because that event carries no `title` *or* `name` at all -- the `d` fallback is the right answer there. Verified on device against the same two events that showed the defects: entry 3 of `my-book-collection` now reads "nostr" instead of "Untitled section", and the German resource reads "Caesar-Scheibe - 30 Buchstaben: A-Z plus Ae Oe Ue ss" instead of "17xu8qb7". Two tests added for the vocabulary split, including the precedence case; LibraryEventsTest 11/11 green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wwk8tDEaEvsNoGbtrjZavz
This commit is contained in:
co-authored by
Claude Opus 5
parent
9ba5a7663c
commit
6099ed6d03
@@ -73,6 +73,9 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||
import com.vitorpamplona.amethyst.ui.stringRes
|
||||
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
||||
import com.vitorpamplona.amethyst.ui.theme.grayText
|
||||
import com.vitorpamplona.quartz.experimental.library.BlossomPieceIndexEvent
|
||||
import com.vitorpamplona.quartz.experimental.library.BookshelfDirectoryEvent
|
||||
import com.vitorpamplona.quartz.experimental.library.LearningResourceEvent
|
||||
import com.vitorpamplona.quartz.experimental.publications.PublicationContentEvent
|
||||
import com.vitorpamplona.quartz.experimental.publications.PublicationIndexEvent
|
||||
import com.vitorpamplona.quartz.experimental.publications.PublicationSectionRef
|
||||
@@ -335,6 +338,12 @@ private fun ObservedSectionRow(
|
||||
is PublicationContentEvent -> event.titleOrIdentifier()
|
||||
is LongTextNoteEvent -> event.title()
|
||||
is WikiNoteEvent -> event.title()
|
||||
// A bookshelf directory lists whatever it likes, including another directory, so the
|
||||
// row has to name the library kinds too -- otherwise a nested entry falls through to
|
||||
// the section placeholder and reads "Untitled section", which it is not.
|
||||
is BookshelfDirectoryEvent -> event.titleOrIdentifier()
|
||||
is LearningResourceEvent -> event.titleOrIdentifier()
|
||||
is BlossomPieceIndexEvent -> event.titleOrIdentifier()
|
||||
else -> null
|
||||
} ?: ref.title
|
||||
|
||||
|
||||
+10
-2
@@ -33,6 +33,8 @@ import com.vitorpamplona.quartz.nip23LongContent.tags.ImageTag
|
||||
import com.vitorpamplona.quartz.nip23LongContent.tags.SummaryTag
|
||||
import com.vitorpamplona.quartz.nip23LongContent.tags.TitleTag
|
||||
import com.vitorpamplona.quartz.nip50Search.SearchableEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.DescriptionTag
|
||||
import com.vitorpamplona.quartz.nip51Lists.tags.NameTag
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
|
||||
/**
|
||||
@@ -55,9 +57,15 @@ class LearningResourceEvent(
|
||||
SearchableEvent {
|
||||
override fun indexableContent() = listOfNotNull(title(), summary(), content).joinToString("\n")
|
||||
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse)
|
||||
/**
|
||||
* Publishers split on which vocabulary they use: most emit `title`/`summary`, but the ones
|
||||
* that tag themselves `type: LearningResource` follow schema.org and emit `name`/`description`
|
||||
* instead. Reading only the first spelling left those rendering as their `d` slug, so both are
|
||||
* accepted with `title`/`summary` winning where an event carries both.
|
||||
*/
|
||||
fun title() = tags.firstNotNullOfOrNull(TitleTag::parse) ?: tags.firstNotNullOfOrNull(NameTag::parse)
|
||||
|
||||
fun summary() = tags.firstNotNullOfOrNull(SummaryTag::parse)
|
||||
fun summary() = tags.firstNotNullOfOrNull(SummaryTag::parse) ?: tags.firstNotNullOfOrNull(DescriptionTag::parse)
|
||||
|
||||
fun image() = tags.firstNotNullOfOrNull(ImageTag::parse)
|
||||
|
||||
|
||||
+47
@@ -65,6 +65,53 @@ class LibraryEventsTest {
|
||||
assertEquals("Intro to Nostr\nThe basics.\nLesson one.", event.indexableContent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aLearningResourceReadsTheSchemaOrgNameAndDescription() {
|
||||
// The `type: LearningResource` publishers emit schema.org's spelling. Shape taken from a
|
||||
// real event (`4fa5d1c4...`, d=17xu8qb7), which rendered as its slug before this.
|
||||
val event =
|
||||
LearningResourceEvent(
|
||||
"id",
|
||||
author,
|
||||
0L,
|
||||
arrayOf(
|
||||
arrayOf("d", "17xu8qb7"),
|
||||
arrayOf("type", "LearningResource"),
|
||||
arrayOf("name", "Caesar-Scheibe"),
|
||||
arrayOf("description", "Eine Anleitung."),
|
||||
),
|
||||
"Body.",
|
||||
"sig",
|
||||
)
|
||||
|
||||
assertEquals("Caesar-Scheibe", event.title())
|
||||
assertEquals("Eine Anleitung.", event.summary())
|
||||
assertEquals("Caesar-Scheibe", event.titleOrIdentifier())
|
||||
assertEquals("Caesar-Scheibe\nEine Anleitung.\nBody.", event.indexableContent())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun titleAndSummaryWinOverNameAndDescription() {
|
||||
val event =
|
||||
LearningResourceEvent(
|
||||
"id",
|
||||
author,
|
||||
0L,
|
||||
arrayOf(
|
||||
arrayOf("d", "both"),
|
||||
arrayOf("title", "Preferred"),
|
||||
arrayOf("name", "Ignored"),
|
||||
arrayOf("summary", "Preferred summary."),
|
||||
arrayOf("description", "Ignored description."),
|
||||
),
|
||||
"",
|
||||
"sig",
|
||||
)
|
||||
|
||||
assertEquals("Preferred", event.title())
|
||||
assertEquals("Preferred summary.", event.summary())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun aLearningResourceFallsBackToItsIdentifier() {
|
||||
val event = LearningResourceEvent("id", author, 0L, arrayOf(arrayOf("d", "untitled-course")), "", "sig")
|
||||
|
||||
Reference in New Issue
Block a user