Skip to content

Move all screens into a screen/ folder#177

Open
Seifert69 wants to merge 1 commit intomainfrom
rename-take-2
Open

Move all screens into a screen/ folder#177
Seifert69 wants to merge 1 commit intomainfrom
rename-take-2

Conversation

@Seifert69
Copy link
Copy Markdown
Contributor

Recommendation from Claude. If you like it, please merge, or close it and do it another way. If you don't like it, just close it :-)

@Seifert69 Seifert69 requested a review from acarlsen March 29, 2026 03:09
@Seifert69
Copy link
Copy Markdown
Contributor Author

I changed too many things. This is now obsolete... But please review the concept anyways

@acarlsen
Copy link
Copy Markdown
Contributor

I feel like we may need to have a discussion of the overall packaged/module structure.
Here is Claudes suggestion (I agree, but it should take a lot shorter time than suggested :-) ):

Question
I feel like we have too much in chat and api module and api module should not depend on base common module, suggest a better strategy

Answer

Module Restructuring Strategy

The Core Problems

1. homebase-api (194 files) is misnamed and overloaded
It's the entire infrastructure layer — HTTP client, SQLDelight database, crypto, sync engine, file/image/video utilities, YouAuth — not just an API client.

2. homebase-common leaks all infrastructure transitively
homebase-common/build.gradle.kts:61 declares api(project(":homebase-api")). This exposes SQLDelight, FFmpeg, and the full crypto stack to every consumer of homebase-common. A UI library shouldn't do this.

3. Two lifecycle orchestrators are misplaced
AuthConnectionCoordinator and BackgroundSyncOrchestrator live in homebase-common but depend on DriveSyncManager, YouAuthFlowManager, OdinWebSocketClient — they belong in homebase-core.


Phase 1 — Decouple homebase-common (~1 day, low risk)

Step 1: Move two files to homebase-core (same id.homebase.core.* package names, zero import rewrites):

  • homebase-common/.../auth/AuthConnectionCoordinator.kthomebase-core/.../auth/
  • homebase-common/.../sync/BackgroundSyncOrchestrator.kthomebase-core/.../sync/

Step 2: In homebase-common/build.gradle.kts line 61:

// Before
api(project(":homebase-api"))

// After
implementation(project(":homebase-api"))

api()implementation() stops the full transitive exposure. homebase-chat and homebase-core already declare their own direct homebase-api dependency so nothing breaks downstream.

Verify: ./gradlew homebase-common:jvmTest homebase-chat:jvmTest androidApp:assembleDebug


Phase 2 — Split homebase-api into two modules (~1–2 weeks, medium risk)

Extract a new homebase-network module containing everything that makes or validates HTTP requests:

Moves to homebase-network Stays in homebase-storage (renamed from homebase-api)
client/ — HTTP client, all drive API providers, WebSocket client sync/DriveSyncManager, OdinDatabase, SQLDelight schema
crypto/AesCbc, AesGcm, EccKeyFunctions (these sign request headers) file/, image/, video/ — media utilities
youauth/, browser/ — OAuth flow di/StorageModule.kt
common/OdinId, SecureByteArray, UnixTimeUtc
serialization/, exception/, util/, storage/

homebase-storage then declares api(project(":homebase-network")).

After this, homebase-common can use api(project(":homebase-network")) — exposing only credentials, OdinId, and drive HTTP providers needed for image loading. No more SQLDelight or FFmpeg in the UI library's transitive graph.

Key constraint: Keep package names as id.homebase.api.* even after moving files — avoids mass import rewrites across 300+ files.

Watch out for: homebase-core/build.gradle.kts iOS framework export — currently exports homebase-api, must be updated to export homebase-storage (which transitively exports homebase-network).


Phase 3 — Split homebase-chat (~2–3 weeks, higher risk)

homebase-chat/services/ (26 files) directly calls QueryBatch, DatabaseManager, OutboxSync — persistence logic disguised as business logic. Properly separating it requires repository interfaces first.

homebase-chat-domain   — services/, data/  (depends on homebase-storage, homebase-network)
homebase-chat (UI)     — screens/, widget/ (depends on homebase-chat-domain, homebase-common)

Design the interfaces before moving files — treat this as a separate architectural initiative.


Summary

Phase Effort Risk Benefit
1: Move 2 files + change api()impl() ~1 day Low Stops SQLDelight/FFmpeg leaking through homebase-common
2: Extract homebase-network ~1–2 weeks Medium Correct naming; clean HTTP vs storage separation
3: Extract homebase-chat-domain 2–3 weeks High Testable services; smaller feature modules

Start with Phase 1 — it's a 2-file move and a 1-line change that delivers the most structural improvement per unit of risk.

@Seifert69
Copy link
Copy Markdown
Contributor Author

I like to take one step at a time though. here's another suggestion from Claude (that I deliberately didn't do first). It would probably have to go in before or as one of the very first items:

Phase 4: Package Rename — homebase-common

Context

homebase-common was historically placed under the id.homebase.core.* package namespace, which collides with homebase-core's own namespace. This rename moves all homebase-common Kotlin declarations to id.homebase.common.* to make module ownership clear, eliminate namespace collision, and match the Gradle namespace = "id.homebase.common" already set in its build.gradle.kts.

