mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
Announce multi-account support
Show a one-time bottom sheet on the home screen to announce that several accounts can now be added (element-hq/element-meta#3349). - Add `Announcement.MultiAccount`, which is never shown by default. - AppMigration11 queues the announcement on application upgrade only, and marks it as shown if the user already has several accounts. - HomePresenter shows the bottom sheet only when the announcement is pending, the MultiAccount feature flag is enabled and the user has a single account. - The "Add account" button hides the sheet, marks the announcement as dismissed and starts the add account flow through the new `HomeEntryPoint.Callback.navigateToAddAccount()`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.migration.impl.migrations
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesIntoSet
|
||||
import io.element.android.features.announcement.api.Announcement
|
||||
import io.element.android.features.announcement.api.AnnouncementService
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
|
||||
/**
|
||||
* Ensure the multi-account announcement is displayed, but only on application upgrade,
|
||||
* and only if the user does not already have several accounts.
|
||||
*/
|
||||
@ContributesIntoSet(AppScope::class)
|
||||
class AppMigration11(
|
||||
private val sessionStore: SessionStore,
|
||||
private val announcementService: AnnouncementService,
|
||||
) : AppMigration {
|
||||
override val order: Int = 11
|
||||
|
||||
override suspend fun migrate(isFreshInstall: Boolean) {
|
||||
if (isFreshInstall) return
|
||||
|
||||
if (sessionStore.getAllSessions().size > 1) {
|
||||
// The user already uses several accounts, no need to announce the feature
|
||||
announcementService.onAnnouncementDismissed(Announcement.MultiAccount)
|
||||
} else {
|
||||
announcementService.showAnnouncement(Announcement.MultiAccount)
|
||||
}
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.migration.impl.migrations
|
||||
|
||||
import io.element.android.features.announcement.api.Announcement
|
||||
import io.element.android.features.rageshake.test.logs.FakeAnnouncementService
|
||||
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
|
||||
import io.element.android.libraries.sessionstorage.test.aSessionData
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
class AppMigration11Test {
|
||||
@Test
|
||||
fun `migration on fresh install should not invoke the AnnouncementService`() = runTest {
|
||||
val service = FakeAnnouncementService()
|
||||
val migration = AppMigration11(
|
||||
sessionStore = InMemorySessionStore(initialList = listOf(aSessionData())),
|
||||
announcementService = service,
|
||||
)
|
||||
// FakeAnnouncementService lambdas throw by default
|
||||
migration.migrate(isFreshInstall = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `migration on upgrade with a single account should show the announcement`() = runTest {
|
||||
val showAnnouncementResult = lambdaRecorder<Announcement, Unit> { }
|
||||
val service = FakeAnnouncementService(
|
||||
showAnnouncementResult = showAnnouncementResult,
|
||||
)
|
||||
val migration = AppMigration11(
|
||||
sessionStore = InMemorySessionStore(initialList = listOf(aSessionData())),
|
||||
announcementService = service,
|
||||
)
|
||||
migration.migrate(isFreshInstall = false)
|
||||
showAnnouncementResult.assertions().isCalledOnce()
|
||||
.with(value(Announcement.MultiAccount))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `migration on upgrade with several accounts should mark the announcement as dismissed`() = runTest {
|
||||
val onAnnouncementDismissedResult = lambdaRecorder<Announcement, Unit> { }
|
||||
val service = FakeAnnouncementService(
|
||||
onAnnouncementDismissedResult = onAnnouncementDismissedResult,
|
||||
)
|
||||
val migration = AppMigration11(
|
||||
sessionStore = InMemorySessionStore(
|
||||
initialList = listOf(
|
||||
aSessionData(sessionId = "@alice:server.org"),
|
||||
aSessionData(sessionId = "@bob:server.org"),
|
||||
)
|
||||
),
|
||||
announcementService = service,
|
||||
)
|
||||
migration.migrate(isFreshInstall = false)
|
||||
onAnnouncementDismissedResult.assertions().isCalledOnce()
|
||||
.with(value(Announcement.MultiAccount))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user