From a87222c51f6e76cd70ae945067511d19f283da98 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 12 Sep 2026 16:26:59 +0000 Subject: [PATCH] refactor: split Compose UI out of commons into a new commonsUI module `:commons` is on the CLI classpath, yet it declared Compose UI, Coil, Compose resources, markdown and desktop Compose as dependencies, dragging ~40 MB of UI/Skiko jars into every `amy` distribution. This moves every Compose-dependent file into a new KMP module, `:commonsUI`, that `api`-depends on `:commons`; `:commons` keeps only the Compose runtime (stability annotations + snapshot state) and lifecycle-viewmodel. Files keep their `com.vitorpamplona.amethyst.commons.*` packages, so the split is a build-graph boundary and no consumer import changed. 236 files were `git mv`'d (composables, icons, robohash, theme, Coil fetchers, the `@Composable` relay-client entry points, `composeResources`, and the tests that exercise them). Two headless files needed surgery instead of a move: `GalleryParser` lost a vestigial foundation `@OptIn`, and the `LocalPrivacyLockState`/`lockStateFor` CompositionLocal accessor moved out of `PrivacyLockState` into its own commonsUI file. The feed DAL under `ui/feeds` and `ui/note/ParentNote`+`ReplyContext` stay in `commons` because ViewModels depend on them. `amethyst`, `desktopApp`, `nappletHost` (NappletWebContract serves the shell from composeResources) and `benchmark` now depend on `:commonsUI`; `cli`, `geode` and `marmotBench` do not. commons' androidMain gains an explicit androidx.core KTX dep it previously got transitively through Compose UI. CI, crowdin, the icon-font tools and the escaping hook point at the new composeResources location; CLAUDE.md, commons/ARCHITECTURE.md, a new commonsUI/ARCHITECTURE.md, CONTRIBUTING, BUILDING and the affected skills document the boundary. A plan doc under commons/plans records the classification method and follow-ups. Verified: JVM compiles for commons, commonsUI, cli, desktopApp; Android debug compiles for nappletHost and amethyst; commons/commonsUI/cli JVM test suites; both verifyKmpPurity gates; the cli runtime classpath no longer resolves Compose UI, material3, Skiko or Coil. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01N56KzPSYiN5edMRamvKEgD --- .claude/CLAUDE.md | 68 ++-- .claude/hooks/compose_escaping_check.py | 4 +- .../references/extraction-recipe.md | 4 +- .claude/skills/compose-expert/SKILL.md | 14 +- .../skills/find-missing-translations/SKILL.md | 28 +- .claude/skills/kotlin-multiplatform/SKILL.md | 2 +- .claude/skills/relay-client/SKILL.md | 2 +- .github/workflows/build.yml | 12 +- .github/workflows/create-release.yml | 11 +- .github/workflows/crowdin.yml | 8 +- BUILDING.md | 13 +- CONTRIBUTING-WITH-AI.md | 10 +- CONTRIBUTING.md | 13 +- amethyst/build.gradle.kts | 1 + benchmark/build.gradle.kts | 1 + commons/ARCHITECTURE.md | 121 +++++--- commons/build.gradle.kts | 119 ++----- commons/plans/2026-09-12-commons-ui-split.md | 89 ++++++ commons/plans/README.md | 7 +- .../commons/privacylock/PrivacyLockState.kt | 23 -- .../commons/richtext/GalleryParser.kt | 2 - commonsUI/.gitignore | 1 + commonsUI/ARCHITECTURE.md | 64 ++++ commonsUI/build.gradle.kts | 293 ++++++++++++++++++ commonsUI/consumer-rules.pro | 0 commonsUI/proguard-rules.pro | 24 ++ .../ui/text/TextFieldValueExtensionTest.kt | 0 commonsUI/src/androidMain/AndroidManifest.xml | 4 + .../service/image/CoilImageBridge.android.kt | 0 .../composeResources/files/napplet/shell.html | 0 .../composeResources/files/napplet/shim.js | 0 .../composeResources/font/amethyst_icons.ttf | Bin .../font/material_symbols_outlined.ttf | Bin .../values-ar-rSA/strings.xml | 0 .../values-bn-rBD/strings.xml | 0 .../composeResources/values-cs/strings.xml | 0 .../values-de-rDE/strings.xml | 0 .../composeResources/values-de/strings.xml | 0 .../values-el-rGR/strings.xml | 0 .../values-en-rGB/strings.xml | 0 .../values-eo-rUY/strings.xml | 0 .../composeResources/values-eo/strings.xml | 0 .../values-es-rES/strings.xml | 0 .../values-es-rMX/strings.xml | 0 .../values-es-rUS/strings.xml | 0 .../composeResources/values-es/strings.xml | 0 .../values-fa-rIR/strings.xml | 0 .../composeResources/values-fa/strings.xml | 0 .../values-fi-rFI/strings.xml | 0 .../values-fr-rCA/strings.xml | 0 .../values-fr-rFR/strings.xml | 0 .../composeResources/values-fr/strings.xml | 0 .../values-hi-rIN/strings.xml | 0 .../values-hu-rHU/strings.xml | 0 .../values-in-rID/strings.xml | 0 .../composeResources/values-in/strings.xml | 0 .../values-it-rIT/strings.xml | 0 .../values-ja-rJP/strings.xml | 0 .../composeResources/values-ja/strings.xml | 0 .../values-ko-rKR/strings.xml | 0 .../values-lv-rLV/strings.xml | 0 .../values-nl-rBE/strings.xml | 0 .../values-nl-rNL/strings.xml | 0 .../composeResources/values-nl/strings.xml | 0 .../values-pl-rPL/strings.xml | 0 .../values-pt-rBR/strings.xml | 0 .../values-pt-rPT/strings.xml | 0 .../values-ru-rRU/strings.xml | 0 .../values-ru-rUA/strings.xml | 0 .../composeResources/values-ru/strings.xml | 0 .../values-sl-rSI/strings.xml | 0 .../values-sr-rSP/strings.xml | 0 .../values-sv-rSE/strings.xml | 0 .../composeResources/values-sw/strings.xml | 0 .../values-ta-rIN/strings.xml | 0 .../composeResources/values-ta/strings.xml | 0 .../values-th-rTH/strings.xml | 0 .../composeResources/values-th/strings.xml | 0 .../values-tr-rTR/strings.xml | 0 .../composeResources/values-tr/strings.xml | 0 .../values-uk-rUA/strings.xml | 0 .../composeResources/values-uk/strings.xml | 0 .../values-uz-rUZ/strings.xml | 0 .../values-vi-rVN/strings.xml | 0 .../values-zh-rCN/strings.xml | 0 .../values-zh-rHK/strings.xml | 0 .../values-zh-rSG/strings.xml | 0 .../values-zh-rTW/strings.xml | 0 .../composeResources/values-zh/strings.xml | 0 .../composeResources/values/strings.xml | 0 .../amethyst/commons/audio/AudioVisualizer.kt | 0 .../amethyst/commons/audio/SpectrumCanvas.kt | 0 .../commons/audio/VisualizerRegistry.kt | 0 .../commons/audio/VisualizerRenderer.kt | 0 .../commons/audio/renderers/AuroraRenderer.kt | 0 .../commons/audio/renderers/BarsRenderer.kt | 0 .../commons/audio/renderers/OffRenderer.kt | 0 .../commons/audio/renderers/RadialRenderer.kt | 0 .../commons/audio/renderers/StaticRenderer.kt | 0 .../commons/audio/renderers/WavesRenderer.kt | 0 .../commons/favorites/FavoriteAppIcon.kt | 0 .../amethyst/commons/hashtags/Amethyst.kt | 0 .../amethyst/commons/hashtags/Btc.kt | 0 .../amethyst/commons/hashtags/Cashu.kt | 0 .../amethyst/commons/hashtags/Coffee.kt | 0 .../commons/hashtags/CustomHashTagIcons.kt | 0 .../amethyst/commons/hashtags/Flowerstr.kt | 0 .../amethyst/commons/hashtags/Footstr.kt | 0 .../amethyst/commons/hashtags/Gamestr.kt | 0 .../amethyst/commons/hashtags/Grownostr.kt | 0 .../amethyst/commons/hashtags/Lightning.kt | 0 .../amethyst/commons/hashtags/Mate.kt | 0 .../amethyst/commons/hashtags/Nostr.kt | 0 .../amethyst/commons/hashtags/Plebs.kt | 0 .../amethyst/commons/hashtags/Skull.kt | 0 .../amethyst/commons/hashtags/Tunestr.kt | 0 .../amethyst/commons/hashtags/Weed.kt | 0 .../amethyst/commons/hashtags/Zap.kt | 0 .../amethyst/commons/icons/Bookmark.kt | 0 .../amethyst/commons/icons/Following.kt | 0 .../amethyst/commons/icons/Like.kt | 0 .../amethyst/commons/icons/Liked.kt | 0 .../amethyst/commons/icons/Reply.kt | 0 .../amethyst/commons/icons/Repost.kt | 0 .../amethyst/commons/icons/Reposted.kt | 0 .../amethyst/commons/icons/Search.kt | 0 .../amethyst/commons/icons/Share.kt | 0 .../amethyst/commons/icons/Zap.kt | 0 .../amethyst/commons/icons/ZapSplit.kt | 0 .../commons/icons/symbols/AmethystIcons.kt | 0 .../icons/symbols/AmethystIconsFont.kt | 0 .../amethyst/commons/icons/symbols/Icon.kt | 0 .../commons/icons/symbols/MaterialSymbol.kt | 0 .../icons/symbols/MaterialSymbolPainter.kt | 0 .../commons/icons/symbols/MaterialSymbols.kt | 0 .../icons/symbols/MaterialSymbolsDefaults.kt | 0 .../icons/symbols/MaterialSymbolsFont.kt | 0 .../nip30CustomEmojis/EmojiSuggestionState.kt | 0 .../commons/napplet/NappletWebContract.kt | 0 .../ui/article/ArticleHeader.kt | 0 .../ui/article/TableOfContents.kt | 0 .../ui/editor/MarkdownEditorState.kt | 0 .../ui/editor/MarkdownToolbar.kt | 0 .../ui/editor/MetadataPanel.kt | 0 .../ui/ShowEmojiSuggestionList.kt | 0 .../commons/nip34Git/ui/CodeHighlighter.kt | 0 .../ui/StreamSystemCard.kt | 0 .../amethyst/commons/nip64Chess/ChessBoard.kt | 0 .../nip64Chess/ChessBroadcastBanner.kt | 0 .../commons/nip64Chess/ChessGameViewer.kt | 0 .../commons/nip64Chess/ChessLobbyCards.kt | 0 .../commons/nip64Chess/ChessPieceVectors.kt | 0 .../commons/nip64Chess/ChessPlayerChip.kt | 0 .../commons/nip64Chess/ChessSyncBanner.kt | 0 .../nip64Chess/InteractiveChessBoard.kt | 0 .../commons/nip64Chess/LiveChessGame.kt | 0 .../commons/nip64Chess/MoveNavigator.kt | 0 .../commons/nip64Chess/PGNMetadata.kt | 0 .../ui/EditNicknameDialog.kt | 0 .../privacylock/LocalPrivacyLockState.kt | 45 +++ .../profile/ui/ProfileBroadcastBanner.kt | 0 .../relayClient/auth/AuthApprovalBanner.kt | 0 .../CommunityFilterAssemblerSubscription.kt | 0 .../EventFinderFilterAssemblerSubscription.kt | 0 .../RepositoryFilterAssemblerSubscription.kt | 0 .../UserProfileFilterAssemblerSubscription.kt | 0 .../KeyDataSourceSubscription.kt | 0 ...LifecycleAwareKeyDataSourceSubscription.kt | 0 .../user/UserFinderSubscription.kt | 0 .../relayClient/user/UserMetadataObservers.kt | 0 .../relays/health/ui/UnhealthyRelayBanner.kt | 0 .../relays/health/ui/UnhealthyRelayRow.kt | 0 .../commons/robohash/CachedRobohash.kt | 0 .../commons/robohash/RobohashAssembler.kt | 0 .../commons/robohash/parts/Accessory0Seven.kt | 0 .../commons/robohash/parts/Accessory1Nose.kt | 0 .../robohash/parts/Accessory2HornRed.kt | 0 .../robohash/parts/Accessory3Button.kt | 0 .../robohash/parts/Accessory4Satellite.kt | 0 .../robohash/parts/Accessory5Mustache.kt | 0 .../commons/robohash/parts/Accessory6Hat.kt | 0 .../robohash/parts/Accessory7Antenna.kt | 0 .../commons/robohash/parts/Accessory8Brush.kt | 0 .../commons/robohash/parts/Accessory9Horn.kt | 0 .../commons/robohash/parts/Body0Trooper.kt | 0 .../commons/robohash/parts/Body1Thin.kt | 0 .../commons/robohash/parts/Body2Thinnest.kt | 0 .../commons/robohash/parts/Body3Front.kt | 0 .../commons/robohash/parts/Body4Round.kt | 0 .../commons/robohash/parts/Body5Neck.kt | 0 .../commons/robohash/parts/Body6Ironman.kt | 0 .../robohash/parts/Body7Neckthinner.kt | 0 .../commons/robohash/parts/Body8Big.kt | 0 .../commons/robohash/parts/Body9Huge.kt | 0 .../commons/robohash/parts/Eyes0Squint.kt | 0 .../commons/robohash/parts/Eyes1Round.kt | 0 .../commons/robohash/parts/Eyes2Single.kt | 0 .../commons/robohash/parts/Eyes3Scott.kt | 0 .../robohash/parts/Eyes4Roundsingle.kt | 0 .../commons/robohash/parts/Eyes5Roundsmall.kt | 0 .../commons/robohash/parts/Eyes6Walle.kt | 0 .../commons/robohash/parts/Eyes7Bar.kt | 0 .../commons/robohash/parts/Eyes8Smallbar.kt | 0 .../commons/robohash/parts/Eyes9Shield.kt | 0 .../commons/robohash/parts/Face0C3po.kt | 0 .../commons/robohash/parts/Face1Rock.kt | 0 .../commons/robohash/parts/Face2Long.kt | 0 .../commons/robohash/parts/Face3Oval.kt | 0 .../commons/robohash/parts/Face4Cylinder.kt | 0 .../commons/robohash/parts/Face5Baloon.kt | 0 .../commons/robohash/parts/Face6Triangle.kt | 0 .../commons/robohash/parts/Face7Bent.kt | 0 .../robohash/parts/Face8TriangleInv.kt | 0 .../commons/robohash/parts/Face9Square.kt | 0 .../commons/robohash/parts/Mouth0Horz.kt | 0 .../commons/robohash/parts/Mouth1Cylinder.kt | 0 .../commons/robohash/parts/Mouth2Teeth.kt | 0 .../commons/robohash/parts/Mouth3Grid.kt | 0 .../commons/robohash/parts/Mouth4Vert.kt | 0 .../commons/robohash/parts/Mouth5Midopen.kt | 0 .../commons/robohash/parts/Mouth6Cell.kt | 0 .../commons/robohash/parts/Mouth7Happy.kt | 0 .../commons/robohash/parts/Mouth8Buttons.kt | 0 .../commons/robohash/parts/Mouth9Closed.kt | 0 .../commons/service/image/Base64Fetcher.kt | 0 .../commons/service/image/BlurHashFetcher.kt | 0 .../commons/service/image/CoilImageBridge.kt | 0 .../commons/service/image/ThumbHashFetcher.kt | 0 .../amethyst/commons/ui/StringRes.kt | 0 .../commons/ui/components/ActionButtons.kt | 0 .../ui/components/BunkerHeartbeatIndicator.kt | 0 .../commons/ui/components/ClickableLinks.kt | 0 .../commons/ui/components/ClickableTexts.kt | 0 .../ui/components/ForwardingPainter.kt | 0 .../commons/ui/components/GenericLoadable.kt | 0 .../commons/ui/components/GlowingCard.kt | 0 .../commons/ui/components/LoadingAnimation.kt | 0 .../commons/ui/components/LoadingState.kt | 0 .../ui/components/Nip05OrPubkeyLine.kt | 0 .../commons/ui/components/RobohashImage.kt | 0 .../ui/components/ShimmerPlaceholder.kt | 0 .../ui/components/TranslationConfig.kt | 0 .../commons/ui/components/UserAvatar.kt | 0 .../commons/ui/components/UserSearchCard.kt | 0 .../ui/components/ZonedSwipeModifier.kt | 0 .../commons/ui/feeds/DmHistoryLoadingCard.kt | 0 .../amethyst/commons/ui/feeds/NewPostsChip.kt | 0 .../commons/ui/feeds/NewPostsChipState.kt | 0 .../commons/ui/feeds/RelayReachMarker.kt | 0 .../commons/ui/feeds/StickToTopOnPrepend.kt | 0 .../ui/layouts/DisappearingBarNestedScroll.kt | 0 .../ui/layouts/DisappearingBarState.kt | 0 .../commons/ui/layouts/GenericRepostLayout.kt | 0 .../commons/ui/layouts/PaddingMerge.kt | 0 .../amethyst/commons/ui/note/ActivityCard.kt | 0 .../amethyst/commons/ui/note/BirdexCard.kt | 0 .../commons/ui/note/CalendarCollectionCard.kt | 0 .../commons/ui/note/CalendarRsvpCard.kt | 0 .../commons/ui/note/CodeSnippetCard.kt | 0 .../commons/ui/note/CollapsedSpamNote.kt | 0 .../amethyst/commons/ui/note/EcashMintCard.kt | 0 .../amethyst/commons/ui/note/GitDiffView.kt | 0 .../amethyst/commons/ui/note/GitStatusPill.kt | 0 .../amethyst/commons/ui/note/HeaderPill.kt | 0 .../commons/ui/note/HighlightedQuote.kt | 0 .../amethyst/commons/ui/note/PodcastChips.kt | 0 .../commons/ui/note/PodcastSoundbites.kt | 0 .../commons/ui/note/PodcastValueSplits.kt | 0 .../amethyst/commons/ui/note/Ps1SaveCard.kt | 0 .../amethyst/commons/ui/note/QuietMark.kt | 0 .../commons/ui/note/RelayDiscoveryCard.kt | 0 .../amethyst/commons/ui/note/ReplyToLabel.kt | 0 .../amethyst/commons/ui/note/RoadEventCard.kt | 0 .../commons/ui/note/StaticWebsiteCard.kt | 0 .../commons/ui/notifications/CardFeedState.kt | 0 .../ui/privacylock/CredentialPrompter.kt | 0 .../ui/privacylock/IdleTimerModifier.kt | 0 .../commons/ui/privacylock/LockScreen.kt | 0 .../ui/privacylock/MessagesLockGate.kt | 0 .../commons/ui/privacylock/WalletLockGate.kt | 0 .../ui/richtext/CustomEmojiRenderer.kt | 0 .../commons/ui/richtext/HashtagIcons.kt | 0 .../amethyst/commons/ui/richtext/README.md | 0 .../ui/richtext/RichTextSegmentRenderer.kt | 0 .../commons/ui/richtext/RichTextViewer.kt | 0 .../commons/ui/screens/PlaceholderScreens.kt | 0 .../commons/ui/search/SearchCalendarPicker.kt | 0 .../commons/ui/search/SearchFieldSources.kt | 0 .../commons/ui/search/SearchFieldState.kt | 0 .../commons/ui/search/SearchPeoplePicker.kt | 0 .../commons/ui/search/SearchTokenStyles.kt | 0 .../ui/search/SearchTokenTransformation.kt | 0 .../commons/ui/search/TokenizedSearchField.kt | 0 .../commons/ui/signing/SigningAwareButton.kt | 0 .../commons/ui/signing/SigningState.kt | 0 .../commons/ui/signing/SigningStatusBar.kt | 0 .../commons/ui/state/AsyncCachedState.kt | 0 .../amethyst/commons/ui/state/CachedState.kt | 0 .../ui/text/TextFieldStateExtensions.kt | 0 .../ui/text/TextFieldValueExtensions.kt | 0 .../amethyst/commons/ui/text/UiThread.kt | 0 .../amethyst/commons/ui/theme/ChatTheme.kt | 0 .../amethyst/commons/ui/theme/Colors.kt | 0 .../amethyst/commons/ui/theme/NoteBorders.kt | 0 .../amethyst/commons/ui/theme/Sizes.kt | 0 .../commons/ui/theme/ThemeExtensions.kt | 0 .../commons/ui/thread/ThreadModifiers.kt | 0 .../commons/viewmodels/ChatNewMessageState.kt | 0 .../viewmodels/thread/LevelFeedViewModel.kt | 0 .../commons/audio/VisualizerRegistryTest.kt | 0 .../commons/napplet/NappletWebContractTest.kt | 0 .../commons/ui/feeds/RelayReachMarkerTest.kt | 0 .../search/SearchTokenTransformationTest.kt | 0 .../commons/ui/text/AppendSignatureTest.kt | 0 .../service/image/CoilImageBridge.ios.kt | 0 .../service/image/BlossomReadAuthFetcher.kt | 0 .../commons/ui/components/UrlPreviewState.kt | 0 .../commons/ui/markdown/RenderMarkdown.kt | 0 .../service/image/CoilImageBridge.jvm.kt | 0 .../napplet/NappletShellResourceTest.kt | 0 .../commons/ui/feeds/NewPostsChipStateTest.kt | 0 .../service/image/SkiaBitmapConverter.kt | 0 crowdin.yml | 4 +- desktopApp/build.gradle.kts | 3 +- nappletHost/build.gradle.kts | 4 +- settings.gradle.kts | 1 + tools/icon-font/README.md | 2 +- tools/ime-test/shim-events.mjs | 4 +- tools/material-symbols-subset/README.md | 4 +- tools/material-symbols-subset/subset.sh | 8 +- tools/strings-migrate/README.md | 2 +- tools/strings-migrate/migrate.py | 4 +- 332 files changed, 752 insertions(+), 267 deletions(-) create mode 100644 commons/plans/2026-09-12-commons-ui-split.md create mode 100644 commonsUI/.gitignore create mode 100644 commonsUI/ARCHITECTURE.md create mode 100644 commonsUI/build.gradle.kts create mode 100644 commonsUI/consumer-rules.pro create mode 100644 commonsUI/proguard-rules.pro rename {commons => commonsUI}/src/androidDeviceTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensionTest.kt (100%) create mode 100644 commonsUI/src/androidMain/AndroidManifest.xml rename {commons => commonsUI}/src/androidMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.android.kt (100%) rename {commons => commonsUI}/src/commonMain/composeResources/files/napplet/shell.html (100%) rename {commons => commonsUI}/src/commonMain/composeResources/files/napplet/shim.js (100%) rename {commons => commonsUI}/src/commonMain/composeResources/font/amethyst_icons.ttf (100%) rename {commons => commonsUI}/src/commonMain/composeResources/font/material_symbols_outlined.ttf (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-ar-rSA/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-bn-rBD/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-cs/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-de-rDE/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-de/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-el-rGR/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-en-rGB/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-eo-rUY/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-eo/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-es-rES/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-es-rMX/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-es-rUS/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-es/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-fa-rIR/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-fa/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-fi-rFI/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-fr-rCA/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-fr-rFR/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-fr/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-hi-rIN/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-hu-rHU/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-in-rID/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-in/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-it-rIT/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-ja-rJP/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-ja/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-ko-rKR/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-lv-rLV/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-nl-rBE/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-nl-rNL/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-nl/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-pl-rPL/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-pt-rBR/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-pt-rPT/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-ru-rRU/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-ru-rUA/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-ru/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-sl-rSI/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-sr-rSP/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-sv-rSE/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-sw/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-ta-rIN/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-ta/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-th-rTH/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-th/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-tr-rTR/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-tr/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-uk-rUA/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-uk/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-uz-rUZ/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-vi-rVN/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-zh-rCN/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-zh-rHK/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-zh-rSG/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-zh-rTW/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values-zh/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/composeResources/values/strings.xml (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/AudioVisualizer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/SpectrumCanvas.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistry.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRenderer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/AuroraRenderer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/BarsRenderer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/OffRenderer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/RadialRenderer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/StaticRenderer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/WavesRenderer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/favorites/FavoriteAppIcon.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Amethyst.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Btc.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Cashu.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Coffee.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/CustomHashTagIcons.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Flowerstr.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Footstr.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Gamestr.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Grownostr.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Lightning.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Mate.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Nostr.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Plebs.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Skull.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Tunestr.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Weed.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Zap.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Bookmark.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Following.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Like.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Liked.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reply.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Repost.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reposted.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Search.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Share.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Zap.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/ZapSplit.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIcons.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIconsFont.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/Icon.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbol.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolPainter.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsDefaults.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsFont.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/nip30CustomEmojis/EmojiSuggestionState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContract.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/ArticleHeader.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/TableOfContents.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownEditorState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownToolbar.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MetadataPanel.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip30CustomEmojis/ui/ShowEmojiSuggestionList.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip34Git/ui/CodeHighlighter.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip53LiveActivities/ui/StreamSystemCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBoard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBroadcastBanner.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessGameViewer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessLobbyCards.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPieceVectors.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPlayerChip.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessSyncBanner.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/InteractiveChessBoard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/LiveChessGame.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/MoveNavigator.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/PGNMetadata.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip85TrustedAssertions/ui/EditNicknameDialog.kt (100%) create mode 100644 commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/privacylock/LocalPrivacyLockState.kt rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/profile/ui/ProfileBroadcastBanner.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/auth/AuthApprovalBanner.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/communities/CommunityFilterAssemblerSubscription.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/event/EventFinderFilterAssemblerSubscription.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/gitRepo/RepositoryFilterAssemblerSubscription.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/profile/UserProfileFilterAssemblerSubscription.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/KeyDataSourceSubscription.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/LifecycleAwareKeyDataSourceSubscription.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserFinderSubscription.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserMetadataObservers.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayBanner.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayRow.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/CachedRobohash.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/RobohashAssembler.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory0Seven.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory1Nose.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory2HornRed.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory3Button.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory4Satellite.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory5Mustache.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory6Hat.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory7Antenna.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory8Brush.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory9Horn.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body0Trooper.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body1Thin.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body2Thinnest.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body3Front.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body4Round.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body5Neck.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body6Ironman.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body7Neckthinner.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body8Big.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body9Huge.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes0Squint.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes1Round.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes2Single.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes3Scott.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes4Roundsingle.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes5Roundsmall.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes6Walle.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes7Bar.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes8Smallbar.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes9Shield.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face0C3po.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face1Rock.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face2Long.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face3Oval.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face4Cylinder.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face5Baloon.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face6Triangle.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face7Bent.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face8TriangleInv.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face9Square.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth0Horz.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth1Cylinder.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth2Teeth.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth3Grid.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth4Vert.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth5Midopen.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth6Cell.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth7Happy.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth8Buttons.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth9Closed.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/Base64Fetcher.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlurHashFetcher.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/ThumbHashFetcher.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/StringRes.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ActionButtons.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/BunkerHeartbeatIndicator.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableLinks.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableTexts.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ForwardingPainter.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GenericLoadable.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GlowingCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingAnimation.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/Nip05OrPubkeyLine.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/RobohashImage.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ShimmerPlaceholder.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/TranslationConfig.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserAvatar.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserSearchCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ZonedSwipeModifier.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/DmHistoryLoadingCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChip.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarker.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/StickToTopOnPrepend.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarNestedScroll.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/GenericRepostLayout.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/PaddingMerge.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ActivityCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/BirdexCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarCollectionCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarRsvpCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CodeSnippetCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CollapsedSpamNote.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/EcashMintCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitDiffView.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitStatusPill.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HeaderPill.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HighlightedQuote.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastChips.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastSoundbites.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastValueSplits.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/Ps1SaveCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/QuietMark.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RelayDiscoveryCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyToLabel.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RoadEventCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/StaticWebsiteCard.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/notifications/CardFeedState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/CredentialPrompter.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/IdleTimerModifier.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/LockScreen.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/MessagesLockGate.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/WalletLockGate.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/CustomEmojiRenderer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/HashtagIcons.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/README.md (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextSegmentRenderer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextViewer.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/screens/PlaceholderScreens.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchCalendarPicker.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldSources.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchPeoplePicker.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenStyles.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformation.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/TokenizedSearchField.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningAwareButton.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningStatusBar.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/AsyncCachedState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/CachedState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldStateExtensions.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensions.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/UiThread.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ChatTheme.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Colors.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/NoteBorders.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Sizes.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ThemeExtensions.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/thread/ThreadModifiers.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/ChatNewMessageState.kt (100%) rename {commons => commonsUI}/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/thread/LevelFeedViewModel.kt (100%) rename {commons => commonsUI}/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistryTest.kt (100%) rename {commons => commonsUI}/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContractTest.kt (100%) rename {commons => commonsUI}/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarkerTest.kt (100%) rename {commons => commonsUI}/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformationTest.kt (100%) rename {commons => commonsUI}/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/AppendSignatureTest.kt (100%) rename {commons => commonsUI}/src/iosMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.ios.kt (100%) rename {commons => commonsUI}/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlossomReadAuthFetcher.kt (100%) rename {commons => commonsUI}/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UrlPreviewState.kt (100%) rename {commons => commonsUI}/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/markdown/RenderMarkdown.kt (100%) rename {commons => commonsUI}/src/jvmMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.jvm.kt (100%) rename {commons => commonsUI}/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletShellResourceTest.kt (100%) rename {commons => commonsUI}/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipStateTest.kt (100%) rename {commons => commonsUI}/src/skikoMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/SkiaBitmapConverter.kt (100%) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 7a15cb83cc..e0a074e5f7 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -3,7 +3,7 @@ ## Project Overview Amethyst is a Nostr Client for Android that was made for Android-only and has been slowly switching -over to a Kotlin Multiplatform project. The main modules are: `quartz`, `commons`, `amethyst`, +over to a Kotlin Multiplatform project. The main modules are: `quartz`, `commons`, `commonsUI`, `amethyst`, `desktopApp`, `cli`, plus the audio-rooms transport stack `quic` + `nestsClient`. Quartz should contain implementations of Nostr specifications and utilities to help implement them. Commons stores shared code between Amethyst Android (`amethyst`) and Amethyst Desktop (`desktopApp`). The Desktop @@ -48,11 +48,18 @@ amethyst/ │ ├── androidMain/ # Android-specific (crypto, storage) │ ├── jvmMain/ # Desktop JVM-specific │ └── iosMain/ # iOS-specific -├── commons/ # Shared UI components (convert to KMP) +├── commons/ # Shared HEADLESS layer (models, state, ViewModels, relay client) — CLI-safe │ └── src/ -│ ├── commonMain/ # Shared composables, icons, state -│ ├── androidMain/ # Android-specific UI utilities -│ └── jvmMain/ # Desktop-specific UI utilities +│ ├── commonMain/ # Domain models, state holders, ViewModels, services +│ ├── jvmAndroid/ # JVM-bound services shared by Android + Desktop +│ ├── androidMain/ # Android-specific actuals (Keystore, DataStore) +│ └── jvmMain/ # Desktop-specific actuals (keyring, upload pipeline) +├── commonsUI/ # Shared Compose UI on top of commons (composables, icons, theme, Coil, resources) +│ └── src/ +│ ├── commonMain/ # Shared composables, icons, theme, composeResources (strings/fonts) +│ ├── jvmAndroid/ # Markdown renderer, Coil OkHttp fetchers +│ ├── androidMain/ # Android Coil bridge +│ └── jvmMain/ # Desktop Coil bridge (+ skikoMain shared with iOS) ├── quic/ # Pure-Kotlin QUIC v1 + HTTP/3 + WebTransport (audio-rooms transport) │ └── src/ │ ├── commonMain/ # Protocol, frame/packet codecs, TLS state machine @@ -70,12 +77,20 @@ amethyst/ **Sharing Philosophy:** - `quartz/` = Nostr business logic, protocol, data (no UI) -- `commons/` = Shared code for every front end (Android, Desktop, iOS, and the - headless `cli`): domain models, state holders, ViewModels, the relay client, - shared services, **and** the Compose UI that ≥1 GUI front end renders. The - package taxonomy, the CLI-safe / UI boundary, and a "where does my code go?" - guide are documented in **`commons/ARCHITECTURE.md`** — read it before adding - a new package or dropping code into `commons`. +- `commons/` = Shared **headless** code for every front end (Android, Desktop, + iOS, and the headless `cli`): domain models, state holders, ViewModels, the + relay client, shared services. It may use the Compose *runtime* + (`@Stable`/`@Immutable`, snapshot state) but never Compose UI, Coil or + Compose resources — the build enforces this: `commons` has no such deps. +- `commonsUI/` = Shared **Compose UI** that ≥1 GUI front end renders + (composables, `ui/theme`, icons, robohash, Coil fetchers, markdown, the + `composeResources` strings/fonts and the generated `Res` class). Depends on + `commons` (as `api`); `cli` never depends on it. Files keep their + `com.vitorpamplona.amethyst.commons.*` packages — the split is a module + boundary, not a package rename. The package taxonomy, the CLI-safe / UI + boundary, and a "where does my code go?" guide are documented in + **`commons/ARCHITECTURE.md`** (+ `commonsUI/ARCHITECTURE.md`) — read them + before adding a new package or dropping code into either module. - `quic/` = Transport library (QUIC + HTTP/3 + WebTransport); reusable for any KMP project that needs MoQ. Has no Android-framework dependencies. - `nestsClient/` = MoQ + audio-rooms client; takes `:quic` as transport, @@ -88,7 +103,7 @@ amethyst/ - `amethyst/` & `desktopApp/` = Platform-native layouts and navigation - `cli/` = Thin assembly layer over `quartz/` + `commons/` (no new logic allowed). May also depend on `:geode` (for `amy serve`, which embeds the - standalone relay); never on `:amethyst` or `:desktopApp`. + standalone relay); never on `:commonsUI`, `:amethyst` or `:desktopApp`. **Plans per module:** design docs for new subsystems live in the owning module's `plans/YYYY-MM-DD-.md` (e.g. `cli/plans/`, `commons/plans/`). @@ -180,16 +195,19 @@ etc. instead of re-implementing them. **Share vs keep platform-native:** -- **Share** → `quartz/commonMain/` (business logic, data models, protocol) and - `commons/commonMain/` (major UI components, **ViewModels** under - `viewmodels/`, icons). ViewModels are platform-agnostic state + logic - (StateFlow/SharedFlow), so they belong in `commons`. +- **Share** → `quartz/commonMain/` (business logic, data models, protocol), + `commons/commonMain/` (**ViewModels** under `viewmodels/`, state holders, + relay client, services — headless) and `commonsUI/commonMain/` (major UI + components, icons, theme). ViewModels are platform-agnostic state + logic + (StateFlow/SharedFlow), so they belong in `commons`; anything that imports + `androidx.compose.ui`/`foundation`/`material3`, Coil, or `Res` belongs in + `commonsUI`. - **Keep native** → screen composables/scaffolding (Desktop `Window` vs Android `Activity`), navigation (sidebar vs bottom nav), platform interactions (gestures, keyboard shortcuts), system integrations (notifications, file pickers). -When extracting a composable: move it to `commons/commonMain/` (see +When extracting a composable: move it to `commonsUI/commonMain/` (see `/compose-expert`), add expect/actual for any platform behavior (see `/kotlin-multiplatform`), then point both Android and Desktop at the shared version. `quartz/` is protocol-only — no composables. @@ -216,7 +234,7 @@ version. `quartz/` is protocol-only — no composables. ## Dependency Licensing **MANDATORY whenever you introduce a new third-party dependency** — in *any* -module (`quartz`, `commons`, `amethyst`, `desktopApp`, `cli`, `quic`, +module (`quartz`, `commons`, `commonsUI`, `amethyst`, `desktopApp`, `cli`, `quic`, `nestsClient`, …), whether you add it to `gradle/libs.versions.toml` or to a module's `build.gradle.kts`: determine its license **before** wiring it in. Amethyst ships under the **MIT** license, so a copyleft dependency linked into a @@ -253,9 +271,9 @@ JVM). See `/kotlin-multiplatform` for the expect/actual and source-set patterns. ## Icons The Material Symbols font bundled at -`commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf` +`commonsUI/src/commonMain/composeResources/font/material_symbols_outlined.ttf` is a **subset** that only contains the glyphs referenced from -`commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt`. +`commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt`. **MANDATORY:** Whenever you add a new icon — i.e. introduce a `MaterialSymbol("\uXXXX")` codepoint that wasn't already referenced anywhere in @@ -274,21 +292,21 @@ regenerating. ### Amethyst's own icons are also a font -The icons in `commons/.../commons/icons/*.kt` (Like, Reply, Reposted, Zap, …) are +The icons in `commonsUI/.../commons/icons/*.kt` (Like, Reply, Reposted, Zap, …) are **also** compiled into a font, `composeResources/font/amethyst_icons.ttf`, and drawn as glyphs via `AmethystIconGlyph`. Drawing an `ImageVector` rasterises its paths into a per-instance cached layer, so a feed re-rasterised the same glyph once per card; a glyph is a blit from the shared text atlas. Measured: frame P90 **-10.7%**, overrun P90 **-17.4%** on the feed scroll benchmark. -**MANDATORY:** whenever you add or change an icon under `commons/.../commons/icons/`, +**MANDATORY:** whenever you add or change an icon under `commonsUI/.../commons/icons/`, regenerate the font *and* its codepoint table together: ```bash python3 tools/icon-font/build_icon_font.py \ - commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons \ - commons/src/commonMain/composeResources/font/amethyst_icons.ttf \ - commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIcons.kt + commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons \ + commonsUI/src/commonMain/composeResources/font/amethyst_icons.ttf \ + commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIcons.kt ``` Both outputs must be committed together: codepoints are assigned in filename order, diff --git a/.claude/hooks/compose_escaping_check.py b/.claude/hooks/compose_escaping_check.py index 1e83bf2e6f..cd9b054eef 100755 --- a/.claude/hooks/compose_escaping_check.py +++ b/.claude/hooks/compose_escaping_check.py @@ -21,7 +21,7 @@ that has to catch it. Repair with: python3 tools/strings-migrate/fix_escapes.py --no-unwrap-quotes \\ - commons/src/commonMain/composeResources + commonsUI/src/commonMain/composeResources `--no-unwrap-quotes` is mandatory on already-migrated files: escape conversion is idempotent, quote-unwrapping is not, and a second unwrap strips the real display @@ -77,7 +77,7 @@ def main() -> int: print( "\nRepair:\n" " python3 tools/strings-migrate/fix_escapes.py --no-unwrap-quotes \\\n" - " commons/src/commonMain/composeResources\n" + " commonsUI/src/commonMain/composeResources\n" "(--no-unwrap-quotes is mandatory on already-migrated files.)", file=out, ) diff --git a/.claude/skills/amy-expert/references/extraction-recipe.md b/.claude/skills/amy-expert/references/extraction-recipe.md index 2c3b2daa3f..f3edcc024f 100644 --- a/.claude/skills/amy-expert/references/extraction-recipe.md +++ b/.claude/skills/amy-expert/references/extraction-recipe.md @@ -47,7 +47,7 @@ Walk the imports. The usual offenders: | `android.util.Log` | Replace with `quartz` `PlatformLog` (already multiplatform). | | `android.graphics.Bitmap` | Almost never needed by Amy. Keep in Android and split the function. | | `android.net.Uri` | Replace with `kotlinx.io` path types or a plain `String`. | -| `androidx.compose.*` | Must stay out of `commons/commonMain` unless you're in a Compose-Multiplatform module. Amy doesn't depend on Compose. | +| `androidx.compose.*` | Compose UI (`ui`/`foundation`/`material3`), Coil and `Res` must stay out of `commons` entirely — they belong in `:commonsUI`, which Amy never depends on. Only the Compose *runtime* (`@Stable`, snapshot state) is allowed in `commons`. | ### Step 3 — Pick a migration strategy per dependency @@ -66,7 +66,7 @@ Walk the imports. The usual offenders: # Target location depends on what it is: # - Protocol → quartz/src/commonMain/kotlin/… # - Business logic → commons/src/commonMain/kotlin/… -# - UI → commons/src/commonMain/… (needs Compose Multiplatform) +# - UI → commonsUI/src/commonMain/… (needs Compose Multiplatform; never used by amy) git mv amethyst/src/main/java/com/.../FollowListManager.kt \ commons/src/commonMain/kotlin/com/.../FollowListManager.kt ``` diff --git a/.claude/skills/compose-expert/SKILL.md b/.claude/skills/compose-expert/SKILL.md index 6b85114ae8..e6eced37b1 100644 --- a/.claude/skills/compose-expert/SKILL.md +++ b/.claude/skills/compose-expert/SKILL.md @@ -24,7 +24,7 @@ Visual UI patterns for sharing composables across Android and Desktop. ## Philosophy: Share by Default -**Default to `commons/commonMain`** unless platform experts indicate otherwise. +**Default to `commonsUI/commonMain`** (shared composables live in `:commonsUI`, the Compose half of the shared layer; headless state/ViewModels stay in `:commons`) unless platform experts indicate otherwise. ### Always Share @@ -416,7 +416,7 @@ fun DataScreen(uiState: UiState) { } ``` -**Components** (all in `commons/commonMain`): +**Components** (all in `commonsUI/commonMain`): - `LoadingState` - Progress indicator + message - `EmptyState` - Empty message + optional refresh button - `ErrorState` - Error message + optional retry button @@ -527,12 +527,12 @@ fun FeedList(items: List) { | Task | Pattern | Location | |------|---------|----------| -| Reusable UI | State hoisting | commons/commonMain | +| Reusable UI | State hoisting | commonsUI/commonMain | | Simple state | remember { mutableStateOf() } | Composable scope | | Derived state | derivedStateOf { } | remember block | | Async → state | produceState { } | Composable function | -| Custom icons | roboBuilder + PathData | commons/icons | -| Loading/Error | LoadingState, ErrorState | commons/ui/components | +| Custom icons | roboBuilder + PathData | commonsUI/icons | +| Loading/Error | LoadingState, ErrorState | commonsUI/ui/components | | Theme colors | MaterialTheme.colorScheme | Any @Composable | | Navigation | Delegate to platform expert | amethyst/, desktopApp/ | @@ -540,7 +540,7 @@ fun FeedList(items: List) { ### Creating a Shared Component -1. Start in `commons/src/commonMain/kotlin/.../ui/components/` +1. Start in `commonsUI/src/commonMain/kotlin/.../ui/components/` 2. Use Material3 primitives only 3. Hoist state (parameters for data, callbacks for events) 4. Add modifier parameter @@ -551,7 +551,7 @@ fun FeedList(items: List) { 1. Read current implementation in `amethyst/` or `desktopApp/` 2. Identify pure visual logic (no platform APIs) -3. Create in `commons/commonMain` with hoisted state +3. Create in `commonsUI/commonMain` with hoisted state 4. Replace platform implementations with shared component 5. Keep platform-specific wrappers if needed diff --git a/.claude/skills/find-missing-translations/SKILL.md b/.claude/skills/find-missing-translations/SKILL.md index 50699978e5..5fa74a543f 100644 --- a/.claude/skills/find-missing-translations/SKILL.md +++ b/.claude/skills/find-missing-translations/SKILL.md @@ -24,9 +24,9 @@ There are two separate `strings.xml` trees, each with its own default `values/` | Tree | Default file | Per-locale file | |------|--------------|-----------------| | **amethyst** (Android app) | `amethyst/src/main/res/values/strings.xml` | `amethyst/src/main/res/values-/strings.xml` | -| **commons** (KMP Compose resources, shared by Android + Desktop) | `commons/src/commonMain/composeResources/values/strings.xml` | `commons/src/commonMain/composeResources/values-/strings.xml` | +| **commonsUI** (KMP Compose resources, shared by Android + Desktop) | `commonsUI/src/commonMain/composeResources/values/strings.xml` | `commonsUI/src/commonMain/composeResources/values-/strings.xml` | -The `commons` tree appeared when shared event-renderer composables were extracted out of `amethyst/` into `commons/` (Compose Multiplatform `stringResource`). It is **not** a copy of the amethyst tree — the vast majority of its keys are commons-only; only a small handful overlap. Every diff/count/translate command below works on either tree by swapping the base path — **run the whole technique once per tree** and report them separately (each maps to its own Crowdin file, so the counts should reconcile against two different Crowdin UI numbers). +The `commonsUI` tree appeared when shared event-renderer composables were extracted out of `amethyst/` into `commons/` — now `commonsUI/` since the UI split (Compose Multiplatform `stringResource`). It is **not** a copy of the amethyst tree — the vast majority of its keys are commons-only; only a small handful overlap. Every diff/count/translate command below works on either tree by swapping the base path — **run the whole technique once per tree** and report them separately (each maps to its own Crowdin file, so the counts should reconcile against two different Crowdin UI numbers). **Locale-qualifier caveat:** `commons` uses the same region-qualified locale dirs as amethyst for our four targets (`values-cs`, `values-de-rDE`, `values-sv-rSE`, `values-pt-rBR`), but the *full* set of locale dirs differs between trees. Enumerate `values-*` under each tree's own base rather than assuming they match. @@ -37,7 +37,7 @@ The `commons` tree appeared when shared event-renderer composables were extracte Detect name-overlap **and flag value mismatches** in one pass: ```bash -cdef=commons/src/commonMain/composeResources/values/strings.xml +cdef=commonsUI/src/commonMain/composeResources/values/strings.xml adef=amethyst/src/main/res/values/strings.xml comm -12 \ <(grep '"' commons/src/commonMain/composeResources/values-*/strings.xml +grep -nE '"' commonsUI/src/commonMain/composeResources/values-*/strings.xml # The commons English tree has zero quote-wrapped values — any hit in a locale file is almost certainly a bad copy from amethyst. ``` @@ -132,14 +132,14 @@ Default: amethyst/src/main/res/values/strings.xml Target: amethyst/src/main/res/values-/strings.xml # commons tree -Default: commons/src/commonMain/composeResources/values/strings.xml -Target: commons/src/commonMain/composeResources/values-/strings.xml +Default: commonsUI/src/commonMain/composeResources/values/strings.xml +Target: commonsUI/src/commonMain/composeResources/values-/strings.xml ``` A convenient way to run the whole technique twice is to loop over the two base dirs: ```bash -for base in amethyst/src/main/res commons/src/commonMain/composeResources; do +for base in amethyst/src/main/res commonsUI/src/commonMain/composeResources; do echo "########## tree: $base ##########" # ... run the diff/count/value-extraction commands with $base/values[...] ... done @@ -258,8 +258,8 @@ Flag and offer to fix: # hardcode "1" (or other literal digits) instead of using a placeholder. # Looks at default + all values-* locales, in BOTH resource trees. for f in amethyst/src/main/res/values/strings.xml amethyst/src/main/res/values-*/strings.xml \ - commons/src/commonMain/composeResources/values/strings.xml \ - commons/src/commonMain/composeResources/values-*/strings.xml; do + commonsUI/src/commonMain/composeResources/values/strings.xml \ + commonsUI/src/commonMain/composeResources/values-*/strings.xml; do awk -v file="$f" ' /]*>(.*?)', re.S) # (?' \ amethyst/src/main/res/values*/strings.xml \ - commons/src/commonMain/composeResources/values*/strings.xml + commonsUI/src/commonMain/composeResources/values*/strings.xml ``` Three things this scan taught us, all of which it now encodes: @@ -528,7 +528,7 @@ When adding translated strings to locale files: ## Common Mistakes -- **Scanning only the amethyst tree** — there are now **two** Crowdin-managed `strings.xml` trees (`amethyst/src/main/res` and `commons/src/commonMain/composeResources`). A key extracted into `commons/` will never show up in the amethyst diff. Run the whole technique once per tree (see "Resource trees") and report each separately. +- **Scanning only the amethyst tree** — there are now **two** Crowdin-managed `strings.xml` trees (`amethyst/src/main/res` and `commonsUI/src/commonMain/composeResources`). A key extracted into `commonsUI/` will never show up in the amethyst diff. Run the whole technique once per tree (see "Resource trees") and report each separately. - **Copying an overlapping `commons` translation by key name alone** — a shared key name does NOT mean shared English. `napplet_card_permissions` is "What it can access" in commons but "Permissions:" in amethyst; copying by name produced the wrong string. Diff the English *values* first; copy verbatim only when they're byte-identical, else translate fresh (see "Overlap" in Resource trees). - **Applying amethyst's `"…"` whitespace-quote convention to a commons string** — the commons Compose-resources tree authors edge whitespace raw and unquoted; wrapping quotes copied from amethyst render literally there. Match the commons source format. - **Trying to "dedupe" the amethyst↔commons value-overlap** — it's required architecture (commons can't depend on amethyst, so shared composables need their own `Res.string` catalog), not an error. Don't fold consolidation into a translation pass. diff --git a/.claude/skills/kotlin-multiplatform/SKILL.md b/.claude/skills/kotlin-multiplatform/SKILL.md index c473298d07..bd21f16742 100644 --- a/.claude/skills/kotlin-multiplatform/SKILL.md +++ b/.claude/skills/kotlin-multiplatform/SKILL.md @@ -383,7 +383,7 @@ import com.fasterxml.jackson.databind.ObjectMapper | State (business logic) | commonMain or commons/jvmAndroid | Reusable StateFlow patterns | | **ViewModels** | **commons/commonMain/viewmodels/** | **StateFlow/SharedFlow + logic shareable, Compose MP lifecycle compatible** | | UI formatters (pure) | commons/commonMain | Reusable, no dependencies | -| UI components (simple) | commons/commonMain | Cards, buttons, dialogs | +| UI components (simple) | commonsUI/commonMain | Cards, buttons, dialogs (Compose UI never goes in `commons`) | | **Screen layouts** | **Platform-specific** | **Window vs Activity, sidebar vs bottom nav** | | Navigation | Platform-specific only | Activity vs Window too different | | Permissions | Platform-specific only | APIs incompatible | diff --git a/.claude/skills/relay-client/SKILL.md b/.claude/skills/relay-client/SKILL.md index 1b72fb6977..a7c6892b18 100644 --- a/.claude/skills/relay-client/SKILL.md +++ b/.claude/skills/relay-client/SKILL.md @@ -17,7 +17,7 @@ The layer between `LocalCache`/`Account` and the raw relay connection. Ensures c ## Layout -All under `commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/`: +All under `commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/` (the `@Composable` entry points — `observeUser*`, `*FilterAssemblerSubscription`, `KeyDataSourceSubscription` — sit in the same package but in `commonsUI/src/commonMain/…`, the Compose half of the shared layer): ``` relayClient/ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5671c3f0f..44582700a4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,7 +45,7 @@ jobs: cache-read-only: ${{ github.ref != 'refs/heads/main' }} - name: Linter (gradle) - run: ./gradlew spotlessCheck :quartz:verifyKmpPurity :commons:verifyKmpPurity + run: ./gradlew spotlessCheck :quartz:verifyKmpPurity :commons:verifyKmpPurity :commonsUI:verifyKmpPurity build-desktop: needs: lint @@ -93,7 +93,7 @@ jobs: - name: Test + Build Desktop (gradle) run: | - CMD="./gradlew :quartz:jvmTest :commons:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test :desktopApp:${{ matrix.desktop-task }}" + CMD="./gradlew :quartz:jvmTest :commons:jvmTest :commonsUI:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test :desktopApp:${{ matrix.desktop-task }}" if [ "${{ runner.os }}" = "Linux" ]; then xvfb-run --auto-servernum $CMD else @@ -129,6 +129,7 @@ jobs: path: | quartz/build/reports/tests commons/build/reports/tests + commonsUI/build/reports/tests nestsClient/build/reports/tests cli/build/reports/tests desktopApp/build/reports/tests @@ -307,11 +308,15 @@ jobs: # :commons:jvmTest stays green — this is the job that catches it. # - compileTestKotlinIosArm64 catches device-only compile drift # (iosArm64 = aarch64-apple-ios) without needing a physical device. + # :commonsUI (the Compose half split out of :commons) gets the same + # treatment so the shared composables keep compiling on Apple targets. - name: Test Commons on iOS run: | ./gradlew \ :commons:iosSimulatorArm64Test \ - :commons:compileTestKotlinIosArm64 + :commons:compileTestKotlinIosArm64 \ + :commonsUI:iosSimulatorArm64Test \ + :commonsUI:compileTestKotlinIosArm64 - name: Upload iOS Test Reports uses: actions/upload-artifact@v7 @@ -363,6 +368,7 @@ jobs: :amethyst:lintPlayBenchmark \ :quartz:jvmTest \ :commons:jvmTest \ + :commonsUI:jvmTest \ :nestsClient:jvmTest \ :amethyst:testFdroidDebugUnitTest \ :amethyst:testPlayDebugUnitTest \ diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 85d5fbde49..618469e193 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -572,11 +572,12 @@ jobs: run: | set -euo pipefail # The plan at cli/plans/2026-04-21-cli-distribution.md §size-budget - # targets < 80 MB, but :commons currently leaks Compose + Skiko as - # transitive deps (~40 MB of unused UI jars). Budget is set to - # 200 MB until commons is split into core + ui modules — track that - # as a follow-up. Until then, this gate just catches pathological - # regressions (e.g. accidental :amethyst dep pulling Android libs). + # targets < 80 MB. Compose UI + Skiko now live in :commonsUI, which + # :cli does not depend on, so the headless :commons no longer drags + # ~40 MB of UI jars into the CLI. Budget stays at 200 MB for now + # (tighten once a release confirms the new size); this gate catches + # pathological regressions (e.g. an accidental :commonsUI/:amethyst + # dep pulling UI or Android libs back in). fail=0 for f in dist/*; do if [[ -f "$f" ]]; then diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index c56009804c..2b555168ec 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -53,7 +53,7 @@ jobs: # Both files in crowdin.yml are declared `type: android`, so Crowdin's Android # serializer escapes apostrophes on the way down: `l'URL` comes back as `l\'URL`. # That is correct for amethyst/src/main/res/, which aapt un-escapes at build time, - # and WRONG for commons/.../composeResources/, where Compose resolves only \uXXXX, + # and WRONG for commonsUI/.../composeResources/, where Compose resolves only \uXXXX, # \n and \t and leaves \' \" \? \@ alone -- so the backslash reaches the screen. # # Without this step every sync reopens the same regression and CI's @@ -68,14 +68,14 @@ jobs: - name: Convert Android escaping to Compose escaping in the shared catalog run: | python3 tools/strings-migrate/fix_escapes.py --no-unwrap-quotes \ - commons/src/commonMain/composeResources + commonsUI/src/commonMain/composeResources # Assert the conversion actually satisfied the check that guards main, so a case # the converter cannot repair fails the sync loudly here instead of opening a red # PR. Known gap if this ever trips: fix_escapes.py only rewrites text inside # / elements, while the check scans the whole file -- an escape in an # XML comment (comments do propagate into the locale files) has to be fixed at the - # source string in commons/.../composeResources/values/strings.xml by hand. + # source string in commonsUI/.../composeResources/values/strings.xml by hand. - name: Verify the shared catalog is free of Android-only escaping run: .claude/hooks/compose_escaping_check.py @@ -99,7 +99,7 @@ jobs: branch: l10n_crowdin_translations add-paths: | amethyst/src/main/res/**/strings.xml - commons/src/commonMain/composeResources/**/strings.xml + commonsUI/src/commonMain/composeResources/**/strings.xml docs/changelog/translators.json commit-message: 'chore: sync Crowdin translations and seed translator npub placeholders' title: 'New Crowdin Translations' diff --git a/BUILDING.md b/BUILDING.md index 93b541e93b..a1b221b904 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -96,7 +96,7 @@ and each has its own guide: | Artifact | Committed at | Regenerate when | Guide | |---|---|---|---| -| **Material Symbols subset font** | `commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf` | You add/remove a `MaterialSymbol("\uXXXX")` codepoint in `MaterialSymbols.kt`, or bump the upstream font | [`tools/material-symbols-subset/README.md`](tools/material-symbols-subset/README.md) — run `./tools/material-symbols-subset/subset.sh` | +| **Material Symbols subset font** | `commonsUI/src/commonMain/composeResources/font/material_symbols_outlined.ttf` | You add/remove a `MaterialSymbol("\uXXXX")` codepoint in `MaterialSymbols.kt`, or bump the upstream font | [`tools/material-symbols-subset/README.md`](tools/material-symbols-subset/README.md) — run `./tools/material-symbols-subset/subset.sh` | | **Arti (Tor) native libs** | `amethyst/src/main/jniLibs/*.so` | You update the pinned Arti version, change the JNI wrapper, or want to reproduce the binaries | [`tools/arti-build/README.md`](tools/arti-build/README.md) | > **Material Symbols is mandatory after icon changes.** The bundled font is a @@ -466,8 +466,8 @@ Homebrew removes the quarantine attribute on its own downloads. > with `dry_run=true` — the sign+notarize step runs regardless of `dry_run` and > now prints the per-file notary log on a non-`Accepted` verdict. If it comes > back `Invalid`, the fix is to codesign the dylibs *inside* those jars before -> zipping (and/or strip the unused `skiko`/Compose jars from the CLI image — the -> `:commons` core/ui split the size budget already flags). The **desktop** app +> zipping (the unused `skiko`/Compose jars left the CLI image with the +> `:commons` / `:commonsUI` split). The **desktop** app > bundles the same jars through Compose/jpackage notarization, so run a desktop > dry-run too; its in-jar handling differs and is likewise unverified. @@ -686,9 +686,10 @@ Caveats that the maintainer must weigh before submitting: - **Pre-built-jar scrutiny.** homebrew-core prefers source builds; downloading a jar bundle is an accepted-but-reviewed pattern for JVM tools. Be ready to justify it (sandboxed Gradle can't fetch Maven deps). -- **Bundle size.** The bundle is ~70 MB today because `:commons` leaks - Compose/Skiko jars onto the CLI classpath. Trimming that (a `:commons` - core/ui split) would shrink it and smooth review — tracked as a follow-up. +- **Bundle size.** The bundle used to be ~70 MB because `:commons` leaked + Compose/Skiko jars onto the CLI classpath. Compose UI now lives in + `:commonsUI`, which `:cli` does not depend on, so the bundle no longer + carries those jars — re-measure at the next release. After the formula merges, the `livecheck` block lets homebrew-core's BrewTestBot auto-open version-bump PRs on each stable release — no token or workflow on our diff --git a/CONTRIBUTING-WITH-AI.md b/CONTRIBUTING-WITH-AI.md index 4aeac7e61a..a2524947e9 100644 --- a/CONTRIBUTING-WITH-AI.md +++ b/CONTRIBUTING-WITH-AI.md @@ -175,9 +175,13 @@ device. PRs that introduce any of them will be sent back. ### KMP source-set discipline -- **Android-only imports don't belong in `commons/commonMain` or - `quartz/commonMain`.** Use `expect`/`actual` for platform-specific - bits, or move the Android-specific code to `androidMain`. +- **Android-only imports don't belong in `commons/commonMain`, + `commonsUI/commonMain` or `quartz/commonMain`.** Use `expect`/`actual` + for platform-specific bits, or move the Android-specific code to + `androidMain`. +- **Compose UI (`ui`/`foundation`/`material3`), Coil and `Res` don't belong + in `commons` at all** — that module is on the CLI classpath. Put the file + in `commonsUI` (same package) instead. ### Logging diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 56a3348ba6..93016404e6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,7 @@ Thanks for your interest in improving Amethyst. This document captures the expectations, conventions, and review rules for code, documentation, and translation contributions across all modules in this repository (`amethyst/`, -`desktopApp/`, `quartz/`, `commons/`, `cli/`, `quic/`, `nestsClient/`). +`desktopApp/`, `quartz/`, `commons/`, `commonsUI/`, `cli/`, `quic/`, `nestsClient/`). By contributing, you agree to license your work under the MIT license. Any work contributed where you are not the original author must contain its @@ -157,7 +157,8 @@ Common Gradle entry points: Modules: - `quartz/` — Nostr KMP library (protocol, crypto, models). **No UI.** -- `commons/` — Shared Compose Multiplatform UI, icons, ViewModels, flows. +- `commons/` — Shared headless layer: models, ViewModels, flows, relay client. **No Compose UI** (the CLI depends on it). +- `commonsUI/` — Shared Compose Multiplatform UI, icons, theme, Compose resources, on top of `commons`. - `quic/` — Pure-Kotlin QUIC v1 + HTTP/3 + WebTransport. - `nestsClient/` — Audio-rooms client (NIP-53) built on `:quic` and `:quartz`. @@ -175,7 +176,8 @@ of PR churn. Place new code by purpose: | What you're adding | Goes in | |---|---| | Nostr event types, NIPs, tags, signing, crypto, Bech32 | `quartz/commonMain/` | -| Shared Composables, icons, ViewModels, StateFlows | `commons/commonMain/viewmodels/` or `commons/commonMain/` | +| Shared ViewModels, StateFlows, relay subscriptions | `commons/commonMain/viewmodels/` or `commons/commonMain/` | +| Shared Composables, icons, theme | `commonsUI/commonMain/` (same packages as `commons`) | | Android-only screen, navigation, system integration | `amethyst/` | | Desktop-only window, sidebar, menu bar, shortcut | `desktopApp/` | | `amy ` subcommand (thin assembly only) | `cli/src/main/kotlin/.../cli/` | @@ -188,8 +190,9 @@ Hard rules: - `cli/` has **no Nostr protocol or business logic** — it's a thin assembly layer over `quartz` + `commons`. If your CLI command needs new behavior, extract it into `commons/` first. -- ViewModels belong in `commons/commonMain/`. Only screens (the Composable - that wires layout + navigation) stay in the platform module. +- ViewModels belong in `commons/commonMain/`; shared composables in + `commonsUI/commonMain/`. Only screens (the Composable that wires layout + + navigation) stay in the platform module. - For platform-specific behavior in a shared file, use `expect`/`actual`. ## Workflow diff --git a/amethyst/build.gradle.kts b/amethyst/build.gradle.kts index 77010ea9fe..87d83bc8b6 100644 --- a/amethyst/build.gradle.kts +++ b/amethyst/build.gradle.kts @@ -405,6 +405,7 @@ dependencies { implementation(project(":quartz")) implementation(project(":commons")) + implementation(project(":commonsUI")) implementation(project(":nestsClient")) // Agent text stream previews: the raw-QUIC binding plus the QUIC // stack under it (for the certificate validator it requires). diff --git a/benchmark/build.gradle.kts b/benchmark/build.gradle.kts index a9a0622133..8f9ee7bd68 100644 --- a/benchmark/build.gradle.kts +++ b/benchmark/build.gradle.kts @@ -67,6 +67,7 @@ dependencies { androidTestImplementation(libs.androidx.benchmark.junit4) androidTestImplementation(project(":quartz")) androidTestImplementation(project(":commons")) + androidTestImplementation(project(":commonsUI")) // Custom C secp256k1 (libschnorr256k1) for the 3-way Android benchmark androidTestImplementation(libs.schnorr256k1.kmp) diff --git a/commons/ARCHITECTURE.md b/commons/ARCHITECTURE.md index 25c594b532..4c6c3206e9 100644 --- a/commons/ARCHITECTURE.md +++ b/commons/ARCHITECTURE.md @@ -4,10 +4,11 @@ | Consumer | Kind | Uses from `commons` | |----------------|------------------------------|----------------------------------------------| -| `amethyst` | Android app (touch-first) | everything (models, state, ViewModels, UI) | -| `desktopApp` | Desktop JVM app (mouse-first)| everything (models, state, ViewModels, UI) | -| `cli` (`amy`) | Headless JVM CLI (no UI) | **non-UI only** — models, actions, relay, services | -| iOS (future) | iOS app | everything; expected to share most UI with Android | +| `amethyst` | Android app (touch-first) | everything (models, state, ViewModels) + `commonsUI` | +| `desktopApp` | Desktop JVM app (mouse-first)| everything (models, state, ViewModels) + `commonsUI` | +| `cli` (`amy`) | Headless JVM CLI (no UI) | everything — `commons` is headless by construction; it never sees `commonsUI` | +| `nappletHost` | Android WebView sandbox | napplet contract + `commonsUI` (for the shell/shim Compose resources) | +| iOS (future) | iOS app | everything + `commonsUI`; expected to share most UI with Android | `commons` sits **above** `quartz` (the protocol-only Nostr KMP library) and **below** the apps. The split between the three is: @@ -15,10 +16,13 @@ - **`quartz/`** — Nostr protocol: events, NIPs, crypto, relay framing. No app state, no UI, no caches of "what this user follows." - **`commons/`** — everything an Amethyst *client* needs that isn't a - platform-native screen or navigation shell: domain models (`Note`, `User`), - in-memory state holders, ViewModels, the relay-subscription client, shared - business services, **and** the Compose UI components that more than one front - end renders. + platform-native screen, navigation shell, **or Compose UI**: domain models + (`Note`, `User`), in-memory state holders, ViewModels, the relay-subscription + client, shared business services. +- **`commonsUI/`** — the Compose UI components that more than one front end + renders, plus everything only they need (icons, theme, Coil fetchers, + markdown, the `composeResources` strings/fonts and the generated `Res`). + Depends on `commons` as `api`. See `commonsUI/ARCHITECTURE.md`. - **`amethyst/` & `desktopApp/`** — platform-native screens, navigation (bottom-nav vs sidebar), gestures, system integration. They assemble `commons` pieces; they should not re-implement them. @@ -31,29 +35,32 @@ ## 1. The one rule that shapes the package tree: the **UI / non-UI boundary** -`commons` is a single module that contains **both** Compose UI and headless -logic. That is deliberate (it keeps a feature's model, state, and UI together — -see §3), but it creates one hard constraint, because **`cli` and any headless -consumer cannot use Compose**: +The shared layer is **two modules** with one package tree: -> **CLI-safe code** = does not depend on Compose UI. It may use the -> `androidx.compose.runtime` *annotations* `@Stable` / `@Immutable` (they are -> just stability tags) and snapshot state, but it must **not** import -> `androidx.compose.ui`, `androidx.compose.foundation`, -> `androidx.compose.material3`, declare `@Composable` functions, or build -> `ImageVector`s. +> **`commons` = CLI-safe code.** It does not depend on Compose UI. It may use +> the `androidx.compose.runtime` *annotations* `@Stable` / `@Immutable` (they +> are just stability tags) and snapshot state (`mutableStateOf`, `State`), but +> it must **not** import `androidx.compose.ui`, `androidx.compose.foundation`, +> `androidx.compose.material3`, Coil, the generated `Res`, declare +> `@Composable` functions, or build `ImageVector`s. Its `build.gradle.kts` +> simply has none of those dependencies, so a violation fails to compile. > -> **UI code** = anything that does. It is only usable by the GUI front ends -> (Android, Desktop, iOS), never by `cli`. +> **`commonsUI` = UI code.** Anything that does the above. It is only usable +> by the GUI front ends (Android, Desktop, iOS), never by `cli`. -Compose is an `implementation` dependency of `commonMain`, so `cli` pulling in -`commons` does **not** force it to render anything — but a `cli` command must -only reach for CLI-safe packages. When you add code, know which side of this -line it is on, and put it in a package that matches (§2). +Both modules share the **same `com.vitorpamplona.amethyst.commons.*` package +tree** — the split is a module boundary, not a package rename, so a file moves +between `commons/src/…` and `commonsUI/src/…` without changing its package or +any consumer's imports. Kotlin resolves same-package declarations across +modules without imports; the only thing that stops working across the boundary +is `internal` visibility (a UI file cannot see an `internal` declaration in +`commons` — make it public or move it). -This boundary is **not** a top-level `ui/` vs `logic/` partition of the whole -module (we chose to stay feature-oriented, §3). It is a property of each file -that you keep track of via package placement and the table in §2. +This boundary is **not** a top-level `ui/` vs `logic/` partition of the package +tree (we chose to stay feature-oriented, §3). It is a property of each file: +a feature keeps its logic in `commons/…//` and its composables in +`commonsUI/…//ui/` (or `commonsUI/…//` for the historical +flat packages), and the table in §2 says which module each package lives in. --- @@ -61,7 +68,9 @@ that you keep track of via package placement and the table in §2. Top-level packages under `commonMain/.../commons/`, grouped by concern. **UI?** marks whether the -package contains Compose UI (and is therefore *not* CLI-safe). +package contains Compose UI (and therefore lives in **`commonsUI`**, not +here). "mixed" means the feature's logic is in `commons` and its composables +in `commonsUI`, under the same package. ### Domain models & data | Package | UI? | Purpose | @@ -91,17 +100,19 @@ package contains Compose UI (and is therefore *not* CLI-safe). | Package | UI? | Purpose | |----------------|-----|---------| | `state` | no² | Small feature `StateFlow` machines (`FollowState`, `UserMetadataState`, `LoadingState`). | -| `viewmodels` | no² | Larger list/feed-backed ViewModels (`androidx.lifecycle.ViewModel`). Shared by all GUI front ends; `cli` usually drives the layers below instead. | +| `viewmodels` | no² | Larger list/feed-backed ViewModels (`androidx.lifecycle.ViewModel`). Shared by all GUI front ends; `cli` usually drives the layers below instead. The few that hold Compose UI state (`ChatNewMessageState` — `TextFieldValue`; `thread/LevelFeedViewModel` — `LazyListState`) live in `commonsUI` under the same package. | | `feeds` | no | `FeedDefinitionRepository` — custom-feed definitions & ordering. | -| `profile` | mixed | `ProfileBroadcastStatus` (state) + `EditProfileFields` at the root; the `ProfileBroadcastBanner` composable lives in `profile/ui`. | +| `profile` | mixed | `ProfileBroadcastStatus` (state) + `EditProfileFields` at the root; the `ProfileBroadcastBanner` composable lives in `commonsUI` `profile/ui`. | +| `privacylock` | mixed | Lock state machine + settings here; `LocalPrivacyLockState`/`lockStateFor` (CompositionLocal accessor) in `commonsUI`. | -² may touch `compose.runtime`/`foundation` state types (e.g. `LazyListState`); -they are shared across the GUI apps. Treat as GUI-shared, not strictly headless. +² may touch `compose.runtime` state types (snapshot state, `@Stable`); they +are shared across the GUI apps. A state holder that needs a `foundation`/`ui` +type (`LazyListState`, `TextFieldValue`, `TextFieldState`) goes to `commonsUI`. ### Relay client | Package | UI? | Purpose | |----------------|-----|---------| -| `relayClient` | no | Compose-scoped subscription managers, filter assemblers, EOSE managers, preloaders. (Despite a `composeSubscriptionManagers` subpackage name, this is subscription-lifecycle logic, not UI.) The canonical **per-visible loading** entry points live here: `relayClient/user/` (`observeUser*` — kind-0 metadata) and `relayClient/event/` (`EventFinderFilterAssemblerSubscription`/`observeNote*` — reactions/zaps/reposts). See the `relay-client` skill. | +| `relayClient` | mixed | Compose-scoped subscription managers, filter assemblers, EOSE managers, preloaders. (Despite a `composeSubscriptionManagers` subpackage name, this is subscription-lifecycle logic, not UI.) The `@Composable` entry points — `relayClient/user/` (`observeUser*` — kind-0 metadata), `relayClient/event/` (`EventFinderFilterAssemblerSubscription`/`observeNote*`), the other `*FilterAssemblerSubscription`s, `KeyDataSourceSubscription`, `auth/AuthApprovalBanner` — are in `commonsUI` under the same packages. See the `relay-client` skill. | | `relays` | no | Low-level EOSE/relay-timing bookkeeping (`EOSECache`, `EOSERelayList`). | ### Platform abstractions (`expect`/`actual`) @@ -112,19 +123,23 @@ they are shared across the GUI apps. Treat as GUI-shared, not strictly headless. | `tor` | no | Tor manager interface + settings. | | `service` | no | Cross-cutting services: `BundledUpdate` batching (common); `service/upload` (JVM), `service/nwc`, `service/lnurl` (jvmAndroid). **Singular `service`** — there is no `services`. | -### UI (Compose — **not** CLI-safe) +### 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/feeds` (feed DAL + filters — see debt §4), `ui/notifications`, `ui/screens`, `ui/elements`, `ui/layouts`, `ui/markdown`, plus Compose helpers in `ui/state` (cached-state) and `ui/text` (TextField extensions). Feature-specific UI lives in `/ui`, **not** here. | -| `nip23LongContent` | yes | Long-form (NIP-23) article UI: `nip23LongContent/ui/article` (reader) + `…/ui/editor` (authoring). The model lives in `model/nip23LongContent`. | -| `icons` | yes | `ImageVector` icon definitions + builders. | +| `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/feeds` in *this* module holds the headless feed DAL (`FeedFilter`, `AdditiveFeedFilter`, `ChangesFlowFilter`, `FeedContentState`, `RepostRenderability`…) — see debt §4; the `ui/feeds` composables (`NewPostsChip`, `RelayReachMarker`…) are in `commonsUI`. Likewise `ui/note/ParentNote`+`ReplyContext` (pure thread logic) stay here. | +| `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. | | `robohash` | yes | Procedural robohash avatar `ImageVector` assembly. | +| `audio` | mixed | Spectrum/visualizer *data* (`AudioSpectrum`, `SpectrumAnalyzer`…) here; the `VisualizerRenderer`s, `VisualizerRegistry` and the canvas composables in `commonsUI`. | +| `service/image` | mixed | `CoilImageBridge` + the BlurHash/ThumbHash/Base64/Blossom Coil fetchers are `commonsUI` (they are Coil); the headless image helpers stay here. | +| `napplet` | mixed | Protocol/permission logic here; `NappletWebContract` (serves the shell/shim from `composeResources`) in `commonsUI`. | +| `favorites`, `nip30CustomEmojis`, `nip34Git`, `nip85TrustedAssertions`, `nip53LiveActivities` | mixed | Logic here; each feature's `ui/` (or the flat `FavoriteAppIcon`, `EmojiSuggestionState`) in `commonsUI`. | ### Mixed (documented debt — see §4) | Package | UI? | Purpose | |----------------|-----|---------| -| `nip64Chess` | mixed | Live-chess feature: game/lobby/subscription logic **and** board/lobby composables in one flat package. Needs a `nip64Chess/ui` split. (Mirrors `quartz/.../nip64Chess`.) | +| `nip64Chess` | mixed | Live-chess feature: game/lobby/subscription logic (here) **and** board/lobby composables (`commonsUI`) in one flat package. Still wants a `nip64Chess/ui` sub-package rename. (Mirrors `quartz/.../nip64Chess`.) | | `domain` | no | Currently only `domain/nip46` (Nostr Connect signer flows). Sparse; candidate to fold into a clearer home. | --- @@ -185,11 +200,15 @@ Instead, **layer is the primary axis, NIP is the secondary axis**: | Source set | For | |---------------|-----| | `commonMain` | KMP code for **all** targets (Android, JVM, iOS). Gated by `verifyKmpPurity` — no Jackson/OkHttp/`System.currentTimeMillis`/`java.util.UUID`/JVM `@Synchronized`/`@Volatile`. Use the KMP replacements. | -| `jvmAndroid` | Shared by Android + Desktop, **not** iOS. Where JVM-bound deps live (`nestsClient`, Coil-OkHttp, markdown, `viewModel()` helper, NWC/LNURL). | -| `jvmMain` | Desktop-only (keyring, EXIF, `service/upload`). `dependsOn(jvmAndroid)`. | -| `androidMain` | Android-only (Keystore, DataStore). `dependsOn(jvmAndroid)`. | +| `jvmAndroid` | Shared by Android + Desktop, **not** iOS. Where JVM-bound deps live (`nestsClient`, OkHttp, NWC/LNURL). | +| `jvmMain` | Desktop-only (keyring, EXIF, `service/upload`, OS notifications). `dependsOn(jvmAndroid)`. | +| `androidMain` | Android-only (Keystore, DataStore, the Android `R` string resources used by the napplet host). `dependsOn(jvmAndroid)`. | | `iosMain` | iOS `actual`s. Compile-only spike today. | +`commonsUI` mirrors the same source-set layout (plus `skikoMain`, shared by +desktop JVM + iOS for `org.jetbrains.skia` pixel helpers); Coil-OkHttp, +markdown and the `viewModel()` helper live in its `jvmAndroid`. + When adding platform code, prefer the **most common** source set that still compiles: `commonMain` → `jvmAndroid` → platform-specific. See `/kotlin-multiplatform`. @@ -197,7 +216,8 @@ compiles: `commonMain` → `jvmAndroid` → platform-specific. See ### Where does my code go? (quick guide) 1. **Pure Nostr protocol** (events/NIPs/crypto)? → not here, it's `quartz`. 2. **A composable** rendered by ≥2 front ends, or that you want iOS to share? → - `ui/` or `/ui`. Never in `cli`. + `commonsUI`, in `ui/` or `/ui` (same package tree as here). + Also anything that imports Coil, `Res`, or a `foundation`/`ui` state type. 3. **A ViewModel / `StateFlow` state holder**? → `viewmodels` or `state` (or `` if feature-scoped). Keep it CLI-safe where practical. 4. **Relay subscription / filter assembly**? → `relayClient`. @@ -212,14 +232,17 @@ compiles: `commonMain` → `jvmAndroid` → platform-specific. See These are intentionally *documented*, not silently tolerated. Fix opportunistically. -- **`nip64Chess` is UI+logic in one flat package.** `LiveChessGame.kt` mixes a - state class with composables. Split into `nip64Chess/` (logic) + - `nip64Chess/ui/` (composables); this needs file-level surgery (extracting - composables out of logic files), not just moves, so it is deferred. -- **`ui/feeds` holds the feed data-access layer** (`FeedFilter`, +- **`nip64Chess` is UI+logic in one flat package.** The composables now sit in + `commonsUI` (module split), but they keep the flat `nip64Chess` package; + renaming them into `nip64Chess/ui/` is the remaining step. +- **`ui/feeds` (in `commons`) holds the feed data-access layer** (`FeedFilter`, `ChangesFlowFilter`, `FeedContentState`), which is logic, not UI, and overlaps - conceptually with the top-level `feeds` (custom-feed definitions). Consider - moving the DAL out of `ui/`. + conceptually with the top-level `feeds` (custom-feed definitions). Since the + module split it is the one `ui.*` package that is *also* in `commons`. Move + the DAL out of `ui/` (a package rename touching app imports) when convenient. +- **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. - **`domain` is sparse** (only `nip46`). Either grow it as the home for use-case/flow types or rename it to the matching `nip46RemoteSigner` per the NIP-second-axis rule. diff --git a/commons/build.gradle.kts b/commons/build.gradle.kts index 50437bf088..0f86f0bdac 100644 --- a/commons/build.gradle.kts +++ b/commons/build.gradle.kts @@ -1,29 +1,20 @@ - import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.plugin.mpp.DisableCacheInKotlinVersion -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCacheApi -import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget -import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable - -// Disables the Kotlin/Native compiler cache for an iOS test binary so the -// Compose ui-uikit klib recompiles fresh instead of linking the broken prebuilt -// cache (see the call site in the `kotlin {}` block). The version guard makes -// Kotlin re-surface this workaround once we move past 2.4.20, so it can be -// dropped when a newer Compose/Kotlin pairing fixes the cache. Wrapped in a -// helper because @OptIn only applies to declarations, not bare statements. -@OptIn(KotlinNativeCacheApi::class) -fun TestExecutable.disableUiKitPrebuiltCache() = - disableNativeCache( - DisableCacheInKotlinVersion.`2_4_20`, - "Compose ui-uikit prebuilt cache references UIViewLayoutRegion (iOS 17+); " + - "linking the iOS test binary fails under Xcode 16.4.", - ) +// `:commons` is the HEADLESS half of the shared layer: domain models, state +// holders, ViewModels, the relay client, services. It is consumed by every +// front end including the headless `:cli`, so it must never depend on Compose +// UI (ui / foundation / material3), Coil, Compose resources or Skiko — those +// live in `:commonsUI`, which sits on top of this module. Only the Compose +// *runtime* (@Stable/@Immutable + snapshot state) is allowed here. plugins { alias(libs.plugins.kotlinMultiplatform) 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. alias(libs.plugins.jetbrainsComposeCompiler) - alias(libs.plugins.composeMultiplatform) alias(libs.plugins.serialization) } @@ -70,45 +61,20 @@ kotlin { iosArm64() iosSimulatorArm64() - // Compose Multiplatform 1.11.x ships an `org.jetbrains.compose.ui:ui-uikit` - // prebuilt Kotlin/Native cache whose CMPLayoutRegion object hard-references - // the UIKit class `UIViewLayoutRegion` (introduced in iOS 17). Linking the - // iOS *test* executable against that cache under Xcode 16.4 fails with - // ld: Undefined symbols: _OBJC_CLASS_$_UIViewLayoutRegion - // because the cached object was built for a newer simulator SDK (18.5) than - // the test binary is being linked for (14.0). Disabling the native cache for - // the iOS test binaries makes ui-uikit recompile against the active SDK, - // where the symbol resolves. See disableUiKitPrebuiltCache() above and - // https://kotl.in/disable-native-cache - targets.withType().configureEach { - binaries.withType().configureEach { - disableUiKitPrebuiltCache() - } - } - sourceSets { commonMain { dependencies { implementation(project(":quartz")) - // Compose Multiplatform - implementation(libs.jetbrains.compose.ui) - implementation(libs.jetbrains.compose.foundation) + // Compose *runtime* only — @Stable/@Immutable annotations and + // snapshot state (mutableStateOf, State) used by state holders. + // No ui / foundation / material3 here: that is :commonsUI. implementation(libs.jetbrains.compose.runtime) - implementation(libs.jetbrains.compose.material3) - implementation(libs.jetbrains.compose.ui.tooling.preview) - // Lifecycle (KMP since 2.8.0). lifecycle-viewmodel and - // lifecycle-runtime-compose ship iOS variants; - // lifecycle-viewmodel-compose (the viewModel() Composable - // helper) is Android-only and lives in jvmAndroid below. + // Lifecycle ViewModel (KMP since 2.8.0, ships iOS variants). + // The Compose-side helpers (lifecycle-runtime-compose, + // viewModel()) live in :commonsUI. implementation(libs.androidx.lifecycle.viewmodel) - implementation(libs.androidx.lifecycle.runtime.compose) - - // Image loading (Coil 3 - KMP). The okhttp network fetcher is - // JVM-only and lives in jvmAndroid; iOS will pull coil-ktor - // when that target wires its actual. - implementation(libs.coil.compose) // LruCache (KMP-ready) implementation(libs.androidx.collection) @@ -119,12 +85,6 @@ kotlin { // JSON for custom-feed definitions (KMP — replaces Jackson // for the one commonMain serializer that was blocking iOS). implementation(libs.kotlinx.serialization.json) - - // Compose Multiplatform Resources - implementation(libs.jetbrains.compose.components.resources) - - // KMP syntax highlighter (Apache-2.0) for the git code browser. - implementation(libs.highlights) } } @@ -149,39 +109,17 @@ kotlin { // Phase 5 lands. implementation(project(":nestsClient")) - // Coil's OkHttp network fetcher (JVM-only). iOS will use - // coil-ktor when the iOS Compose UI ships. - implementation(libs.coil.okhttp) - // OkHttp (+ coroutines bridge) for the link-preview fetcher // (service/preview/UrlPreview). JVM-only; iOS will swap to // Ktor when its UI ships. implementation(libs.okhttp) implementation(libs.okhttpCoroutines) - - // Markdown rendering (richtext-commonmark). The single - // consumer (RenderMarkdown.kt) already lives in jvmAndroid. - // iOS support pending Phase 3 markdown decision. - implementation(libs.markdown.commonmark) - implementation(libs.markdown.ui) - implementation(libs.markdown.ui.material3) - - // viewModel() Compose helper. AndroidX publishes this - // artifact for android/jvmStubs/linuxx64Stubs but not iOS, - // so it stays in jvmAndroid until we either swap to the - // org.jetbrains.androidx.lifecycle variant or accept a - // platform-specific ViewModel access pattern on iOS. - implementation(libs.androidx.lifecycle.viewmodel.compose) } } jvmMain { dependsOn(jvmAndroid) dependencies { - // Desktop-specific Compose - implementation(compose.desktop.currentOs) - implementation(libs.jetbrains.compose.ui.tooling) - // Secure key storage via OS keychain (macOS/Windows/Linux) implementation(libs.java.keyring) @@ -205,8 +143,10 @@ kotlin { androidMain { dependsOn(jvmAndroid) dependencies { - // Android-specific Compose tooling - implementation(libs.androidx.ui.tooling.preview) + // androidx.core KTX (Bitmap.scale, prefs.edit {}) used by the + // Android actuals. Was reaching us transitively through the + // Compose UI artifacts before the :commonsUI split. + implementation(libs.androidx.core.ktx) // Secure key storage via Android Keystore implementation(libs.androidx.security.crypto.ktx) @@ -222,16 +162,6 @@ kotlin { getByName("iosArm64Main").dependsOn(iosMain) getByName("iosSimulatorArm64Main").dependsOn(iosMain) - // Skiko-backed targets (desktop JVM + iOS) share pixel-format helpers - // (org.jetbrains.skia.* resolves on both through Compose). Android is - // deliberately NOT in this set — it renders through android.graphics. - val skikoMain = - create("skikoMain") { - dependsOn(commonMain.get()) - } - getByName("jvmMain").dependsOn(skikoMain) - iosMain.dependsOn(skikoMain) - getByName("androidHostTest") { dependencies { implementation(libs.junit) @@ -259,12 +189,6 @@ kotlin { } } -compose.resources { - publicResClass = true - packageOfResClass = "com.vitorpamplona.amethyst.commons.resources" - generateResClass = always -} - // JVM tests run AWT-backed code (ImageIO, Thumbnailator, BufferedImage) — pin // headless mode so a stray Toolkit.getDefaultToolkit() in a transitive dep // never bounces the macOS Dock during CI/local test runs. @@ -287,7 +211,6 @@ val verifyKmpPurity by tasks.registering { "src/appleMain", "src/appleTest", "src/nativeMain", "src/nativeTest", "src/iosMain", "src/iosTest", - "src/skikoMain", "src/skikoTest", "src/iosArm64Main", "src/iosArm64Test", "src/iosSimulatorArm64Main", "src/iosSimulatorArm64Test", "src/linuxMain", "src/linuxTest", diff --git a/commons/plans/2026-09-12-commons-ui-split.md b/commons/plans/2026-09-12-commons-ui-split.md new file mode 100644 index 0000000000..cb28d7d7f8 --- /dev/null +++ b/commons/plans/2026-09-12-commons-ui-split.md @@ -0,0 +1,89 @@ +# Split `commons` into `commons` (headless) + `commonsUI` (Compose) + +**Date:** 2026-09-12 +**Status:** shipped on this branch + +## Why + +`cli` (`amy`) depends on `:commons`. Until now `:commons` declared Compose +UI, Coil, Compose resources, markdown and (on JVM) `compose.desktop.currentOs` +as dependencies, so every CLI distribution dragged ~40 MB of Compose + Skiko +jars it never loads (`create-release.yml` had a 200 MB budget "until commons +is split into core + ui modules"; `BUILDING.md` flagged the same for the +Homebrew bundle). The UI / non-UI boundary documented in +`commons/ARCHITECTURE.md` §1 was a convention enforced by nothing. + +## What + +A new KMP module **`:commonsUI`** (same targets and source-set layout as +`:commons`, plus `skikoMain`) that `api`-depends on `:commons` and owns every +Compose-dependent file. `:commons` keeps only the Compose *runtime* +(`@Stable`/`@Immutable`, snapshot state) and `lifecycle-viewmodel`; it no +longer applies the `org.jetbrains.compose` plugin, has no `composeResources`, +no Coil, no markdown, no `highlights`, no desktop Compose. + +**Files keep their packages.** The split is a build-graph boundary, not a +package rename: `231` files were `git mv`'d from `commons/src/…` to +`commonsUI/src/…` and not a single import changed in `amethyst`, +`desktopApp`, `nappletHost` or `cli`. The generated `Res` class stays at +`com.vitorpamplona.amethyst.commons.resources` for the same reason. + +Consumers: `amethyst`, `desktopApp`, `nappletHost` (for +`NappletWebContract`, which reads the shell/shim from `composeResources`) and +`benchmark` (robohash) gained `project(":commonsUI")`. `cli`, `geode`, +`marmotBench` are untouched and must stay that way. + +## Method (reproducible) + +1. Classify every `.kt` under `commons/src` as **UI** if it imports + `androidx.compose.{ui,foundation,material3,animation}`, + `org.jetbrains.compose.*`, `coil3`, `org.jetbrains.skia`, + `androidx.lifecycle.compose`, `…commons.resources`, or declares + `@Composable`. +2. Build the intra-module reference graph (imports + same-package simple-name + hits) and verify **no headless file references a UI file**. Two real hits + surfaced and were fixed by surgery rather than by moving logic into the UI + module: + - `richtext/GalleryParser` carried a vestigial + `@OptIn(ExperimentalLayoutApi::class)` — dropped; it is pure logic. + - `privacylock/PrivacyLockState` declared the `LocalPrivacyLockState` + CompositionLocal + `lockStateFor()` next to the state machine — the two + Compose members moved to `commonsUI/…/privacylock/LocalPrivacyLockState.kt` + (same package). +3. Additionally move the rest of the UI-only packages (`ui/**`, `icons`, + `hashtags`, `robohash`, `/ui`) **unless a headless file depends + on the file**. That rule keeps the feed DAL (`ui/feeds/FeedFilter`, + `AdditiveFeedFilter`, `ChangesFlowFilter`, `FeedContentState`, + `RepostRenderability`, `AdditiveComplexFeedFilter`…) and + `ui/note/ParentNote`+`ReplyContext` in `commons` (ViewModels use them). +4. Tests follow their subject; test fixtures shared with headless tests + (`ui/note/StubCache`) stay in `commons`. +5. Check `expect`/`actual` pairs never straddle the boundary (none did) and + that no `internal` declaration is used across it (none was). + +## Verified + +- `:commons:compileKotlinJvm`, `:commonsUI:compileKotlinJvm`, + `:cli:compileKotlin`, `:desktopApp:compileKotlin`, + `:nappletHost:compileDebugKotlin`, `:amethyst:compileFdroidDebugKotlin`. +- `:commons:jvmTest`, `:commonsUI:jvmTest`, `:cli:test`, + `:commons:verifyKmpPurity`, `:commonsUI:verifyKmpPurity`. +- `:cli` runtime classpath no longer contains `org.jetbrains.compose.ui`, + `foundation`, `material3`, `skiko` or `coil`. + +iOS targets could not be linked in the Linux CI container; the workflow runs +`:commonsUI:iosSimulatorArm64Test` + `:commonsUI:compileTestKotlinIosArm64` +next to the `:commons` ones on macOS. + +## Follow-ups + +- **Tighten the CLI size budget** in `create-release.yml` once a release + confirms the new `amy` tarball size (target < 80 MB per + `cli/plans/2026-04-21-cli-distribution.md`). +- **Rename the feed DAL out of `ui.feeds`** (it is the one `ui.*` package + that still lives in `commons`); a package rename that touches app imports. +- **`nip64Chess` → `nip64Chess/ui`** for the composables now in `commonsUI` + (module split done, package rename pending). +- `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. diff --git a/commons/plans/README.md b/commons/plans/README.md index cf0a4a40df..3e35c3732c 100644 --- a/commons/plans/README.md +++ b/commons/plans/README.md @@ -1,6 +1,6 @@ # commons plans -_Audited 2026-06-30. 6 plans: 2 shipped (archived), 2 in-progress, 2 queued, 0 abandoned._ +_Audited 2026-06-30 (+ 2026-09-12 split entry). 7 plans: 3 shipped, 2 in-progress, 2 queued, 0 abandoned._ ## In progress | Plan | Summary | @@ -15,6 +15,11 @@ _Audited 2026-06-30. 6 plans: 2 shipped (archived), 2 in-progress, 2 queued, 0 a | [2026-05-30-amethyst-to-commons-migration.md](2026-05-30-amethyst-to-commons-migration.md) | Roadmap to move shared `amethyst` Android code into `commons`; keystone `Account`/`LocalCache` extraction not begun. | | [2026-08-03-poll-results-page.md](2026-08-03-poll-results-page.md) | Extended NIP-88 poll results page (per-option counts + who voted for what) for Android and Desktop; also specifies four tally-correctness fixes and the missing poll-relay subscription. Proposed, not started. | +## Shipped +| Plan | Summary | +| ---- | ------- | +| [2026-09-12-commons-ui-split.md](2026-09-12-commons-ui-split.md) | Split the Compose half of `commons` into the new `:commonsUI` module (same packages, `api(:commons)`), so `cli` no longer carries Compose/Skiko; records the classification method and follow-ups. | + ## Archived (shipped) | Plan | Summary | | ---- | ------- | diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/privacylock/PrivacyLockState.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/privacylock/PrivacyLockState.kt index 23648af539..c0b2826c9b 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/privacylock/PrivacyLockState.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/privacylock/PrivacyLockState.kt @@ -20,9 +20,6 @@ */ package com.vitorpamplona.amethyst.commons.privacylock -import androidx.compose.runtime.Composable -import androidx.compose.runtime.ReadOnlyComposable -import androidx.compose.runtime.compositionLocalOf import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -174,23 +171,3 @@ class PrivacyLockState( idleTimerJob = null } } - -/** - * Provided once at the App composition root. Map keyed by [LockScope]; every - * scope must have an entry (see [lockStateFor] which throws when missing). - */ -val LocalPrivacyLockState = - compositionLocalOf> { - error("LocalPrivacyLockState not provided — wrap App() with CompositionLocalProvider") - } - -/** - * Convenience accessor used inside gate composables. Reads the map from the - * ambient [LocalPrivacyLockState] and returns the state holder for [scope]. - * Throws if the scope was not registered at the App root. - */ -@Composable -@ReadOnlyComposable -fun lockStateFor(scope: LockScope): PrivacyLockState = - LocalPrivacyLockState.current[scope] - ?: error("PrivacyLockState for $scope not registered at App root") diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/richtext/GalleryParser.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/richtext/GalleryParser.kt index e72592cb44..b66ee57ab4 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/richtext/GalleryParser.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/richtext/GalleryParser.kt @@ -20,7 +20,6 @@ */ package com.vitorpamplona.amethyst.commons.richtext -import androidx.compose.foundation.layout.ExperimentalLayoutApi import kotlinx.collections.immutable.toImmutableList data class ParagraphImageAnalysis( @@ -106,7 +105,6 @@ class GalleryParser { return imageParagraphs to j } - @OptIn(ExperimentalLayoutApi::class) fun processParagraphs(paragraphs: List): List { val result = mutableListOf() diff --git a/commonsUI/.gitignore b/commonsUI/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/commonsUI/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/commonsUI/ARCHITECTURE.md b/commonsUI/ARCHITECTURE.md new file mode 100644 index 0000000000..1f0ffea9fb --- /dev/null +++ b/commonsUI/ARCHITECTURE.md @@ -0,0 +1,64 @@ +# `commonsUI` — the Compose half of the shared layer + +`commonsUI` holds every piece of shared code that needs **Compose UI** and is +therefore useless to the headless `cli`: + +- composables (`ui/`, `/ui`, and the historical flat feature + packages like `nip64Chess`, `audio`), +- `ImageVector` icons (`icons`, `hashtags`, `robohash`) and the icon fonts, +- theme, layouts, markdown rendering (`ui/markdown`, jvmAndroid), +- Coil (`service/image`: `CoilImageBridge` + BlurHash/ThumbHash/Base64/Blossom + fetchers), +- the `composeResources` tree (translated strings, fonts, the napplet shell + + shim files) and the generated `com.vitorpamplona.amethyst.commons.resources.Res`, +- the `@Composable` relay-client entry points (`observeUser*`, + `*FilterAssemblerSubscription`, `KeyDataSourceSubscription`), +- state holders that carry a `foundation`/`ui` type (`LevelFeedViewModel` with + its `LazyListState`, `ChatNewMessageState` with `TextFieldValue`, + `EmojiSuggestionState` with `TextFieldState`). + +It depends on `:commons` (and `:quartz`) as **`api`**, so a consumer that adds +`:commonsUI` sees the headless layer transitively. `amethyst`, `desktopApp`, +`nappletHost` and `benchmark` depend on it; `cli`, `geode`, `marmotBench` +must never. + +## Same packages as `commons` + +Every file keeps its `com.vitorpamplona.amethyst.commons.*` package. The split +is a **build-graph boundary, not a package rename**: nothing in the apps had to +change an import, and a file can move between the two modules with a `git mv`. +The rule for which module a file lives in is mechanical: + +> imports `androidx.compose.ui` / `foundation` / `material3` / `animation`, +> Coil, `org.jetbrains.compose.resources`, `Res`, `org.jetbrains.skia`, or +> declares a `@Composable` → **`commonsUI`**. Otherwise → **`commons`**. + +The only cross-module gotcha is `internal`: a `commonsUI` file cannot see an +`internal` declaration in `commons`. Make it public (or move the caller). + +The full package taxonomy — including which packages are "mixed" (logic in +`commons`, composables here, same package name) — is the table in +`commons/ARCHITECTURE.md` §2. Read that first; this file only documents what +is specific to the UI module. + +## Source sets + +| Source set | For | +|---------------|-----| +| `commonMain` | Composables, icons, theme, Coil fetchers, `composeResources`. Gated by `verifyKmpPurity` like `commons`. | +| `jvmAndroid` | Markdown renderer (`ui/markdown`), Coil-OkHttp + Blossom read-auth fetcher, the `viewModel()` helper. | +| `jvmMain` | Desktop Coil bridge (`CoilImageBridge.jvm.kt`), `compose.desktop.currentOs`. `dependsOn(jvmAndroid)` + `skikoMain`. | +| `androidMain` | Android Coil bridge. `dependsOn(jvmAndroid)`. | +| `skikoMain` | `org.jetbrains.skia` pixel helpers shared by desktop JVM + iOS (`SkiaBitmapConverter`). | +| `iosMain` | iOS Coil bridge. Compile-only spike today. | + +## Tooling that points here + +- Icon fonts: `tools/material-symbols-subset/subset.sh` and + `tools/icon-font/build_icon_font.py` read `icons/` and write + `composeResources/font/` in this module (see root `.claude/CLAUDE.md`, "Icons"). +- Translations: `crowdin.yml` and `tools/strings-migrate/` target + `commonsUI/src/commonMain/composeResources/`. +- CI: `.github/workflows/build.yml` runs `:commonsUI:jvmTest`, + `:commonsUI:verifyKmpPurity` and the iOS compile/test tasks next to the + `:commons` ones. diff --git a/commonsUI/build.gradle.kts b/commonsUI/build.gradle.kts new file mode 100644 index 0000000000..8fe797c39e --- /dev/null +++ b/commonsUI/build.gradle.kts @@ -0,0 +1,293 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.DisableCacheInKotlinVersion +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCacheApi +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.TestExecutable + +// `:commonsUI` is the Compose half of the shared layer: every composable, +// icon, theme, Coil fetcher and Compose-resource (strings/fonts/files) that the +// GUI front ends (Android, Desktop, iOS) render. It sits on top of `:commons` +// (headless models, state, ViewModels, relay client) and is never a dependency +// of `:cli`, which keeps Compose UI + Skiko off the CLI classpath. +// Source files keep their `com.vitorpamplona.amethyst.commons.*` packages so +// the module boundary is purely a build-graph constraint — consumers did not +// have to change a single import when the split happened. + +// Disables the Kotlin/Native compiler cache for an iOS test binary so the +// Compose ui-uikit klib recompiles fresh instead of linking the broken prebuilt +// cache (see the call site in the `kotlin {}` block). The version guard makes +// Kotlin re-surface this workaround once we move past 2.4.20, so it can be +// dropped when a newer Compose/Kotlin pairing fixes the cache. Wrapped in a +// helper because @OptIn only applies to declarations, not bare statements. +@OptIn(KotlinNativeCacheApi::class) +fun TestExecutable.disableUiKitPrebuiltCache() = + disableNativeCache( + DisableCacheInKotlinVersion.`2_4_20`, + "Compose ui-uikit prebuilt cache references UIViewLayoutRegion (iOS 17+); " + + "linking the iOS test binary fails under Xcode 16.4.", + ) + +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidKotlinMultiplatformLibrary) + alias(libs.plugins.jetbrainsComposeCompiler) + alias(libs.plugins.composeMultiplatform) +} + +kotlin { + compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } + + jvm { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + } + } + + android { + namespace = "com.vitorpamplona.amethyst.commons.ui" + compileSdk = + libs.versions.android.compileSdk + .get() + .toInt() + minSdk = + libs.versions.android.minSdk + .get() + .toInt() + + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + } + + androidResources.enable = true + + withHostTest { + isReturnDefaultValues = true + } + + withDeviceTest { + instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + } + + // iOS targets — same compile-only spike as :commons. + iosArm64() + iosSimulatorArm64() + + // Compose Multiplatform 1.11.x ships an `org.jetbrains.compose.ui:ui-uikit` + // prebuilt Kotlin/Native cache whose CMPLayoutRegion object hard-references + // the UIKit class `UIViewLayoutRegion` (introduced in iOS 17). Linking the + // iOS *test* executable against that cache under Xcode 16.4 fails with + // ld: Undefined symbols: _OBJC_CLASS_$_UIViewLayoutRegion + // because the cached object was built for a newer simulator SDK (18.5) than + // the test binary is being linked for (14.0). Disabling the native cache for + // the iOS test binaries makes ui-uikit recompile against the active SDK, + // where the symbol resolves. See disableUiKitPrebuiltCache() above and + // https://kotl.in/disable-native-cache + targets.withType().configureEach { + binaries.withType().configureEach { + disableUiKitPrebuiltCache() + } + } + + sourceSets { + commonMain { + dependencies { + // The headless half. `api` because every composable here takes + // or returns commons types (Note, User, ViewModels, states). + api(project(":commons")) + api(project(":quartz")) + + // Compose Multiplatform + implementation(libs.jetbrains.compose.ui) + implementation(libs.jetbrains.compose.foundation) + implementation(libs.jetbrains.compose.runtime) + implementation(libs.jetbrains.compose.material3) + implementation(libs.jetbrains.compose.ui.tooling.preview) + + // Lifecycle (KMP since 2.8.0). lifecycle-runtime-compose ships + // iOS variants; lifecycle-viewmodel-compose (the viewModel() + // Composable helper) is Android-only and lives in jvmAndroid. + implementation(libs.androidx.lifecycle.viewmodel) + implementation(libs.androidx.lifecycle.runtime.compose) + + // Image loading (Coil 3 - KMP). The okhttp network fetcher is + // JVM-only and lives in jvmAndroid; iOS will pull coil-ktor + // when that target wires its actual. + implementation(libs.coil.compose) + + // LruCache (KMP-ready) + implementation(libs.androidx.collection) + + // Immutable collections + api(libs.kotlinx.collections.immutable) + + // Compose Multiplatform Resources (strings, fonts, napplet shell files) + implementation(libs.jetbrains.compose.components.resources) + + // KMP syntax highlighter (Apache-2.0) for the git code browser. + implementation(libs.highlights) + } + } + + commonTest { + dependencies { + implementation(libs.kotlin.test) + implementation(libs.kotlinx.coroutines.test) + } + } + + // Shared JVM code for both Android and Desktop + val jvmAndroid = + create("jvmAndroid") { + dependsOn(commonMain.get()) + dependencies { + // Coil's OkHttp network fetcher (JVM-only). iOS will use + // coil-ktor when the iOS Compose UI ships. + implementation(libs.coil.okhttp) + + // OkHttp for the Blossom read-auth Coil fetcher. + implementation(libs.okhttp) + + // Markdown rendering (richtext-commonmark). The single + // consumer (RenderMarkdown.kt) lives in jvmAndroid. + // iOS support pending Phase 3 markdown decision. + implementation(libs.markdown.commonmark) + implementation(libs.markdown.ui) + implementation(libs.markdown.ui.material3) + + // viewModel() Compose helper. AndroidX publishes this + // artifact for android/jvmStubs/linuxx64Stubs but not iOS, + // so it stays in jvmAndroid until we either swap to the + // org.jetbrains.androidx.lifecycle variant or accept a + // platform-specific ViewModel access pattern on iOS. + implementation(libs.androidx.lifecycle.viewmodel.compose) + } + } + + jvmMain { + dependsOn(jvmAndroid) + dependencies { + // Desktop-specific Compose + implementation(compose.desktop.currentOs) + implementation(libs.jetbrains.compose.ui.tooling) + } + } + + androidMain { + dependsOn(jvmAndroid) + dependencies { + // Android-specific Compose tooling + implementation(libs.androidx.ui.tooling.preview) + } + } + + // iOS intermediate so iosArm64Main and iosSimulatorArm64Main share code. + val iosMain = + create("iosMain") { + dependsOn(commonMain.get()) + } + getByName("iosArm64Main").dependsOn(iosMain) + getByName("iosSimulatorArm64Main").dependsOn(iosMain) + + // Skiko-backed targets (desktop JVM + iOS) share pixel-format helpers + // (org.jetbrains.skia.* resolves on both through Compose). Android is + // deliberately NOT in this set — it renders through android.graphics. + val skikoMain = + create("skikoMain") { + dependsOn(commonMain.get()) + } + getByName("jvmMain").dependsOn(skikoMain) + iosMain.dependsOn(skikoMain) + + getByName("androidHostTest") { + dependencies { + implementation(libs.junit) + } + } + + getByName("androidDeviceTest") { + dependencies { + implementation(libs.androidx.junit) + implementation(libs.androidx.espresso.core) + } + } + } +} + +compose.resources { + publicResClass = true + // Kept on the pre-split package so `Res` imports in every consumer + // (amethyst, desktopApp, nappletHost) keep resolving unchanged. + packageOfResClass = "com.vitorpamplona.amethyst.commons.resources" + generateResClass = always +} + +// iOS purity gate — same shape as :quartz / :commons verifyKmpPurity. +// commonMain here must stay free of JVM-only JSON / HTTP deps. +val verifyKmpPurity by tasks.registering { + group = "verification" + description = "Fails if iOS-targeted source sets import JVM-only deps." + val checkedDirs = + listOf( + "src/commonMain", "src/commonTest", + "src/appleMain", "src/appleTest", + "src/nativeMain", "src/nativeTest", + "src/iosMain", "src/iosTest", + "src/skikoMain", "src/skikoTest", + "src/iosArm64Main", "src/iosArm64Test", + "src/iosSimulatorArm64Main", "src/iosSimulatorArm64Test", + "src/linuxMain", "src/linuxTest", + "src/linuxX64Main", "src/linuxX64Test", + "src/macosMain", "src/macosTest", + "src/macosArm64Main", "src/macosArm64Test", + ).map { layout.projectDirectory.dir(it).asFile } + .filter { it.exists() } + inputs.files(checkedDirs) + doLast { + // Each pattern is paired with a short hint so the failure message + // points at the canonical KMP replacement. + val forbidden = + listOf( + "com.fasterxml.jackson" to "Jackson is JVM-only — use kotlinx.serialization", + "okhttp3" to "OkHttp is JVM-only — wrap behind expect/actual or use Ktor on iOS", + "System.currentTimeMillis" to "use TimeUtils.now()", + "Thread.sleep" to "use kotlinx.coroutines.delay or platform-specific actual", + "java.util.UUID" to "use kotlin.uuid.Uuid", + "kotlin.jvm.Synchronized" to "use KmpLock.withLock {}", + // The bare call, not just the annotation: `synchronized(lock) {}` resolves + // from kotlin-stdlib-jvm with no import, so it compiles on Android/JVM and + // only fails at the iOS compile step. Catch it here instead. + "synchronized(" to "`synchronized` is JVM-only — use KmpLock.withLock {}", + "kotlin.jvm.Volatile" to "use kotlin.concurrent.Volatile", + ) + val offenders = + checkedDirs.flatMap { dir -> + dir.walkTopDown() + .filter { it.isFile && it.extension == "kt" } + .flatMap { file -> + file.readLines().withIndex().mapNotNull { (idx, line) -> + val trimmed = line.trimStart() + // Skip KDoc / line-comment lines — those legitimately + // mention forbidden names (migration notes, doc refs). + if (trimmed.startsWith("//") || trimmed.startsWith("*") || trimmed.startsWith("/*")) { + return@mapNotNull null + } + forbidden.firstOrNull { (pattern, _) -> line.contains(pattern) }?.let { (hit, hint) -> + "${file.relativeTo(rootDir)}:${idx + 1}: '$hit' — $hint" + } + } + } + } + if (offenders.isNotEmpty()) { + throw GradleException( + "iOS-targeted source sets must not reference JVM-only APIs. " + + "Move the offending code to jvmAndroid/ or behind an expect/actual:\n " + + offenders.joinToString("\n "), + ) + } + } +} + +tasks.named("check").configure { dependsOn(verifyKmpPurity) } diff --git a/commonsUI/consumer-rules.pro b/commonsUI/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/commonsUI/proguard-rules.pro b/commonsUI/proguard-rules.pro new file mode 100644 index 0000000000..0bf7b32616 --- /dev/null +++ b/commonsUI/proguard-rules.pro @@ -0,0 +1,24 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +-keep class com.vitorpamplona.quartz.** { *; } +-keep class com.vitorpamplona.amethyst.** { *; } \ No newline at end of file diff --git a/commons/src/androidDeviceTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensionTest.kt b/commonsUI/src/androidDeviceTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensionTest.kt similarity index 100% rename from commons/src/androidDeviceTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensionTest.kt rename to commonsUI/src/androidDeviceTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensionTest.kt diff --git a/commonsUI/src/androidMain/AndroidManifest.xml b/commonsUI/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000000..44008a4332 --- /dev/null +++ b/commonsUI/src/androidMain/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/commons/src/androidMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.android.kt b/commonsUI/src/androidMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.android.kt similarity index 100% rename from commons/src/androidMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.android.kt rename to commonsUI/src/androidMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.android.kt diff --git a/commons/src/commonMain/composeResources/files/napplet/shell.html b/commonsUI/src/commonMain/composeResources/files/napplet/shell.html similarity index 100% rename from commons/src/commonMain/composeResources/files/napplet/shell.html rename to commonsUI/src/commonMain/composeResources/files/napplet/shell.html diff --git a/commons/src/commonMain/composeResources/files/napplet/shim.js b/commonsUI/src/commonMain/composeResources/files/napplet/shim.js similarity index 100% rename from commons/src/commonMain/composeResources/files/napplet/shim.js rename to commonsUI/src/commonMain/composeResources/files/napplet/shim.js diff --git a/commons/src/commonMain/composeResources/font/amethyst_icons.ttf b/commonsUI/src/commonMain/composeResources/font/amethyst_icons.ttf similarity index 100% rename from commons/src/commonMain/composeResources/font/amethyst_icons.ttf rename to commonsUI/src/commonMain/composeResources/font/amethyst_icons.ttf diff --git a/commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf b/commonsUI/src/commonMain/composeResources/font/material_symbols_outlined.ttf similarity index 100% rename from commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf rename to commonsUI/src/commonMain/composeResources/font/material_symbols_outlined.ttf diff --git a/commons/src/commonMain/composeResources/values-ar-rSA/strings.xml b/commonsUI/src/commonMain/composeResources/values-ar-rSA/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-ar-rSA/strings.xml rename to commonsUI/src/commonMain/composeResources/values-ar-rSA/strings.xml diff --git a/commons/src/commonMain/composeResources/values-bn-rBD/strings.xml b/commonsUI/src/commonMain/composeResources/values-bn-rBD/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-bn-rBD/strings.xml rename to commonsUI/src/commonMain/composeResources/values-bn-rBD/strings.xml diff --git a/commons/src/commonMain/composeResources/values-cs/strings.xml b/commonsUI/src/commonMain/composeResources/values-cs/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-cs/strings.xml rename to commonsUI/src/commonMain/composeResources/values-cs/strings.xml diff --git a/commons/src/commonMain/composeResources/values-de-rDE/strings.xml b/commonsUI/src/commonMain/composeResources/values-de-rDE/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-de-rDE/strings.xml rename to commonsUI/src/commonMain/composeResources/values-de-rDE/strings.xml diff --git a/commons/src/commonMain/composeResources/values-de/strings.xml b/commonsUI/src/commonMain/composeResources/values-de/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-de/strings.xml rename to commonsUI/src/commonMain/composeResources/values-de/strings.xml diff --git a/commons/src/commonMain/composeResources/values-el-rGR/strings.xml b/commonsUI/src/commonMain/composeResources/values-el-rGR/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-el-rGR/strings.xml rename to commonsUI/src/commonMain/composeResources/values-el-rGR/strings.xml diff --git a/commons/src/commonMain/composeResources/values-en-rGB/strings.xml b/commonsUI/src/commonMain/composeResources/values-en-rGB/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-en-rGB/strings.xml rename to commonsUI/src/commonMain/composeResources/values-en-rGB/strings.xml diff --git a/commons/src/commonMain/composeResources/values-eo-rUY/strings.xml b/commonsUI/src/commonMain/composeResources/values-eo-rUY/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-eo-rUY/strings.xml rename to commonsUI/src/commonMain/composeResources/values-eo-rUY/strings.xml diff --git a/commons/src/commonMain/composeResources/values-eo/strings.xml b/commonsUI/src/commonMain/composeResources/values-eo/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-eo/strings.xml rename to commonsUI/src/commonMain/composeResources/values-eo/strings.xml diff --git a/commons/src/commonMain/composeResources/values-es-rES/strings.xml b/commonsUI/src/commonMain/composeResources/values-es-rES/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-es-rES/strings.xml rename to commonsUI/src/commonMain/composeResources/values-es-rES/strings.xml diff --git a/commons/src/commonMain/composeResources/values-es-rMX/strings.xml b/commonsUI/src/commonMain/composeResources/values-es-rMX/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-es-rMX/strings.xml rename to commonsUI/src/commonMain/composeResources/values-es-rMX/strings.xml diff --git a/commons/src/commonMain/composeResources/values-es-rUS/strings.xml b/commonsUI/src/commonMain/composeResources/values-es-rUS/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-es-rUS/strings.xml rename to commonsUI/src/commonMain/composeResources/values-es-rUS/strings.xml diff --git a/commons/src/commonMain/composeResources/values-es/strings.xml b/commonsUI/src/commonMain/composeResources/values-es/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-es/strings.xml rename to commonsUI/src/commonMain/composeResources/values-es/strings.xml diff --git a/commons/src/commonMain/composeResources/values-fa-rIR/strings.xml b/commonsUI/src/commonMain/composeResources/values-fa-rIR/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-fa-rIR/strings.xml rename to commonsUI/src/commonMain/composeResources/values-fa-rIR/strings.xml diff --git a/commons/src/commonMain/composeResources/values-fa/strings.xml b/commonsUI/src/commonMain/composeResources/values-fa/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-fa/strings.xml rename to commonsUI/src/commonMain/composeResources/values-fa/strings.xml diff --git a/commons/src/commonMain/composeResources/values-fi-rFI/strings.xml b/commonsUI/src/commonMain/composeResources/values-fi-rFI/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-fi-rFI/strings.xml rename to commonsUI/src/commonMain/composeResources/values-fi-rFI/strings.xml diff --git a/commons/src/commonMain/composeResources/values-fr-rCA/strings.xml b/commonsUI/src/commonMain/composeResources/values-fr-rCA/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-fr-rCA/strings.xml rename to commonsUI/src/commonMain/composeResources/values-fr-rCA/strings.xml diff --git a/commons/src/commonMain/composeResources/values-fr-rFR/strings.xml b/commonsUI/src/commonMain/composeResources/values-fr-rFR/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-fr-rFR/strings.xml rename to commonsUI/src/commonMain/composeResources/values-fr-rFR/strings.xml diff --git a/commons/src/commonMain/composeResources/values-fr/strings.xml b/commonsUI/src/commonMain/composeResources/values-fr/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-fr/strings.xml rename to commonsUI/src/commonMain/composeResources/values-fr/strings.xml diff --git a/commons/src/commonMain/composeResources/values-hi-rIN/strings.xml b/commonsUI/src/commonMain/composeResources/values-hi-rIN/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-hi-rIN/strings.xml rename to commonsUI/src/commonMain/composeResources/values-hi-rIN/strings.xml diff --git a/commons/src/commonMain/composeResources/values-hu-rHU/strings.xml b/commonsUI/src/commonMain/composeResources/values-hu-rHU/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-hu-rHU/strings.xml rename to commonsUI/src/commonMain/composeResources/values-hu-rHU/strings.xml diff --git a/commons/src/commonMain/composeResources/values-in-rID/strings.xml b/commonsUI/src/commonMain/composeResources/values-in-rID/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-in-rID/strings.xml rename to commonsUI/src/commonMain/composeResources/values-in-rID/strings.xml diff --git a/commons/src/commonMain/composeResources/values-in/strings.xml b/commonsUI/src/commonMain/composeResources/values-in/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-in/strings.xml rename to commonsUI/src/commonMain/composeResources/values-in/strings.xml diff --git a/commons/src/commonMain/composeResources/values-it-rIT/strings.xml b/commonsUI/src/commonMain/composeResources/values-it-rIT/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-it-rIT/strings.xml rename to commonsUI/src/commonMain/composeResources/values-it-rIT/strings.xml diff --git a/commons/src/commonMain/composeResources/values-ja-rJP/strings.xml b/commonsUI/src/commonMain/composeResources/values-ja-rJP/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-ja-rJP/strings.xml rename to commonsUI/src/commonMain/composeResources/values-ja-rJP/strings.xml diff --git a/commons/src/commonMain/composeResources/values-ja/strings.xml b/commonsUI/src/commonMain/composeResources/values-ja/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-ja/strings.xml rename to commonsUI/src/commonMain/composeResources/values-ja/strings.xml diff --git a/commons/src/commonMain/composeResources/values-ko-rKR/strings.xml b/commonsUI/src/commonMain/composeResources/values-ko-rKR/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-ko-rKR/strings.xml rename to commonsUI/src/commonMain/composeResources/values-ko-rKR/strings.xml diff --git a/commons/src/commonMain/composeResources/values-lv-rLV/strings.xml b/commonsUI/src/commonMain/composeResources/values-lv-rLV/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-lv-rLV/strings.xml rename to commonsUI/src/commonMain/composeResources/values-lv-rLV/strings.xml diff --git a/commons/src/commonMain/composeResources/values-nl-rBE/strings.xml b/commonsUI/src/commonMain/composeResources/values-nl-rBE/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-nl-rBE/strings.xml rename to commonsUI/src/commonMain/composeResources/values-nl-rBE/strings.xml diff --git a/commons/src/commonMain/composeResources/values-nl-rNL/strings.xml b/commonsUI/src/commonMain/composeResources/values-nl-rNL/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-nl-rNL/strings.xml rename to commonsUI/src/commonMain/composeResources/values-nl-rNL/strings.xml diff --git a/commons/src/commonMain/composeResources/values-nl/strings.xml b/commonsUI/src/commonMain/composeResources/values-nl/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-nl/strings.xml rename to commonsUI/src/commonMain/composeResources/values-nl/strings.xml diff --git a/commons/src/commonMain/composeResources/values-pl-rPL/strings.xml b/commonsUI/src/commonMain/composeResources/values-pl-rPL/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-pl-rPL/strings.xml rename to commonsUI/src/commonMain/composeResources/values-pl-rPL/strings.xml diff --git a/commons/src/commonMain/composeResources/values-pt-rBR/strings.xml b/commonsUI/src/commonMain/composeResources/values-pt-rBR/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-pt-rBR/strings.xml rename to commonsUI/src/commonMain/composeResources/values-pt-rBR/strings.xml diff --git a/commons/src/commonMain/composeResources/values-pt-rPT/strings.xml b/commonsUI/src/commonMain/composeResources/values-pt-rPT/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-pt-rPT/strings.xml rename to commonsUI/src/commonMain/composeResources/values-pt-rPT/strings.xml diff --git a/commons/src/commonMain/composeResources/values-ru-rRU/strings.xml b/commonsUI/src/commonMain/composeResources/values-ru-rRU/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-ru-rRU/strings.xml rename to commonsUI/src/commonMain/composeResources/values-ru-rRU/strings.xml diff --git a/commons/src/commonMain/composeResources/values-ru-rUA/strings.xml b/commonsUI/src/commonMain/composeResources/values-ru-rUA/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-ru-rUA/strings.xml rename to commonsUI/src/commonMain/composeResources/values-ru-rUA/strings.xml diff --git a/commons/src/commonMain/composeResources/values-ru/strings.xml b/commonsUI/src/commonMain/composeResources/values-ru/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-ru/strings.xml rename to commonsUI/src/commonMain/composeResources/values-ru/strings.xml diff --git a/commons/src/commonMain/composeResources/values-sl-rSI/strings.xml b/commonsUI/src/commonMain/composeResources/values-sl-rSI/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-sl-rSI/strings.xml rename to commonsUI/src/commonMain/composeResources/values-sl-rSI/strings.xml diff --git a/commons/src/commonMain/composeResources/values-sr-rSP/strings.xml b/commonsUI/src/commonMain/composeResources/values-sr-rSP/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-sr-rSP/strings.xml rename to commonsUI/src/commonMain/composeResources/values-sr-rSP/strings.xml diff --git a/commons/src/commonMain/composeResources/values-sv-rSE/strings.xml b/commonsUI/src/commonMain/composeResources/values-sv-rSE/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-sv-rSE/strings.xml rename to commonsUI/src/commonMain/composeResources/values-sv-rSE/strings.xml diff --git a/commons/src/commonMain/composeResources/values-sw/strings.xml b/commonsUI/src/commonMain/composeResources/values-sw/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-sw/strings.xml rename to commonsUI/src/commonMain/composeResources/values-sw/strings.xml diff --git a/commons/src/commonMain/composeResources/values-ta-rIN/strings.xml b/commonsUI/src/commonMain/composeResources/values-ta-rIN/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-ta-rIN/strings.xml rename to commonsUI/src/commonMain/composeResources/values-ta-rIN/strings.xml diff --git a/commons/src/commonMain/composeResources/values-ta/strings.xml b/commonsUI/src/commonMain/composeResources/values-ta/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-ta/strings.xml rename to commonsUI/src/commonMain/composeResources/values-ta/strings.xml diff --git a/commons/src/commonMain/composeResources/values-th-rTH/strings.xml b/commonsUI/src/commonMain/composeResources/values-th-rTH/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-th-rTH/strings.xml rename to commonsUI/src/commonMain/composeResources/values-th-rTH/strings.xml diff --git a/commons/src/commonMain/composeResources/values-th/strings.xml b/commonsUI/src/commonMain/composeResources/values-th/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-th/strings.xml rename to commonsUI/src/commonMain/composeResources/values-th/strings.xml diff --git a/commons/src/commonMain/composeResources/values-tr-rTR/strings.xml b/commonsUI/src/commonMain/composeResources/values-tr-rTR/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-tr-rTR/strings.xml rename to commonsUI/src/commonMain/composeResources/values-tr-rTR/strings.xml diff --git a/commons/src/commonMain/composeResources/values-tr/strings.xml b/commonsUI/src/commonMain/composeResources/values-tr/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-tr/strings.xml rename to commonsUI/src/commonMain/composeResources/values-tr/strings.xml diff --git a/commons/src/commonMain/composeResources/values-uk-rUA/strings.xml b/commonsUI/src/commonMain/composeResources/values-uk-rUA/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-uk-rUA/strings.xml rename to commonsUI/src/commonMain/composeResources/values-uk-rUA/strings.xml diff --git a/commons/src/commonMain/composeResources/values-uk/strings.xml b/commonsUI/src/commonMain/composeResources/values-uk/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-uk/strings.xml rename to commonsUI/src/commonMain/composeResources/values-uk/strings.xml diff --git a/commons/src/commonMain/composeResources/values-uz-rUZ/strings.xml b/commonsUI/src/commonMain/composeResources/values-uz-rUZ/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-uz-rUZ/strings.xml rename to commonsUI/src/commonMain/composeResources/values-uz-rUZ/strings.xml diff --git a/commons/src/commonMain/composeResources/values-vi-rVN/strings.xml b/commonsUI/src/commonMain/composeResources/values-vi-rVN/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-vi-rVN/strings.xml rename to commonsUI/src/commonMain/composeResources/values-vi-rVN/strings.xml diff --git a/commons/src/commonMain/composeResources/values-zh-rCN/strings.xml b/commonsUI/src/commonMain/composeResources/values-zh-rCN/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-zh-rCN/strings.xml rename to commonsUI/src/commonMain/composeResources/values-zh-rCN/strings.xml diff --git a/commons/src/commonMain/composeResources/values-zh-rHK/strings.xml b/commonsUI/src/commonMain/composeResources/values-zh-rHK/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-zh-rHK/strings.xml rename to commonsUI/src/commonMain/composeResources/values-zh-rHK/strings.xml diff --git a/commons/src/commonMain/composeResources/values-zh-rSG/strings.xml b/commonsUI/src/commonMain/composeResources/values-zh-rSG/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-zh-rSG/strings.xml rename to commonsUI/src/commonMain/composeResources/values-zh-rSG/strings.xml diff --git a/commons/src/commonMain/composeResources/values-zh-rTW/strings.xml b/commonsUI/src/commonMain/composeResources/values-zh-rTW/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-zh-rTW/strings.xml rename to commonsUI/src/commonMain/composeResources/values-zh-rTW/strings.xml diff --git a/commons/src/commonMain/composeResources/values-zh/strings.xml b/commonsUI/src/commonMain/composeResources/values-zh/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values-zh/strings.xml rename to commonsUI/src/commonMain/composeResources/values-zh/strings.xml diff --git a/commons/src/commonMain/composeResources/values/strings.xml b/commonsUI/src/commonMain/composeResources/values/strings.xml similarity index 100% rename from commons/src/commonMain/composeResources/values/strings.xml rename to commonsUI/src/commonMain/composeResources/values/strings.xml diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/AudioVisualizer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/AudioVisualizer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/AudioVisualizer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/AudioVisualizer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/SpectrumCanvas.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/SpectrumCanvas.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/SpectrumCanvas.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/SpectrumCanvas.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistry.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistry.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistry.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistry.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRenderer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRenderer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRenderer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRenderer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/AuroraRenderer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/AuroraRenderer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/AuroraRenderer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/AuroraRenderer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/BarsRenderer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/BarsRenderer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/BarsRenderer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/BarsRenderer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/OffRenderer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/OffRenderer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/OffRenderer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/OffRenderer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/RadialRenderer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/RadialRenderer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/RadialRenderer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/RadialRenderer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/StaticRenderer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/StaticRenderer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/StaticRenderer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/StaticRenderer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/WavesRenderer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/WavesRenderer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/WavesRenderer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/audio/renderers/WavesRenderer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/favorites/FavoriteAppIcon.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/favorites/FavoriteAppIcon.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/favorites/FavoriteAppIcon.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/favorites/FavoriteAppIcon.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Amethyst.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Amethyst.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Amethyst.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Amethyst.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Btc.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Btc.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Btc.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Btc.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Cashu.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Cashu.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Cashu.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Cashu.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Coffee.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Coffee.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Coffee.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Coffee.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/CustomHashTagIcons.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/CustomHashTagIcons.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/CustomHashTagIcons.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/CustomHashTagIcons.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Flowerstr.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Flowerstr.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Flowerstr.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Flowerstr.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Footstr.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Footstr.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Footstr.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Footstr.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Gamestr.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Gamestr.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Gamestr.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Gamestr.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Grownostr.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Grownostr.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Grownostr.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Grownostr.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Lightning.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Lightning.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Lightning.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Lightning.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Mate.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Mate.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Mate.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Mate.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Nostr.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Nostr.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Nostr.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Nostr.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Plebs.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Plebs.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Plebs.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Plebs.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Skull.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Skull.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Skull.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Skull.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Tunestr.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Tunestr.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Tunestr.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Tunestr.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Weed.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Weed.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Weed.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Weed.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Zap.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Zap.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Zap.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/hashtags/Zap.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Bookmark.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Bookmark.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Bookmark.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Bookmark.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Following.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Following.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Following.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Following.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Like.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Like.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Like.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Like.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Liked.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Liked.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Liked.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Liked.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reply.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reply.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reply.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reply.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Repost.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Repost.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Repost.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Repost.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reposted.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reposted.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reposted.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Reposted.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Search.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Search.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Search.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Search.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Share.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Share.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Share.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Share.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Zap.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Zap.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Zap.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/Zap.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/ZapSplit.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/ZapSplit.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/ZapSplit.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/ZapSplit.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIcons.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIcons.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIcons.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIcons.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIconsFont.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIconsFont.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIconsFont.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/AmethystIconsFont.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/Icon.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/Icon.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/Icon.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/Icon.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbol.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbol.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbol.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbol.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolPainter.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolPainter.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolPainter.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolPainter.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsDefaults.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsDefaults.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsDefaults.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsDefaults.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsFont.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsFont.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsFont.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbolsFont.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/nip30CustomEmojis/EmojiSuggestionState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/nip30CustomEmojis/EmojiSuggestionState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/nip30CustomEmojis/EmojiSuggestionState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/nip30CustomEmojis/EmojiSuggestionState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContract.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContract.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContract.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContract.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/ArticleHeader.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/ArticleHeader.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/ArticleHeader.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/ArticleHeader.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/TableOfContents.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/TableOfContents.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/TableOfContents.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/article/TableOfContents.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownEditorState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownEditorState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownEditorState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownEditorState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownToolbar.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownToolbar.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownToolbar.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MarkdownToolbar.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MetadataPanel.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MetadataPanel.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MetadataPanel.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip23LongContent/ui/editor/MetadataPanel.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip30CustomEmojis/ui/ShowEmojiSuggestionList.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip30CustomEmojis/ui/ShowEmojiSuggestionList.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip30CustomEmojis/ui/ShowEmojiSuggestionList.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip30CustomEmojis/ui/ShowEmojiSuggestionList.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip34Git/ui/CodeHighlighter.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip34Git/ui/CodeHighlighter.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip34Git/ui/CodeHighlighter.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip34Git/ui/CodeHighlighter.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip53LiveActivities/ui/StreamSystemCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip53LiveActivities/ui/StreamSystemCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip53LiveActivities/ui/StreamSystemCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip53LiveActivities/ui/StreamSystemCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBoard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBoard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBoard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBoard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBroadcastBanner.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBroadcastBanner.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBroadcastBanner.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessBroadcastBanner.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessGameViewer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessGameViewer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessGameViewer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessGameViewer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessLobbyCards.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessLobbyCards.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessLobbyCards.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessLobbyCards.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPieceVectors.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPieceVectors.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPieceVectors.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPieceVectors.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPlayerChip.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPlayerChip.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPlayerChip.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessPlayerChip.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessSyncBanner.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessSyncBanner.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessSyncBanner.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/ChessSyncBanner.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/InteractiveChessBoard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/InteractiveChessBoard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/InteractiveChessBoard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/InteractiveChessBoard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/LiveChessGame.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/LiveChessGame.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/LiveChessGame.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/LiveChessGame.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/MoveNavigator.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/MoveNavigator.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/MoveNavigator.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/MoveNavigator.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/PGNMetadata.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/PGNMetadata.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/PGNMetadata.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip64Chess/PGNMetadata.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip85TrustedAssertions/ui/EditNicknameDialog.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip85TrustedAssertions/ui/EditNicknameDialog.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip85TrustedAssertions/ui/EditNicknameDialog.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/nip85TrustedAssertions/ui/EditNicknameDialog.kt diff --git a/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/privacylock/LocalPrivacyLockState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/privacylock/LocalPrivacyLockState.kt new file mode 100644 index 0000000000..1c8429b662 --- /dev/null +++ b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/privacylock/LocalPrivacyLockState.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * 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.privacylock + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.compositionLocalOf + +/** + * Provided once at the App composition root. Map keyed by [LockScope]; every + * scope must have an entry (see [lockStateFor] which throws when missing). + */ +val LocalPrivacyLockState = + compositionLocalOf> { + error("LocalPrivacyLockState not provided — wrap App() with CompositionLocalProvider") + } + +/** + * Convenience accessor used inside gate composables. Reads the map from the + * ambient [LocalPrivacyLockState] and returns the state holder for [scope]. + * Throws if the scope was not registered at the App root. + */ +@Composable +@ReadOnlyComposable +fun lockStateFor(scope: LockScope): PrivacyLockState = + LocalPrivacyLockState.current[scope] + ?: error("PrivacyLockState for $scope not registered at App root") diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/profile/ui/ProfileBroadcastBanner.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/profile/ui/ProfileBroadcastBanner.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/profile/ui/ProfileBroadcastBanner.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/profile/ui/ProfileBroadcastBanner.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/auth/AuthApprovalBanner.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/auth/AuthApprovalBanner.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/auth/AuthApprovalBanner.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/auth/AuthApprovalBanner.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/communities/CommunityFilterAssemblerSubscription.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/communities/CommunityFilterAssemblerSubscription.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/communities/CommunityFilterAssemblerSubscription.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/communities/CommunityFilterAssemblerSubscription.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/event/EventFinderFilterAssemblerSubscription.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/event/EventFinderFilterAssemblerSubscription.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/event/EventFinderFilterAssemblerSubscription.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/event/EventFinderFilterAssemblerSubscription.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/gitRepo/RepositoryFilterAssemblerSubscription.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/gitRepo/RepositoryFilterAssemblerSubscription.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/gitRepo/RepositoryFilterAssemblerSubscription.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/gitRepo/RepositoryFilterAssemblerSubscription.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/profile/UserProfileFilterAssemblerSubscription.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/profile/UserProfileFilterAssemblerSubscription.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/profile/UserProfileFilterAssemblerSubscription.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/profile/UserProfileFilterAssemblerSubscription.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/KeyDataSourceSubscription.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/KeyDataSourceSubscription.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/KeyDataSourceSubscription.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/KeyDataSourceSubscription.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/LifecycleAwareKeyDataSourceSubscription.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/LifecycleAwareKeyDataSourceSubscription.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/LifecycleAwareKeyDataSourceSubscription.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/LifecycleAwareKeyDataSourceSubscription.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserFinderSubscription.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserFinderSubscription.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserFinderSubscription.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserFinderSubscription.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserMetadataObservers.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserMetadataObservers.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserMetadataObservers.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/user/UserMetadataObservers.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayBanner.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayBanner.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayBanner.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayBanner.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayRow.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayRow.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayRow.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relays/health/ui/UnhealthyRelayRow.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/CachedRobohash.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/CachedRobohash.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/CachedRobohash.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/CachedRobohash.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/RobohashAssembler.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/RobohashAssembler.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/RobohashAssembler.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/RobohashAssembler.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory0Seven.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory0Seven.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory0Seven.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory0Seven.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory1Nose.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory1Nose.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory1Nose.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory1Nose.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory2HornRed.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory2HornRed.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory2HornRed.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory2HornRed.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory3Button.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory3Button.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory3Button.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory3Button.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory4Satellite.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory4Satellite.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory4Satellite.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory4Satellite.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory5Mustache.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory5Mustache.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory5Mustache.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory5Mustache.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory6Hat.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory6Hat.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory6Hat.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory6Hat.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory7Antenna.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory7Antenna.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory7Antenna.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory7Antenna.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory8Brush.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory8Brush.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory8Brush.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory8Brush.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory9Horn.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory9Horn.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory9Horn.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Accessory9Horn.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body0Trooper.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body0Trooper.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body0Trooper.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body0Trooper.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body1Thin.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body1Thin.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body1Thin.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body1Thin.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body2Thinnest.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body2Thinnest.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body2Thinnest.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body2Thinnest.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body3Front.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body3Front.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body3Front.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body3Front.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body4Round.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body4Round.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body4Round.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body4Round.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body5Neck.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body5Neck.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body5Neck.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body5Neck.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body6Ironman.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body6Ironman.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body6Ironman.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body6Ironman.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body7Neckthinner.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body7Neckthinner.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body7Neckthinner.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body7Neckthinner.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body8Big.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body8Big.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body8Big.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body8Big.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body9Huge.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body9Huge.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body9Huge.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Body9Huge.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes0Squint.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes0Squint.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes0Squint.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes0Squint.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes1Round.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes1Round.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes1Round.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes1Round.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes2Single.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes2Single.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes2Single.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes2Single.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes3Scott.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes3Scott.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes3Scott.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes3Scott.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes4Roundsingle.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes4Roundsingle.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes4Roundsingle.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes4Roundsingle.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes5Roundsmall.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes5Roundsmall.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes5Roundsmall.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes5Roundsmall.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes6Walle.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes6Walle.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes6Walle.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes6Walle.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes7Bar.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes7Bar.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes7Bar.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes7Bar.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes8Smallbar.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes8Smallbar.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes8Smallbar.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes8Smallbar.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes9Shield.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes9Shield.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes9Shield.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Eyes9Shield.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face0C3po.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face0C3po.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face0C3po.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face0C3po.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face1Rock.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face1Rock.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face1Rock.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face1Rock.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face2Long.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face2Long.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face2Long.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face2Long.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face3Oval.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face3Oval.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face3Oval.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face3Oval.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face4Cylinder.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face4Cylinder.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face4Cylinder.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face4Cylinder.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face5Baloon.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face5Baloon.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face5Baloon.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face5Baloon.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face6Triangle.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face6Triangle.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face6Triangle.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face6Triangle.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face7Bent.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face7Bent.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face7Bent.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face7Bent.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face8TriangleInv.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face8TriangleInv.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face8TriangleInv.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face8TriangleInv.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face9Square.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face9Square.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face9Square.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Face9Square.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth0Horz.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth0Horz.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth0Horz.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth0Horz.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth1Cylinder.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth1Cylinder.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth1Cylinder.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth1Cylinder.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth2Teeth.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth2Teeth.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth2Teeth.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth2Teeth.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth3Grid.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth3Grid.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth3Grid.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth3Grid.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth4Vert.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth4Vert.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth4Vert.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth4Vert.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth5Midopen.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth5Midopen.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth5Midopen.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth5Midopen.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth6Cell.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth6Cell.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth6Cell.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth6Cell.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth7Happy.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth7Happy.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth7Happy.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth7Happy.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth8Buttons.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth8Buttons.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth8Buttons.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth8Buttons.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth9Closed.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth9Closed.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth9Closed.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/robohash/parts/Mouth9Closed.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/Base64Fetcher.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/Base64Fetcher.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/Base64Fetcher.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/Base64Fetcher.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlurHashFetcher.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlurHashFetcher.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlurHashFetcher.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlurHashFetcher.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/ThumbHashFetcher.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/ThumbHashFetcher.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/ThumbHashFetcher.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/ThumbHashFetcher.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/StringRes.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/StringRes.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/StringRes.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/StringRes.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ActionButtons.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ActionButtons.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ActionButtons.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ActionButtons.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/BunkerHeartbeatIndicator.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/BunkerHeartbeatIndicator.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/BunkerHeartbeatIndicator.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/BunkerHeartbeatIndicator.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableLinks.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableLinks.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableLinks.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableLinks.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableTexts.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableTexts.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableTexts.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ClickableTexts.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ForwardingPainter.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ForwardingPainter.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ForwardingPainter.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ForwardingPainter.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GenericLoadable.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GenericLoadable.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GenericLoadable.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GenericLoadable.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GlowingCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GlowingCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GlowingCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/GlowingCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingAnimation.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingAnimation.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingAnimation.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingAnimation.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/LoadingState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/Nip05OrPubkeyLine.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/Nip05OrPubkeyLine.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/Nip05OrPubkeyLine.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/Nip05OrPubkeyLine.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/RobohashImage.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/RobohashImage.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/RobohashImage.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/RobohashImage.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ShimmerPlaceholder.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ShimmerPlaceholder.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ShimmerPlaceholder.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ShimmerPlaceholder.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/TranslationConfig.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/TranslationConfig.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/TranslationConfig.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/TranslationConfig.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserAvatar.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserAvatar.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserAvatar.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserAvatar.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserSearchCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserSearchCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserSearchCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UserSearchCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ZonedSwipeModifier.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ZonedSwipeModifier.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ZonedSwipeModifier.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/components/ZonedSwipeModifier.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/DmHistoryLoadingCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/DmHistoryLoadingCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/DmHistoryLoadingCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/DmHistoryLoadingCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChip.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChip.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChip.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChip.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarker.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarker.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarker.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarker.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/StickToTopOnPrepend.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/StickToTopOnPrepend.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/StickToTopOnPrepend.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/StickToTopOnPrepend.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarNestedScroll.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarNestedScroll.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarNestedScroll.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarNestedScroll.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/DisappearingBarState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/GenericRepostLayout.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/GenericRepostLayout.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/GenericRepostLayout.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/GenericRepostLayout.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/PaddingMerge.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/PaddingMerge.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/PaddingMerge.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/layouts/PaddingMerge.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ActivityCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ActivityCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ActivityCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ActivityCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/BirdexCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/BirdexCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/BirdexCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/BirdexCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarCollectionCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarCollectionCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarCollectionCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarCollectionCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarRsvpCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarRsvpCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarRsvpCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CalendarRsvpCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CodeSnippetCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CodeSnippetCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CodeSnippetCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CodeSnippetCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CollapsedSpamNote.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CollapsedSpamNote.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CollapsedSpamNote.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/CollapsedSpamNote.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/EcashMintCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/EcashMintCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/EcashMintCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/EcashMintCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitDiffView.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitDiffView.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitDiffView.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitDiffView.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitStatusPill.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitStatusPill.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitStatusPill.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/GitStatusPill.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HeaderPill.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HeaderPill.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HeaderPill.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HeaderPill.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HighlightedQuote.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HighlightedQuote.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HighlightedQuote.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/HighlightedQuote.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastChips.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastChips.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastChips.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastChips.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastSoundbites.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastSoundbites.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastSoundbites.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastSoundbites.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastValueSplits.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastValueSplits.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastValueSplits.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/PodcastValueSplits.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/Ps1SaveCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/Ps1SaveCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/Ps1SaveCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/Ps1SaveCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/QuietMark.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/QuietMark.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/QuietMark.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/QuietMark.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RelayDiscoveryCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RelayDiscoveryCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RelayDiscoveryCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RelayDiscoveryCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyToLabel.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyToLabel.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyToLabel.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/ReplyToLabel.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RoadEventCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RoadEventCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RoadEventCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/RoadEventCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/StaticWebsiteCard.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/StaticWebsiteCard.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/StaticWebsiteCard.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/note/StaticWebsiteCard.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/notifications/CardFeedState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/notifications/CardFeedState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/notifications/CardFeedState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/notifications/CardFeedState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/CredentialPrompter.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/CredentialPrompter.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/CredentialPrompter.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/CredentialPrompter.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/IdleTimerModifier.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/IdleTimerModifier.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/IdleTimerModifier.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/IdleTimerModifier.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/LockScreen.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/LockScreen.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/LockScreen.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/LockScreen.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/MessagesLockGate.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/MessagesLockGate.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/MessagesLockGate.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/MessagesLockGate.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/WalletLockGate.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/WalletLockGate.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/WalletLockGate.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/privacylock/WalletLockGate.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/CustomEmojiRenderer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/CustomEmojiRenderer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/CustomEmojiRenderer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/CustomEmojiRenderer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/HashtagIcons.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/HashtagIcons.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/HashtagIcons.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/HashtagIcons.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/README.md b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/README.md similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/README.md rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/README.md diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextSegmentRenderer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextSegmentRenderer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextSegmentRenderer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextSegmentRenderer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextViewer.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextViewer.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextViewer.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/richtext/RichTextViewer.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/screens/PlaceholderScreens.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/screens/PlaceholderScreens.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/screens/PlaceholderScreens.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/screens/PlaceholderScreens.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchCalendarPicker.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchCalendarPicker.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchCalendarPicker.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchCalendarPicker.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldSources.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldSources.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldSources.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldSources.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchFieldState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchPeoplePicker.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchPeoplePicker.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchPeoplePicker.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchPeoplePicker.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenStyles.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenStyles.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenStyles.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenStyles.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformation.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformation.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformation.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformation.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/TokenizedSearchField.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/TokenizedSearchField.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/TokenizedSearchField.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/search/TokenizedSearchField.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningAwareButton.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningAwareButton.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningAwareButton.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningAwareButton.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningStatusBar.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningStatusBar.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningStatusBar.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/signing/SigningStatusBar.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/AsyncCachedState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/AsyncCachedState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/AsyncCachedState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/AsyncCachedState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/CachedState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/CachedState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/CachedState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/state/CachedState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldStateExtensions.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldStateExtensions.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldStateExtensions.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldStateExtensions.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensions.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensions.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensions.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/TextFieldValueExtensions.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/UiThread.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/UiThread.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/UiThread.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/text/UiThread.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ChatTheme.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ChatTheme.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ChatTheme.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ChatTheme.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Colors.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Colors.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Colors.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Colors.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/NoteBorders.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/NoteBorders.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/NoteBorders.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/NoteBorders.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Sizes.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Sizes.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Sizes.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/Sizes.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ThemeExtensions.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ThemeExtensions.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ThemeExtensions.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/theme/ThemeExtensions.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/thread/ThreadModifiers.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/thread/ThreadModifiers.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/thread/ThreadModifiers.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/ui/thread/ThreadModifiers.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/ChatNewMessageState.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/ChatNewMessageState.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/ChatNewMessageState.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/ChatNewMessageState.kt diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/thread/LevelFeedViewModel.kt b/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/thread/LevelFeedViewModel.kt similarity index 100% rename from commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/thread/LevelFeedViewModel.kt rename to commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/viewmodels/thread/LevelFeedViewModel.kt diff --git a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistryTest.kt b/commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistryTest.kt similarity index 100% rename from commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistryTest.kt rename to commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/audio/VisualizerRegistryTest.kt diff --git a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContractTest.kt b/commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContractTest.kt similarity index 100% rename from commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContractTest.kt rename to commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletWebContractTest.kt diff --git a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarkerTest.kt b/commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarkerTest.kt similarity index 100% rename from commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarkerTest.kt rename to commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/RelayReachMarkerTest.kt diff --git a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformationTest.kt b/commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformationTest.kt similarity index 100% rename from commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformationTest.kt rename to commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/search/SearchTokenTransformationTest.kt diff --git a/commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/AppendSignatureTest.kt b/commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/AppendSignatureTest.kt similarity index 100% rename from commons/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/AppendSignatureTest.kt rename to commonsUI/src/commonTest/kotlin/com/vitorpamplona/amethyst/commons/ui/text/AppendSignatureTest.kt diff --git a/commons/src/iosMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.ios.kt b/commonsUI/src/iosMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.ios.kt similarity index 100% rename from commons/src/iosMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.ios.kt rename to commonsUI/src/iosMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.ios.kt diff --git a/commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlossomReadAuthFetcher.kt b/commonsUI/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlossomReadAuthFetcher.kt similarity index 100% rename from commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlossomReadAuthFetcher.kt rename to commonsUI/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/service/image/BlossomReadAuthFetcher.kt diff --git a/commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UrlPreviewState.kt b/commonsUI/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UrlPreviewState.kt similarity index 100% rename from commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UrlPreviewState.kt rename to commonsUI/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/components/UrlPreviewState.kt diff --git a/commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/markdown/RenderMarkdown.kt b/commonsUI/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/markdown/RenderMarkdown.kt similarity index 100% rename from commons/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/markdown/RenderMarkdown.kt rename to commonsUI/src/jvmAndroid/kotlin/com/vitorpamplona/amethyst/commons/ui/markdown/RenderMarkdown.kt diff --git a/commons/src/jvmMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.jvm.kt b/commonsUI/src/jvmMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.jvm.kt similarity index 100% rename from commons/src/jvmMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.jvm.kt rename to commonsUI/src/jvmMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/CoilImageBridge.jvm.kt diff --git a/commons/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletShellResourceTest.kt b/commonsUI/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletShellResourceTest.kt similarity index 100% rename from commons/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletShellResourceTest.kt rename to commonsUI/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/napplet/NappletShellResourceTest.kt diff --git a/commons/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipStateTest.kt b/commonsUI/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipStateTest.kt similarity index 100% rename from commons/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipStateTest.kt rename to commonsUI/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/ui/feeds/NewPostsChipStateTest.kt diff --git a/commons/src/skikoMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/SkiaBitmapConverter.kt b/commonsUI/src/skikoMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/SkiaBitmapConverter.kt similarity index 100% rename from commons/src/skikoMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/SkiaBitmapConverter.kt rename to commonsUI/src/skikoMain/kotlin/com/vitorpamplona/amethyst/commons/service/image/SkiaBitmapConverter.kt diff --git a/crowdin.yml b/crowdin.yml index f2aae05f9d..2b8aa58db0 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -31,8 +31,8 @@ files: # commons (Compose Multiplatform resources, consumed by amethyst + desktopApp). # Same android layout + language mapping as the amethyst source so a key reads # identically whichever module owns it after the note-ui-commons extraction. - - source: commons/src/commonMain/composeResources/values/strings.xml - translation: commons/src/commonMain/composeResources/values-%android_code%/%original_file_name% + - source: commonsUI/src/commonMain/composeResources/values/strings.xml + translation: commonsUI/src/commonMain/composeResources/values-%android_code%/%original_file_name% type: android skip_untranslated_strings: true languages_mapping: diff --git a/desktopApp/build.gradle.kts b/desktopApp/build.gradle.kts index 7e3fea51fb..49f0fe025b 100644 --- a/desktopApp/build.gradle.kts +++ b/desktopApp/build.gradle.kts @@ -35,8 +35,9 @@ dependencies { // Quartz Nostr library (will use JVM target) implementation(project(":quartz")) - // Commons library + // Commons library (headless) + its Compose UI half implementation(project(":commons")) + implementation(project(":commonsUI")) // Lifecycle ViewModel (needed to access ViewModel supertype from commons) implementation(libs.androidx.lifecycle.viewmodel.compose) diff --git a/nappletHost/build.gradle.kts b/nappletHost/build.gradle.kts index cec65e1ef4..f10b0653c1 100644 --- a/nappletHost/build.gradle.kts +++ b/nappletHost/build.gradle.kts @@ -33,10 +33,12 @@ kotlin { } dependencies { - // The sandbox runtime depends ONLY on the protocol/contract (commons) and Nostr resolution + // The sandbox runtime depends ONLY on the protocol/contract (commons), the shell/shim + // Compose resources it serves (commonsUI's NappletWebContract) and Nostr resolution // (quartz) — never on :amethyst. This makes it impossible for the `:napplet` process code to // reach for Amethyst.instance / LocalCache / Account (which don't exist in that process). implementation(project(":commons")) + implementation(project(":commonsUI")) implementation(project(":quartz")) implementation(libs.androidx.core.ktx) diff --git a/settings.gradle.kts b/settings.gradle.kts index 260b92e6e1..dd0b7da848 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,6 +37,7 @@ include(":baselineprofile") include(":quartz") include(":geode") include(":commons") +include(":commonsUI") include(":quic") include(":nestsClient") include(":marmotQuic") diff --git a/tools/icon-font/README.md b/tools/icon-font/README.md index f669635728..5074fdb82c 100644 --- a/tools/icon-font/README.md +++ b/tools/icon-font/README.md @@ -1,7 +1,7 @@ # Amethyst icon font Builds `amethyst_icons.ttf` from the Kotlin `ImageVector` icons in -`commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/`. +`commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/`. ## Why diff --git a/tools/ime-test/shim-events.mjs b/tools/ime-test/shim-events.mjs index acb5a62dc1..a2bb794ca1 100644 --- a/tools/ime-test/shim-events.mjs +++ b/tools/ime-test/shim-events.mjs @@ -1,6 +1,6 @@ // Regression test for the embedded-WebView IME relay's page→host protocol. // -// Loads the REAL shim (commons/src/commonMain/composeResources/files/napplet/shim.js) into real Chromium +// Loads the REAL shim (commonsUI/src/commonMain/composeResources/files/napplet/shim.js) into real Chromium // with the embedded-surface flags set, drives genuine focus/tap/blur gestures, and asserts the `ime.*` // envelopes it emits. This is the only honest automated coverage for this code: the half worth protecting // is the page↔host contract (real browser focus/gesture behavior), which no JVM unit test of the host-side @@ -17,7 +17,7 @@ import { fileURLToPath } from 'node:url' import { dirname, resolve } from 'node:path' const HERE = dirname(fileURLToPath(import.meta.url)) -const SHIM = process.argv[2] ?? resolve(HERE, '../../commons/src/commonMain/composeResources/files/napplet/shim.js') +const SHIM = process.argv[2] ?? resolve(HERE, '../../commonsUI/src/commonMain/composeResources/files/napplet/shim.js') const CHROMIUM = process.env.CHROMIUM_PATH ?? '/opt/pw-browsers/chromium-1194/chrome-linux/chrome' const HTML = `ime diff --git a/tools/material-symbols-subset/README.md b/tools/material-symbols-subset/README.md index 9db8fea879..c3c428c8c8 100644 --- a/tools/material-symbols-subset/README.md +++ b/tools/material-symbols-subset/README.md @@ -1,11 +1,11 @@ # Material Symbols Subset The font shipped at -`commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf` +`commonsUI/src/commonMain/composeResources/font/material_symbols_outlined.ttf` is a **subset** of Google's [Material Symbols Outlined](https://github.com/google/material-design-icons) variable font, trimmed to only the codepoints referenced from -`commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt`. +`commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt`. | | Full upstream | Subset | |---|---|---| diff --git a/tools/material-symbols-subset/subset.sh b/tools/material-symbols-subset/subset.sh index 640964d342..8f9fe9f365 100755 --- a/tools/material-symbols-subset/subset.sh +++ b/tools/material-symbols-subset/subset.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Subset commons/.../material_symbols_outlined.ttf to only the codepoints +# Subset commonsUI/.../material_symbols_outlined.ttf to only the codepoints # referenced from MaterialSymbols.kt. The full Google variable font is ~11 MB # (≈3500 glyphs); the subset is ~410 KB. # @@ -13,13 +13,13 @@ # font from Google Fonts. # # Output: -# Overwrites commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf +# Overwrites commonsUI/src/commonMain/composeResources/font/material_symbols_outlined.ttf set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" -SYMBOLS_KT="$REPO_ROOT/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt" -TARGET="$REPO_ROOT/commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf" +SYMBOLS_KT="$REPO_ROOT/commonsUI/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/icons/symbols/MaterialSymbols.kt" +TARGET="$REPO_ROOT/commonsUI/src/commonMain/composeResources/font/material_symbols_outlined.ttf" if ! command -v pyftsubset >/dev/null 2>&1; then echo "pyftsubset not found. Install with: pip install fonttools brotli" >&2 diff --git a/tools/strings-migrate/README.md b/tools/strings-migrate/README.md index 16aa92657b..7611efed3d 100644 --- a/tools/strings-migrate/README.md +++ b/tools/strings-migrate/README.md @@ -1,7 +1,7 @@ # strings-migrate Moves string keys from the Android app's `res/` into commons Compose -resources (`commons/src/commonMain/composeResources`) across **all** +resources (`commonsUI/src/commonMain/composeResources`) across **all** locales in one shot, preserving each element byte-for-byte so Crowdin sees a pure move. Both trees are Crowdin-managed with the same android layout (see `crowdin.yml`), so a migrated key keeps its translations. diff --git a/tools/strings-migrate/migrate.py b/tools/strings-migrate/migrate.py index f7cac05e89..151eeb1f85 100755 --- a/tools/strings-migrate/migrate.py +++ b/tools/strings-migrate/migrate.py @@ -7,7 +7,7 @@ For the default locale and every values-* locale dir, each named or element is removed from amethyst/src/main/res//strings.xml and appended (before ) to - commons/src/commonMain/composeResources//strings.xml + commonsUI/src/commonMain/composeResources//strings.xml creating the commons locale file when a translation exists that commons doesn't carry yet. Elements are moved verbatim (raw XML slice), so escaping, CDATA and comments inside values survive byte-for-byte and @@ -25,7 +25,7 @@ import sys from fix_escapes import STRING_EL, fix_text, strip_android_only_attrs APP_RES = "amethyst/src/main/res" -COMMONS_RES = "commons/src/commonMain/composeResources" +COMMONS_RES = "commonsUI/src/commonMain/composeResources" NEW_FILE_TEMPLATE = '\n\n\n'