From 97b13b7c476a92412a0b28c0edf53c5bf8e83709 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 12 Sep 2026 20:58:28 +0000 Subject: [PATCH] refactor: move reply-context logic to commons.model; keep the Compose compiler in commons by measurement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the last two items of documented debt from the commons/commonsUI split. ParentNote (replyingDirectlyTo, isCommunityDefinition) and ReplyContext are pure thread logic used by ViewModels, so they move from the misleading `ui.note` package to `commons.model`, next to ThreadAssembler, together with their tests and the StubCache fixture that shared the package. No `ui.*` package is left in commons. The `ui.note` composables in commonsUI gain explicit imports; consumer imports rewritten. Whether commons still needs the Compose compiler plugin was an open question; it is now measured. With compiler reports on the three GUI modules and full, non-incremental recompiles in both configurations, removing the plugin flips composable parameters typed with unannotated commons classes (TopFilter, TorSettings, ProfileBroadcastStatus, ScheduledPost, EmojiPackState, ...) from runtime-stable to unstable: 20→28 in commonsUI, 33→65 in desktopApp, 90→149 in amethyst. The plugin stays; the numbers are recorded in the build file, ARCHITECTURE.md and the split plan so the question is not reopened. Verified: JVM compiles for commons, commonsUI, cli, desktopApp; Android debug compiles for nappletHost and amethyst; commons/commonsUI/cli/desktopApp JVM test suites. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01N56KzPSYiN5edMRamvKEgD --- .../amethyst/ui/note/NoteCompose.kt | 4 +-- .../amethyst/ui/note/types/Text.kt | 2 +- .../amethyst/ui/note/types/ZapPoll.kt | 2 +- commons/ARCHITECTURE.md | 14 +++++---- commons/build.gradle.kts | 10 +++++-- commons/plans/2026-09-12-commons-ui-split.md | 30 +++++++++++++++---- .../commons/{ui/note => model}/ParentNote.kt | 2 +- .../{ui/note => model}/ReplyContext.kt | 2 +- .../{ui/note => model}/ParentNoteTest.kt | 2 +- .../{ui/note => model}/ReplyContextTest.kt | 2 +- .../commons/{ui/note => model}/StubCache.kt | 2 +- .../amethyst/desktop/ui/FeedScreen.kt | 2 +- .../amethyst/desktop/ui/note/NoteCard.kt | 2 +- 13 files changed, 51 insertions(+), 25 deletions(-) rename commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/{ui/note => model}/ParentNote.kt (98%) rename commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/{ui/note => model}/ReplyContext.kt (97%) rename commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/{ui/note => model}/ParentNoteTest.kt (99%) rename commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/{ui/note => model}/ReplyContextTest.kt (98%) rename commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/{ui/note => model}/StubCache.kt (98%) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt index 5a52fc7e9e..8c13a982ad 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/NoteCompose.kt @@ -61,8 +61,10 @@ import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.model.AddressableNote import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.concord.ConcordChannel +import com.vitorpamplona.amethyst.commons.model.isCommunityDefinition import com.vitorpamplona.amethyst.commons.model.nip28PublicChats.PublicChatChannel import com.vitorpamplona.amethyst.commons.model.nip29RelayGroups.RelayGroupChannel +import com.vitorpamplona.amethyst.commons.model.replyingDirectlyTo import com.vitorpamplona.amethyst.commons.model.textNoteModifications import com.vitorpamplona.amethyst.commons.resources.Res import com.vitorpamplona.amethyst.commons.resources.approve @@ -78,8 +80,6 @@ import com.vitorpamplona.amethyst.commons.ui.note.QuietMark import com.vitorpamplona.amethyst.commons.ui.note.RenderCashuMint import com.vitorpamplona.amethyst.commons.ui.note.RenderFedimint import com.vitorpamplona.amethyst.commons.ui.note.RenderMintRecommendation -import com.vitorpamplona.amethyst.commons.ui.note.isCommunityDefinition -import com.vitorpamplona.amethyst.commons.ui.note.replyingDirectlyTo import com.vitorpamplona.amethyst.commons.ui.state.produceCachedStateAsync import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.service.relayClient.reqCommand.channel.observeChannelPicture diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Text.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Text.kt index ee51d3ba73..ea5f987dc2 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Text.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/Text.kt @@ -35,10 +35,10 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextOverflow import com.vitorpamplona.amethyst.commons.model.EmptyTagList import com.vitorpamplona.amethyst.commons.model.Note +import com.vitorpamplona.amethyst.commons.model.replyingDirectlyTo import com.vitorpamplona.amethyst.commons.model.toImmutableListOfLists import com.vitorpamplona.amethyst.commons.ui.components.GenericLoadable import com.vitorpamplona.amethyst.commons.ui.note.ReplyToLabel -import com.vitorpamplona.amethyst.commons.ui.note.replyingDirectlyTo import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.ui.components.SensitivityWarning import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/ZapPoll.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/ZapPoll.kt index d0dfbbe2d4..0706b83d8b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/ZapPoll.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/ZapPoll.kt @@ -34,8 +34,8 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.style.TextOverflow import com.vitorpamplona.amethyst.commons.model.EmptyTagList import com.vitorpamplona.amethyst.commons.model.Note +import com.vitorpamplona.amethyst.commons.model.replyingDirectlyTo import com.vitorpamplona.amethyst.commons.model.toImmutableListOfLists -import com.vitorpamplona.amethyst.commons.ui.note.replyingDirectlyTo import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.ui.components.SensitivityWarning import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer diff --git a/commons/ARCHITECTURE.md b/commons/ARCHITECTURE.md index 20e0b37e8f..bda85c11a5 100644 --- a/commons/ARCHITECTURE.md +++ b/commons/ARCHITECTURE.md @@ -75,7 +75,7 @@ in `commonsUI`, under the same package. ### Domain models & data | Package | UI? | Purpose | |----------------|-----|---------| -| `model` | no¹ | Core domain types (`Note`, `User`, `Channel`), thread assembly, and per-NIP event model extensions in `model/nipNN…` subpackages. `model/cache` holds the in-memory event-store interfaces + `UserMetadataCache`. `model/account`, `model/observables`. The largest package; keep it organized by NIP. | +| `model` | no¹ | Core domain types (`Note`, `User`, `Channel`), thread assembly (`ThreadAssembler`, `ThreadLevelCalculator`, `ReplyContext`, `replyingDirectlyTo`), and per-NIP event model extensions in `model/nipNN…` subpackages. `model/cache` holds the in-memory event-store interfaces + `UserMetadataCache`. `model/account`, `model/observables`. The largest package; keep it organized by NIP. | | `defaults` | no | Static bootstrap data (default relays, channels). | ¹ `model` uses only the `@Stable`/`@Immutable` runtime annotations — CLI-safe. @@ -126,7 +126,7 @@ type (`LazyListState`, `TextFieldValue`, `TextFieldState`) goes to `commonsUI`. ### UI (Compose — lives in **`commonsUI`**) | Package | UI? | Purpose | |----------------|-----|---------| -| `ui` | yes | **Cross-cutting** shared composables only, organized by area: `ui/components`, `ui/theme`, `ui/signing`, `ui/thread`, `ui/note`, `ui/richtext`, `ui/search`, `ui/notifications`, `ui/screens`, `ui/layouts`, `ui/markdown`, `ui/privacylock`, plus Compose helpers in `ui/state` (cached-state) and `ui/text` (TextField extensions). Feature-specific UI lives in `/ui`, **not** here. **Exception:** `ui/note/ParentNote`+`ReplyContext` (pure thread logic) stay in *this* module. The `ui/feeds` composables (`NewPostsChip`, `RelayReachMarker`…) are in `commonsUI`; the feed DAL that used to share that package now lives in `feeds/` here. | +| `ui` | yes | **Cross-cutting** shared composables only, organized by area: `ui/components`, `ui/theme`, `ui/signing`, `ui/thread`, `ui/note`, `ui/richtext`, `ui/search`, `ui/notifications`, `ui/screens`, `ui/layouts`, `ui/markdown`, `ui/privacylock`, plus Compose helpers in `ui/state` (cached-state) and `ui/text` (TextField extensions). Feature-specific UI lives in `/ui`, **not** here. Nothing under `ui.*` lives in *this* module any more: the feed DAL that used to sit in `ui/feeds` is now `feeds/`, and the reply-context logic that sat in `ui/note` (`replyingDirectlyTo`, `ReplyContext`) is now in `model/` next to `ThreadAssembler`. | | `nip23LongContent` | yes | Long-form (NIP-23) article UI: `nip23LongContent/ui/article` (reader) + `…/ui/editor` (authoring). The model lives in `model/nip23LongContent` (here). | | `icons` | yes | `ImageVector` icon definitions + builders, Material Symbols codepoints, the icon-font glyph tables. | | `hashtags` | yes | Custom hashtag `ImageVector`s. | @@ -232,9 +232,13 @@ compiles: `commonMain` → `jvmAndroid` → platform-specific. See These are intentionally *documented*, not silently tolerated. Fix opportunistically. -- **`ui/note` in `commons`** still hosts `ParentNote` + `ReplyContext` (pure - thread logic used by ViewModels) under a `ui.*` package name. Candidate for - `model/` when touched next. +- **`commons` applies the Compose *compiler* plugin without declaring any + composable.** Deliberate, not debt: the plugin's `@StabilityInferred` + stamps are what keep unannotated commons classes stable from the apps' + point of view. Measured on full recompiles (2026-09-12): without it, + unstable composable params go 20→28 in `commonsUI`, 33→65 in `desktopApp`, + 90→149 in `amethyst`. Don't remove it; if a class must be stable for a + hot path, annotate it explicitly as well. - **Same package tree in two modules.** Intentional (zero-import-churn split), but it means a package's module is not visible from its name. Rule of thumb: if it imports Compose UI it is in `commonsUI`; check §2 when unsure. diff --git a/commons/build.gradle.kts b/commons/build.gradle.kts index 0f86f0bdac..1c044bed5d 100644 --- a/commons/build.gradle.kts +++ b/commons/build.gradle.kts @@ -11,9 +11,13 @@ plugins { alias(libs.plugins.androidKotlinMultiplatformLibrary) // Kept on purpose even though no @Composable lives here anymore: the // Compose compiler stamps @StabilityInferred on every class it compiles, - // which is what lets the apps' composables treat commons models (Note, - // User, states) as stable/skippable. Dropping it would silently make all - // of them "unstable" from the UI's point of view. + // which is what lets the apps' composables treat unannotated commons + // classes (TopFilter, TorSettings, ProfileBroadcastStatus, …) as stable. + // Measured with Compose compiler reports on full recompiles (2026-09-12): + // removing this plugin turns 20→28 composable params unstable in + // :commonsUI, 33→65 in :desktopApp and 90→149 in :amethyst. Inference is + // also self-maintaining, unlike hand-written @Immutable annotations that + // silently lie once a `var` is added — so this stays. alias(libs.plugins.jetbrainsComposeCompiler) alias(libs.plugins.serialization) } diff --git a/commons/plans/2026-09-12-commons-ui-split.md b/commons/plans/2026-09-12-commons-ui-split.md index 01895d86fc..e6deffb590 100644 --- a/commons/plans/2026-09-12-commons-ui-split.md +++ b/commons/plans/2026-09-12-commons-ui-split.md @@ -84,11 +84,29 @@ next to the `:commons` ones on macOS. existing `feeds` package, next to `feeds/custom`). Consumer imports rewritten. - **Chess composables moved to `nip64Chess/ui`** in `commonsUI`; the logic stays in `commons/…/nip64Chess/`. +- **`ui/note/ParentNote` + `ReplyContext` moved to `commons/…/model/`** next to + `ThreadAssembler` (with the `StubCache` test fixture). No `ui.*` package is + left in `commons`. -## Open +## Decided: `commons` keeps the Compose compiler plugin + +Measured rather than guessed. With `composeCompiler { reportsDestination }` +on the three GUI modules and full (non-incremental, `--rerun`) compiles in +both configurations, removing the plugin from `commons` flips composable +parameters typed with unannotated commons classes from runtime-stable to +unstable: + +| Module | unstable params, plugin on | plugin off | +|---|---|---| +| `commonsUI` | 20 | 28 | +| `desktopApp` | 33 | 65 | +| `amethyst` (fdroidDebug) | 90 | 149 | + +The classes involved (`TopFilter`, `TorSettings`, `TorServiceStatus`, +`ProfileBroadcastStatus`, `ScheduledPost`, `EmojiPackState`, +`Nip65RelayListState`, `PendingAuthApproval`, `UserSearchEngine`, …) are +all-`val` classes with no `@Stable`/`@Immutable` annotation; the plugin infers +their stability and keeps inferring it as they evolve. Hand-annotating them +would reproduce today's result but rot silently the first time a `var` is +added, so the plugin stays. Recorded in `commons/build.gradle.kts`. -- `commons` still applies the Compose *compiler* plugin on purpose (stability - inference for its model classes as seen from the apps' composables). - Revisit if a `runtime-annotation`-only setup proves sufficient. -- `ui/note/ParentNote` + `ReplyContext` remain in `commons` under a `ui.*` - package name (pure logic; candidate for `model/`). diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ParentNote.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/ParentNote.kt similarity index 98% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ParentNote.kt rename to commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/ParentNote.kt index 3c1df2afd3..b377e6f4f4 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ParentNote.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/ParentNote.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.commons.ui.note +package com.vitorpamplona.amethyst.commons.model import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.cache.ICacheProvider diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyContext.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/ReplyContext.kt similarity index 97% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyContext.kt rename to commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/ReplyContext.kt index 92ea646504..7dca3be782 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyContext.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/ReplyContext.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.commons.ui.note +package com.vitorpamplona.amethyst.commons.model import com.vitorpamplona.amethyst.commons.model.cache.ICacheProvider import com.vitorpamplona.quartz.nip10Notes.BaseThreadedEvent diff --git a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ParentNoteTest.kt b/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/model/ParentNoteTest.kt similarity index 99% rename from commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ParentNoteTest.kt rename to commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/model/ParentNoteTest.kt index 5331ac9187..117c5d525d 100644 --- a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ParentNoteTest.kt +++ b/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/model/ParentNoteTest.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.commons.ui.note +package com.vitorpamplona.amethyst.commons.model import com.vitorpamplona.amethyst.commons.model.AddressableNote import com.vitorpamplona.amethyst.commons.model.Note diff --git a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyContextTest.kt b/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/model/ReplyContextTest.kt similarity index 98% rename from commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyContextTest.kt rename to commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/model/ReplyContextTest.kt index 88c2a79113..afdd0077e2 100644 --- a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyContextTest.kt +++ b/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/model/ReplyContextTest.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.commons.ui.note +package com.vitorpamplona.amethyst.commons.model import com.vitorpamplona.amethyst.commons.model.Note import com.vitorpamplona.amethyst.commons.model.User diff --git a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/note/StubCache.kt b/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/model/StubCache.kt similarity index 98% rename from commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/note/StubCache.kt rename to commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/model/StubCache.kt index 4785fd6f75..1ab49b42eb 100644 --- a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/note/StubCache.kt +++ b/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/model/StubCache.kt @@ -18,7 +18,7 @@ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -package com.vitorpamplona.amethyst.commons.ui.note +package com.vitorpamplona.amethyst.commons.model import com.vitorpamplona.amethyst.commons.model.AddressableNote import com.vitorpamplona.amethyst.commons.model.Channel diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/FeedScreen.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/FeedScreen.kt index 134de2c694..9ae8b96117 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/FeedScreen.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/FeedScreen.kt @@ -92,6 +92,7 @@ import com.vitorpamplona.amethyst.commons.feeds.FeedState import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.model.Note +import com.vitorpamplona.amethyst.commons.model.ReplyContext import com.vitorpamplona.amethyst.commons.model.nip02FollowList.FollowAction import com.vitorpamplona.amethyst.commons.model.nip05DnsIdentifiers.namecoin.NamecoinResolveState import com.vitorpamplona.amethyst.commons.model.nip25Reactions.ReactionAction @@ -110,7 +111,6 @@ import com.vitorpamplona.amethyst.commons.ui.feeds.NewPostsChip import com.vitorpamplona.amethyst.commons.ui.feeds.StickToTopOnPrepend import com.vitorpamplona.amethyst.commons.ui.feeds.rememberNewPostsChipState import com.vitorpamplona.amethyst.commons.ui.layouts.GenericRepostLayout -import com.vitorpamplona.amethyst.commons.ui.note.ReplyContext import com.vitorpamplona.amethyst.commons.util.toTimeAgo import com.vitorpamplona.amethyst.desktop.DesktopPreferences import com.vitorpamplona.amethyst.desktop.SearchHistoryStore diff --git a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/note/NoteCard.kt b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/note/NoteCard.kt index 27d6ae795a..54b5971176 100644 --- a/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/note/NoteCard.kt +++ b/desktopApp/src/jvmMain/kotlin/com/vitorpamplona/amethyst/desktop/ui/note/NoteCard.kt @@ -56,12 +56,12 @@ import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage import com.vitorpamplona.amethyst.commons.model.EmptyTagList import com.vitorpamplona.amethyst.commons.model.ImmutableListOfLists +import com.vitorpamplona.amethyst.commons.model.ReplyContext import com.vitorpamplona.amethyst.commons.relayClient.event.EventFinderFilterAssemblerSubscription import com.vitorpamplona.amethyst.commons.relayClient.user.UserFinderFilterAssemblerSubscription import com.vitorpamplona.amethyst.commons.richtext.CachedRichTextParser import com.vitorpamplona.amethyst.commons.richtext.RichTextParser import com.vitorpamplona.amethyst.commons.richtext.UrlParser -import com.vitorpamplona.amethyst.commons.ui.note.ReplyContext import com.vitorpamplona.amethyst.commons.ui.note.ReplyToLabel import com.vitorpamplona.amethyst.desktop.cache.DesktopLocalCache import com.vitorpamplona.amethyst.desktop.ui.components.ToggleableTimeAgoText