diff options
Diffstat (limited to 'shared/src/commonMain/kotlin/dev/serrahima/lluerna/domain/Model.kt')
| -rw-r--r-- | shared/src/commonMain/kotlin/dev/serrahima/lluerna/domain/Model.kt | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/shared/src/commonMain/kotlin/dev/serrahima/lluerna/domain/Model.kt b/shared/src/commonMain/kotlin/dev/serrahima/lluerna/domain/Model.kt new file mode 100644 index 0000000..680bfcf --- /dev/null +++ b/shared/src/commonMain/kotlin/dev/serrahima/lluerna/domain/Model.kt @@ -0,0 +1,74 @@ +package dev.serrahima.lluerna.domain + +/** + * the protocol-neutral domain model. + * + * nothing in here knows about `site.standard.*` (or any other lexicon). the + * source adapters map raw records into these types; the ui renders these types. + * that boundary is what makes a future bluesky/wafrn adapter additive. + * + * this is a starter: it will grow as we build the feed. + */ + +/** which protocol a piece of content came from. */ +enum class Protocol { STANDARD_SITE } + +/** a publication (ours) or a foreign actor, depending on [protocol]. */ +data class Author( + /** did, or an at-uri for a publication. */ + val id: String, + /** a handle or publication slug, if known. */ + val handle: String? = null, + val name: String, + val avatarUrl: String? = null, + /** canonical web url, if the author has one. */ + val url: String? = null, + val protocol: Protocol = Protocol.STANDARD_SITE, +) + +/** + * a post body is a sum type: either our rich native content, or opaque foreign + * content we can only render textually (a future bluesky/wafrn post). + */ +sealed interface PostBody { + data class Native(val blocks: List<Block>) : PostBody + data class Foreign(val text: String, val facets: List<Facet> = emptyList()) : PostBody +} + +/** a block of native rich content. will grow (images, embeds, ...). */ +sealed interface Block { + data class Paragraph(val text: String, val facets: List<Facet> = emptyList()) : Block + data class Header(val level: Int, val text: String) : Block +} + +/** an inline annotation over a byte range of a text. */ +sealed interface Facet { + val byteStart: Int + val byteEnd: Int + + data class Link(override val byteStart: Int, override val byteEnd: Int, val uri: String) : Facet + data class Mention(override val byteStart: Int, override val byteEnd: Int, val uri: String) : Facet + data class Bold(override val byteStart: Int, override val byteEnd: Int) : Facet + data class Italic(override val byteStart: Int, override val byteEnd: Int) : Facet + data class Header(override val byteStart: Int, override val byteEnd: Int, val level: Int) : Facet +} + +/** + * a post in the feed. [parents] is the chain toward the root, newest-nearest + * first; the tumblr dedup + "tags from every post in the chain" logic both + * operate on it. + */ +data class Post( + val uri: String, + val cid: String, + val author: Author, + val body: PostBody, + /** plaintext fallback (site.standard.document.textContent). */ + val plaintext: String, + val tags: List<String> = emptyList(), + val publishedAt: Long, + val updatedAt: Long? = null, + val parents: List<Post> = emptyList(), + /** at-uri of the post this is an addition to, if it is a reblog-with-addition. */ + val replyTarget: String? = null, +) |