Scope constraint: Only touch files under homebase-common/src/. The homebase-core module's id.homebase.core.* packages are NOT renamed.

Collision warning: Two package subtrees exist in BOTH modules. Class-specific sed rules are required for these — not package-level rules:

  • id.homebase.core.share — homebase-common owns: ShareCacheStorage, ShareableConversation, ShareContentProcessor, ShareConversationCacheWriter, SharedContentDescriptor. homebase-core owns: ShareHandlerRegistration, registerShareHandler, unregisterShareHandler.
  • id.homebase.core.ui.navigation — homebase-common owns: ObserveAsEvents, Routes, Route. homebase-core owns: AppNavHost, AppViewModel.

Step 1 — Git checkpoint

git add -A && git commit -m "chore: pre-rename checkpoint (phase 4)"

Step 2 — Update package declarations inside homebase-common/src

Anchored to ^package so only package lines are touched (not import lines):

find homebase-common/src -name "*.kt" \
  -exec sed -i 's/^package id\.homebase\.core/package id.homebase.common/g' {} +

Verify: should show ~215 modified files, zero unchanged id.homebase.core package lines:

grep -rn "^package id\.homebase\.core" homebase-common/src --include="*.kt"
# Expected: no output

Step 3 — Rename physical directories (all 6 source sets)

Use git mv to preserve file rename history. The destination parent id/homebase/common must be created first since it doesn't exist yet.

for SS in commonMain androidMain jvmMain nativeMain webMain commonTest; do
  SRC="homebase-common/src/${SS}/kotlin/id/homebase/core"
  DST="homebase-common/src/${SS}/kotlin/id/homebase/common"
  if [ -d "$SRC" ]; then
    mkdir -p "$(dirname "$DST")"
    git mv "$SRC" "$DST"
  fi
done

Note: webMain (18 files) was missing from the original plan — it must be included.


Step 4 — Update intra-module imports inside homebase-common

Files within homebase-common import from each other using id.homebase.core.*. These are NOT covered by Step 3's package declaration sed (which only touches ^package lines) or Step 5's external sed (which excludes homebase-common/). A separate blanket pass is required.

No collision risk here — homebase-common never imports from homebase-core's collision classes.

find homebase-common/src -name "*.kt" \
  -exec sed -i 's/import id\.homebase\.core\./import id.homebase.common./g' {} +

Verify:

grep -rn "import id\.homebase\.core\." homebase-common/src --include="*.kt"
# Expected: no output (~59 imports updated)

Step 5 — Update imports in all consuming files (outside homebase-common)

5a — Unambiguous package-level replacements

These packages exist only in homebase-common (not homebase-core), so a package-level sed is safe:

find . -name "*.kt" ! -path "*/homebase-common/*" -exec sed -i \
  -e 's/import id\.homebase\.core\.audio\./import id.homebase.common.audio./g' \
  -e 's/import id\.homebase\.core\.auth\./import id.homebase.common.auth./g' \
  -e 's/import id\.homebase\.core\.avatars\./import id.homebase.common.avatars./g' \
  -e 's/import id\.homebase\.core\.clipboard\./import id.homebase.common.clipboard./g' \
  -e 's/import id\.homebase\.core\.config\./import id.homebase.common.config./g' \
  -e 's/import id\.homebase\.core\.emoji\./import id.homebase.common.emoji./g' \
  -e 's/import id\.homebase\.core\.gallery\./import id.homebase.common.gallery./g' \
  -e 's/import id\.homebase\.core\.image\./import id.homebase.common.image./g' \
  -e 's/import id\.homebase\.core\.localization\./import id.homebase.common.localization./g' \
  -e 's/import id\.homebase\.core\.logging\./import id.homebase.common.logging./g' \
  -e 's/import id\.homebase\.core\.navigation\./import id.homebase.common.navigation./g' \
  -e 's/import id\.homebase\.core\.notifications\./import id.homebase.common.notifications./g' \
  -e 's/import id\.homebase\.core\.permissions\./import id.homebase.common.permissions./g' \
  -e 's/import id\.homebase\.core\.settings\./import id.homebase.common.settings./g' \
  -e 's/import id\.homebase\.core\.shapes\./import id.homebase.common.shapes./g' \
  -e 's/import id\.homebase\.core\.sync\./import id.homebase.common.sync./g' \
  -e 's/import id\.homebase\.core\.ui\.assets\./import id.homebase.common.ui.assets./g' \
  -e 's/import id\.homebase\.core\.ui\.auth\./import id.homebase.common.ui.auth./g' \
  -e 's/import id\.homebase\.core\.ui\.theme\./import id.homebase.common.ui.theme./g' \
  -e 's/import id\.homebase\.core\.util\./import id.homebase.common.util./g' \
  -e 's/import id\.homebase\.core\.widget\./import id.homebase.common.widget./g' \
  -e 's/import id\.homebase\.core\.HomebaseConstants/import id.homebase.common.HomebaseConstants/g' \
  -e 's/import id\.homebase\.core\.MainViewControllerRef/import id.homebase.common.MainViewControllerRef/g' \
  {} +

