Skip to content

refactor(tabgroup): manage people from group settings - #337

Merged
DennisBauer merged 4 commits into
mainfrom
feat/group-screens-rework
Aug 5, 2026
Merged

refactor(tabgroup): manage people from group settings#337
DennisBauer merged 4 commits into
mainfrom
feat/group-screens-rework

Conversation

@DennisBauer

@DennisBauer DennisBauer commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added a dedicated People screen for viewing members and placeholders.
    • Added placeholder-name creation, validation, cancellation, and accessibility support.
    • Added invite-link copying, sharing, and rotation.
    • Added member badges, counts, and improved person list presentation.
    • Group settings now provides access to People, while group details use a settings action.
  • Bug Fixes

    • Improved group layout behavior on tablets and updated localized labels.

fixes: #143

Members moves out of the tab row and Settings stops being a tablet-only
tab, so the set is Transactions/History/Balances on every width and the
gear icon is the single way into settings.

Drops perPersonBalances and rotateInvite with the Members tab: nothing
else read them.
@DennisBauer DennisBauer added the feature New feature or request label Aug 5, 2026
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9ef95ede-4e6b-4bce-8d8d-cbc87ddad205

📥 Commits

Reviewing files that changed from the base of the PR and between 9b303ad and c3e60b5.

📒 Files selected for processing (20)
  • composeApp/src/commonMain/kotlin/de/tabmates/composeapp/navigation/GroupTwoPaneSceneStrategy.kt
  • core/designsystem/src/commonMain/kotlin/de/tabmates/core/designsystem/textfields/TabMatesTextField.kt
  • features/tabgroup/presentation/src/commonMain/composeResources/values-de/string.xml
  • features/tabgroup/presentation/src/commonMain/composeResources/values/string.xml
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/components/PersonRow.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/MainGraph.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/MainNavKeys.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupdetail/GroupDetailRoot.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupdetail/GroupDetailViewModel.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupoverview/GroupDetailPane.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleScreen.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleState.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleViewModel.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsScreen.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsState.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModel.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/creategroup/FakeGroupRepository.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleViewModelTest.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModelTest.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/testing/Fixtures.kt
💤 Files with no reviewable changes (2)
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupdetail/GroupDetailViewModel.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupdetail/GroupDetailRoot.kt
🚧 Files skipped from review as they are similar to previous changes (15)
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/creategroup/FakeGroupRepository.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsState.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/MainNavKeys.kt
  • composeApp/src/commonMain/kotlin/de/tabmates/composeapp/navigation/GroupTwoPaneSceneStrategy.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModelTest.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleState.kt
  • core/designsystem/src/commonMain/kotlin/de/tabmates/core/designsystem/textfields/TabMatesTextField.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/MainGraph.kt
  • features/tabgroup/presentation/src/commonMain/composeResources/values/string.xml
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/components/PersonRow.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleScreen.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/testing/Fixtures.kt
  • features/tabgroup/presentation/src/commonMain/composeResources/values-de/string.xml
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModel.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupoverview/GroupDetailPane.kt

📝 Walkthrough

Walkthrough

Changes

The PR adds a dedicated group-people screen for members, placeholders, and invite links. It moves people access into group settings, removes members and settings tabs from group detail, updates tablet navigation, and adds state, ViewModel, UI, localization, and tests.

Group People Management

Layer / File(s) Summary
People state and ViewModel logic
features/tabgroup/presentation/.../grouppeople/*, features/tabgroup/presentation/.../testing/Fixtures.kt, features/tabgroup/presentation/.../FakeGroupRepository.kt, features/tabgroup/presentation/.../GroupPeopleViewModelTest.kt
Adds people state, member mapping, placeholder validation, invite rotation, error events, fixtures, repository controls, and ViewModel tests.
People screen and presentation UI
features/tabgroup/presentation/.../grouppeople/GroupPeopleScreen.kt, features/tabgroup/presentation/.../components/PersonRow.kt, core/designsystem/.../TabMatesTextField.kt, features/tabgroup/presentation/.../composeResources/values*/*
Adds the people screen, person rows, placeholder entry controls, invite actions, trailing text-field icons, and localized strings.
Group detail and settings restructuring
features/tabgroup/presentation/.../groupdetail/*, features/tabgroup/presentation/.../groupoverview/GroupDetailPane.kt, features/tabgroup/presentation/.../groupsettings/*
Removes member and settings tabs, moves settings access to the header, removes detail invite rotation and leave handling, and replaces placeholder settings UI with a people card and participant count.
People destination navigation
features/tabgroup/presentation/.../navigation/MainGraph.kt, MainNavKeys.kt, composeApp/.../GroupTwoPaneSceneStrategy.kt
Registers and renders GroupPeople, routes from settings, moves group-leave handling into settings, and updates two-pane route documentation.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GroupDetailPane
  participant GroupSettings
  participant MainGraph
  participant GroupPeopleRoot
  participant GroupPeopleViewModel
  participant GroupRepository
  GroupDetailPane->>GroupSettings: open settings
  GroupSettings->>MainGraph: navigate to GroupPeople(groupId)
  MainGraph->>GroupPeopleRoot: render group people destination
  GroupPeopleRoot->>GroupPeopleViewModel: collect state and events
  GroupPeopleViewModel->>GroupRepository: observe group and submit actions
  GroupRepository-->>GroupPeopleViewModel: group updates or operation results
  GroupPeopleViewModel-->>GroupPeopleRoot: people state or error event
Loading
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: managing group people from group settings.
Linked Issues check ✅ Passed The PR implements group people management, including adding placeholder users, as requested by issue [#143].
Out of Scope Changes check ✅ Passed The navigation, settings, group-detail, resources, and tests support the group people management objective in issue [#143].
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/group-screens-rework

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (5)
features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleState.kt (1)

25-25: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider word-based initials.

name.take(2) returns the first two characters of the first word. For "Anna Beispiel" it returns "AN" instead of "AB". It can also split a surrogate pair and render a broken glyph.

♻️ Word-based initials
-    val initials: String get() = name.take(2).uppercase()
+    val initials: String
+        get() =
+            name
+                .trim()
+                .split(' ')
+                .filter { it.isNotBlank() }
+                .take(2)
+                .joinToString("") { it.take(1) }
+                .uppercase()
+                .ifEmpty { "?" }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleState.kt`
at line 25, Update the initials getter in GroupPeopleState so it derives
initials from the first character of each of the first two words in name, rather
than taking the first two code units. Preserve uppercase output and safely
handle names with fewer than two words or Unicode surrogate pairs.
features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/testing/Fixtures.kt (1)

30-30: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

participants.first() throws for an empty participant set.

If a test calls Fixtures.group(participants = emptySet()) and omits creator, the default expression throws NoSuchElementException. The failure message does not point at the fixture.

♻️ Fall back to a default participant
-        creator: GroupParticipant = participants.first(),
+        creator: GroupParticipant = participants.firstOrNull() ?: participant(),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/testing/Fixtures.kt`
at line 30, Update the default creator expression in Fixtures.group so empty
participants collections do not call participants.first() and throw. Reuse or
provide a default participant fallback while preserving the existing
first-participant behavior when participants is non-empty.
features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModelTest.kt (1)

72-73: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add the participant as a placeholder.

The test name and the comment at line 61 describe a placeholder added on the People screen. The id "ph-1" implies a placeholder, but Fixtures.participant defaults to ParticipantType.REGISTERED. The test therefore does not prove that peopleCount counts placeholders.

The fixture now accepts a type argument. Use it so the test locks in the count contract that PeopleCard and GroupPeopleScreen share.

💚 Use the placeholder type
-            val added = Fixtures.participant(id = "ph-1", name = "Tom")
+            val added =
+                Fixtures.participant(
+                    id = "ph-1",
+                    name = "Tom",
+                    type = ParticipantType.PLACEHOLDER,
+                )
             repo.emitGroups(listOf(group.copy(participants = setOf(alice, added))))

Add the import for de.tabmates.features.tabgroup.domain.models.ParticipantType.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModelTest.kt`
around lines 72 - 73, Update the participant fixture in the test around
GroupSettingsViewModelTest to pass ParticipantType.PLACEHOLDER as its type, and
add the ParticipantType import. Keep the existing placeholder id and count
assertion unchanged so the test verifies placeholder participants are included
in peopleCount.
features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleViewModel.kt (1)

134-137: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

The duplicate check depends on an active state subscription.

state uses SharingStarted.WhileSubscribed(5.seconds). When no collector is active, state.value holds the last cached value, or the GroupPeopleState() initial value with empty lists. isKnownName then reports false for a name that already exists.

The screen is normally subscribed while the user types, so the window is narrow. Reading the group from the repository removes the hidden coupling between a validation rule and the sharing policy.

♻️ Read the participants from the repository
-    private fun isKnownName(name: String): Boolean {
-        val existing = state.value.let { it.members + it.placeholders }
-        return existing.any { it.name.equals(name, ignoreCase = true) }
-    }
+    private suspend fun isKnownName(name: String): Boolean {
+        val group = groupRepository.getGroups().first().firstOrNull { it.id == groupId } ?: return false
+        return group.participants.any { it.username.equals(name, ignoreCase = true) }
+    }

Move the call inside the existing viewModelScope.launch in submitName.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleViewModel.kt`
around lines 134 - 137, Update submitName to read the current group participants
from the repository inside its existing viewModelScope.launch, and perform the
duplicate-name check against that repository data rather than the cached state.
Replace or bypass isKnownName’s state.value dependency while preserving
case-insensitive matching across members and placeholders.
features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModel.kt (1)

53-61: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Observe only the requested group’s participants.

getGroups() maps every group and performs an active-participant query for each group on every emission. getActiveParticipantsByGroupId(groupId) returns all active participant types, including PLACEHOLDER, so its size matches the People screen’s members and placeholders.

♻️ Observe this group’s participants
     private fun observePeopleCount() {
         viewModelScope.launch {
             groupRepository
-                .getGroups()
-                .map { groups -> groups.firstOrNull { it.id == groupId }?.participants?.size ?: 0 }
+                .getActiveParticipantsByGroupId(groupId)
+                .map { participants -> participants.size }
                 .distinctUntilChanged()
                 .collect { count -> _state.update { it.copy(peopleCount = count) } }
         }
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModel.kt`
around lines 53 - 61, Update observePeopleCount in GroupSettingsViewModel to
observe only the requested group by using
getActiveParticipantsByGroupId(groupId) rather than collecting all groups and
counting participants locally. Preserve distinctUntilChanged and update
peopleCount with the returned active participant count, including PLACEHOLDER
entries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleViewModel.kt`:
- Around line 114-117: Update submitName’s isKnownName branch to emit
GroupPeopleEvent.Error using the new group_people_error_duplicate_name string
resource instead of clearing the input; preserve the typed text so the user can
correct and resubmit it. Add the matching group_people_error_duplicate_name
translations to string.xml and values-de/string.xml.
- Around line 65-73: Update GroupPeopleViewModel’s group-loading state
construction to distinguish an initial, un-emitted flow from a completed lookup
with no matching group. Add the GroupLookup helper with hasLoaded and group
fields, track the first getGroups() emission, and set isLoading only while
hasLoaded is false; preserve the existing member, placeholder, token, and
form-state mappings.
- Around line 118-131: Update submitName and rotateInvite in
features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleViewModel.kt:118-131
and :139-148 to set their re-entrancy guards before launching viewModelScope
coroutines, then reset each guard in a finally block. Keep isAdding cleared
after addNewParticipantsToGroup and isRotatingInvite cleared after rotation,
including cancellation and exception paths.

In
`@features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/MainGraph.kt`:
- Around line 265-268: Update the back-stack cleanup predicate in MainGraph so
GroupSettings and GroupPeople are removed only when their groupId matches
route.groupId, while preserving the existing GroupDetail match. Apply the same
group-scoped filtering to the detail-route cleanup used when selecting another
group around the group-selection navigation logic.

---

Nitpick comments:
In
`@features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleState.kt`:
- Line 25: Update the initials getter in GroupPeopleState so it derives initials
from the first character of each of the first two words in name, rather than
taking the first two code units. Preserve uppercase output and safely handle
names with fewer than two words or Unicode surrogate pairs.

In
`@features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleViewModel.kt`:
- Around line 134-137: Update submitName to read the current group participants
from the repository inside its existing viewModelScope.launch, and perform the
duplicate-name check against that repository data rather than the cached state.
Replace or bypass isKnownName’s state.value dependency while preserving
case-insensitive matching across members and placeholders.

In
`@features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModel.kt`:
- Around line 53-61: Update observePeopleCount in GroupSettingsViewModel to
observe only the requested group by using
getActiveParticipantsByGroupId(groupId) rather than collecting all groups and
counting participants locally. Preserve distinctUntilChanged and update
peopleCount with the returned active participant count, including PLACEHOLDER
entries.

In
`@features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModelTest.kt`:
- Around line 72-73: Update the participant fixture in the test around
GroupSettingsViewModelTest to pass ParticipantType.PLACEHOLDER as its type, and
add the ParticipantType import. Keep the existing placeholder id and count
assertion unchanged so the test verifies placeholder participants are included
in peopleCount.

In
`@features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/testing/Fixtures.kt`:
- Line 30: Update the default creator expression in Fixtures.group so empty
participants collections do not call participants.first() and throw. Reuse or
provide a default participant fallback while preserving the existing
first-participant behavior when participants is non-empty.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 985616c9-b35a-4c92-8e27-92fc97b7f25f

📥 Commits

Reviewing files that changed from the base of the PR and between 9b303ad and e859b66.

📒 Files selected for processing (20)
  • composeApp/src/commonMain/kotlin/de/tabmates/composeapp/navigation/GroupTwoPaneSceneStrategy.kt
  • core/designsystem/src/commonMain/kotlin/de/tabmates/core/designsystem/textfields/TabMatesTextField.kt
  • features/tabgroup/presentation/src/commonMain/composeResources/values-de/string.xml
  • features/tabgroup/presentation/src/commonMain/composeResources/values/string.xml
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/components/PersonRow.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/MainGraph.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/MainNavKeys.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupdetail/GroupDetailRoot.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupdetail/GroupDetailViewModel.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupoverview/GroupDetailPane.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleScreen.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleState.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleViewModel.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsScreen.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsState.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModel.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/creategroup/FakeGroupRepository.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/grouppeople/GroupPeopleViewModelTest.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupsettings/GroupSettingsViewModelTest.kt
  • features/tabgroup/presentation/src/commonTest/kotlin/de/tabmates/features/tabgroup/presentation/testing/Fixtures.kt
💤 Files with no reviewable changes (2)
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupdetail/GroupDetailRoot.kt
  • features/tabgroup/presentation/src/commonMain/kotlin/de/tabmates/features/tabgroup/presentation/navigation/groupdetail/GroupDetailViewModel.kt

One row style and one screen for everyone in a group, split into Members
and Placeholders sections, with the invite link card alongside. Adding a
placeholder is an inline field that stays open after each name.

PersonRow takes an optional trailing slot: the server has no delete for
participants yet, and that slot is where it lands when it does.

The route is registered but not yet reachable; group settings links it in
the next commit.
Replaces the placeholder chip row with a People entry that opens the new
screen, so members and placeholders are handled in one place.

peopleCount is observed rather than read once: settings stays composed on
the back stack while People is open, and a placeholder added there has to
reach the row on the way back.

Settings and People become detail panes, so opening them on a tablet keeps
the group list instead of covering the window.
@DennisBauer
DennisBauer force-pushed the feat/group-screens-rework branch from e859b66 to c3e60b5 Compare August 5, 2026 19:48
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@DennisBauer
DennisBauer merged commit cfccfb3 into main Aug 5, 2026
4 checks passed
@DennisBauer
DennisBauer deleted the feat/group-screens-rework branch August 5, 2026 20:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Placeholder user when editing group also from members tab?

1 participant