5b — Collision packages: class-specific replacements

These two packages overlap with homebase-core, so replacements must be class-level to avoid renaming homebase-core's classes.

id.homebase.core.share — homebase-common classes only:

find . -name "*.kt" ! -path "*/homebase-common/*" -exec sed -i \
  -e 's/import id\.homebase\.core\.share\.ShareCacheStorage/import id.homebase.common.share.ShareCacheStorage/g' \
  -e 's/import id\.homebase\.core\.share\.ShareableConversation/import id.homebase.common.share.ShareableConversation/g' \
  -e 's/import id\.homebase\.core\.share\.ShareContentProcessor/import id.homebase.common.share.ShareContentProcessor/g' \
  -e 's/import id\.homebase\.core\.share\.ShareConversationCacheWriter/import id.homebase.common.share.ShareConversationCacheWriter/g' \
  -e 's/import id\.homebase\.core\.share\.SharedContentDescriptor/import id.homebase.common.share.SharedContentDescriptor/g' \
  {} +

Homebase-core's ShareHandlerRegistration, registerShareHandler, unregisterShareHandler are NOT replaced and stay as id.homebase.core.share.*.

id.homebase.core.ui.navigation — homebase-common classes only:

find . -name "*.kt" ! -path "*/homebase-common/*" -exec sed -i \
  -e 's/import id\.homebase\.core\.ui\.navigation\.ObserveAsEvents/import id.homebase.common.ui.navigation.ObserveAsEvents/g' \
  -e 's/import id\.homebase\.core\.ui\.navigation\.Routes/import id.homebase.common.ui.navigation.Routes/g' \
  -e 's/import id\.homebase\.core\.ui\.navigation\.Route\b/import id.homebase.common.ui.navigation.Route/g' \
  {} +

Homebase-core's AppNavHost and AppViewModel are NOT replaced and stay as id.homebase.core.ui.navigation.*.


Step 5c — Fix implicit same-package resolution breakage

After the rename, any file in homebase-core that shared a package name with homebase-common and relied on implicit same-package resolution now has a broken reference. The known case:

  • AppNavHost.kt is in id.homebase.core.ui.navigation and used Route (from homebase-common's Routes.kt) without an explicit import — both were in the same package before. After the rename Route is in id.homebase.common.ui.navigation, so an explicit import must be added manually:
// homebase-core/src/commonMain/kotlin/id/homebase/core/ui/navigation/AppNavHost.kt
import id.homebase.common.ui.navigation.Route

General rule: After running Steps 5a/5b, if compilation reports Unresolved reference for a symbol that has no explicit import anywhere in the file, check whether that file previously shared a package with the symbol's source in homebase-common.


Step 6 — Sanity checks

# 1. No homebase-common files should still declare id.homebase.core.* packages
grep -rn "^package id\.homebase\.core" homebase-common/src --include="*.kt"
# Expected: no output

# 2. homebase-core packages must be untouched
grep -rn "^package id\.homebase\.common" homebase-core/src --include="*.kt"
# Expected: no output

# 3. No stale id.homebase.core imports from homebase-common packages in consuming files
#    (excludes homebase-common itself, and homebase-core's own share/ui.navigation classes)
grep -rn "import id\.homebase\.core\.\(audio\|auth\|avatars\|clipboard\|config\|emoji\|gallery\|image\|localization\|logging\|navigation\|notifications\|permissions\|settings\|shapes\|sync\|util\|widget\|HomebaseConstants\|MainViewControllerRef\)" \
  . --include="*.kt" \
  | grep -v "homebase-common/"
# Expected: no output

grep -rn "import id\.homebase\.core\.ui\.\(assets\|auth\|theme\)\." \
  . --include="*.kt" \
  | grep -v "homebase-common/"
# Expected: no output

# 4. Verify collision classes were handled correctly (homebase-common classes updated)
grep -rn "import id\.homebase\.core\.share\.Share\|import id\.homebase\.core\.share\.Shared" \
  . --include="*.kt" | grep -v "homebase-common/"
# Expected: no output (all homebase-common share classes now use id.homebase.common.share)

grep -rn "import id\.homebase\.core\.ui\.navigation\.ObserveAsEvents\|import id\.homebase\.core\.ui\.navigation\.Route" \
  . --include="*.kt" | grep -v "homebase-common/"
# Expected: no output

# 5. homebase-core's collision classes must still use id.homebase.core (not accidentally renamed)
grep -rn "import id\.homebase\.core\.share\.ShareHandlerRegistration\|import id\.homebase\.core\.share\.registerShareHandler\|import id\.homebase\.core\.share\.unregisterShareHandler" \
  homebase-core/src --include="*.kt"
# Expected: lines present (these must NOT have been renamed)

grep -rn "import id\.homebase\.core\.ui\.navigation\.AppNavHost\|import id\.homebase\.core\.ui\.navigation\.AppViewModel" \
  homebase-core/src --include="*.kt"
# Expected: lines present

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants