Skip to content
Closed
2 changes: 1 addition & 1 deletion apps/flipcash/features/balance/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies {

implementation(libs.compose.paging)

implementation(project(":apps:flipcash:shared:activityfeed"))
implementation(project(":apps:flipcash:shared:transaction-history"))
implementation(project(":apps:flipcash:shared:analytics"))
implementation(project(":apps:flipcash:shared:chat"))
implementation(project(":apps:flipcash:shared:featureflags"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.flipcash.app.analytics.Analytics
import com.flipcash.app.analytics.FlipcashAnalyticsService
import com.flipcash.app.balance.internal.components.OnboardingItem
import com.flipcash.app.core.AppRoute
import com.flipcash.app.activityfeed.ActivityFeedCoordinator
import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
import com.flipcash.app.funding.PurchaseMethodController
import com.flipcash.app.userflags.UserFlagsCoordinator
import com.flipcash.shared.chat.ChatCoordinator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.flipcash.app.analytics.StubFlipcashAnalytics
import com.flipcash.app.core.AppRoute
import com.flipcash.app.core.MainCoroutineRule
import com.flipcash.app.core.dispatchers.TestDispatchers
import com.flipcash.app.activityfeed.ActivityFeedCoordinator
import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
import com.flipcash.app.funding.PurchaseMethodController
import com.flipcash.app.userflags.UserFlagsCoordinator
import com.flipcash.shared.chat.ChatCoordinator
Expand Down
2 changes: 1 addition & 1 deletion apps/flipcash/features/transactions/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ dependencies {

implementation(libs.compose.paging)

implementation(project(":apps:flipcash:shared:activityfeed"))
implementation(project(":apps:flipcash:shared:transaction-history"))
implementation(project(":apps:flipcash:shared:featureflags"))
implementation(project(":apps:flipcash:shared:tokens"))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.flipcash.app.transactions.internal

import androidx.lifecycle.viewModelScope
import com.flipcash.app.activityfeed.ActivityFeedCoordinator
import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
import com.flipcash.app.core.extensions.onResult
import com.flipcash.app.core.feed.ActivityFeedMessage
import com.flipcash.app.core.feed.MessageMetadata
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.flipcash.app.transactions.internal

import com.flipcash.app.activityfeed.ActivityFeedCoordinator
import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
import com.flipcash.app.featureflags.FeatureFlagController
import com.flipcash.app.tokens.TokenCoordinator
import com.flipcash.services.user.UserManager
Expand Down
2 changes: 1 addition & 1 deletion apps/flipcash/features/withdrawal/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ dependencies {
testImplementation(libs.bundles.compose.ui.testing)

implementation(project(":apps:flipcash:shared:amount-entry"))
implementation(project(":apps:flipcash:shared:activityfeed"))
implementation(project(":apps:flipcash:shared:transaction-history"))
implementation(project(":apps:flipcash:shared:analytics"))
implementation(project(":apps:flipcash:shared:tokens"))
implementation(project(":apps:flipcash:shared:userflags"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import androidx.compose.foundation.text.input.TextFieldState
import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
import androidx.compose.runtime.snapshotFlow
import androidx.lifecycle.viewModelScope
import com.flipcash.app.activityfeed.ActivityFeedCoordinator
import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
import com.flipcash.app.analytics.Analytics
import com.flipcash.app.analytics.FlipcashAnalyticsService
import com.flipcash.app.core.extensions.onResult
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.flipcash.app.withdrawal

import android.content.ClipboardManager
import com.flipcash.app.activityfeed.ActivityFeedCoordinator
import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
import com.flipcash.app.analytics.FlipcashAnalyticsService
import com.flipcash.app.tokens.TokenCoordinator
import com.flipcash.app.userflags.UserFlagsCoordinator
Expand Down
13 changes: 6 additions & 7 deletions apps/flipcash/shared/activityfeed/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ android {
}

dependencies {
implementation(libs.bundles.room)
implementation(libs.androidx.paging.runtime)

compileOnly(project(":apps:flipcash:shared:persistence:db"))
implementation(project(":apps:flipcash:shared:persistence:sources"))
implementation(project(":services:flipcash"))
implementation(project(":libs:datetime"))
// Deprecated shim module: it only forwards to the new home (:shared:transaction-history) via
// @Deprecated typealiases. `api` (not implementation) so the underlying types resolve
// transitively for callers still importing the old com.flipcash.app.activityfeed package
// during the phase-out. Removed once all consumers migrate (plan Task 8, gated on v2 launch).
// See docs/superpowers/plans/2026-08-11-activityfeed-phaseout.md.
api(project(":apps:flipcash:shared:transaction-history"))
}
Original file line number Diff line number Diff line change
@@ -1,111 +1,12 @@
package com.flipcash.app.activityfeed

import androidx.paging.ExperimentalPagingApi
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.filter
import androidx.paging.map
import com.flipcash.app.core.feed.ActivityFeedMessage
import com.flipcash.app.core.feed.ActivityFeedMessageWithToken
import com.flipcash.app.persistence.sources.MessageDataSource
import com.flipcash.app.persistence.sources.mapper.notifications.MessageEntityToFeedMessageMapper
import com.flipcash.app.persistence.sources.mediator.FeedRemoteMediator
import com.flipcash.services.controllers.ActivityFeedController
import com.flipcash.services.models.ActivityFeedType
import com.flipcash.services.models.NotificationState
import com.flipcash.services.models.QueryOptions
import com.flipcash.services.user.UserManager
import com.getcode.opencode.providers.TokenMetadataProvider
import com.getcode.solana.keys.Mint
import com.getcode.utils.TraceType
import com.getcode.utils.trace
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class ActivityFeedCoordinator @Inject constructor(
private val activityFeedController: ActivityFeedController,
private val dataSource: MessageDataSource,
private val mapper: MessageEntityToFeedMessageMapper,
private val userManager: UserManager,
private val tokenProvider: TokenMetadataProvider,
) {
private val pagingConfig = PagingConfig(pageSize = 20)

@OptIn(ExperimentalPagingApi::class)
private val _messages: Flow<PagingData<ActivityFeedMessage>> = userManager.state
.filter { it.authState.canAccessAuthenticatedApis }
.flatMapLatest {
Pager(
config = pagingConfig,
remoteMediator = FeedRemoteMediator(activityFeedController, dataSource)
) {
dataSource.observe()
}.flow.map { page -> page.map { entity -> mapper.map(entity) } }
}

@OptIn(ExperimentalCoroutinesApi::class)
val messages: Flow<PagingData<ActivityFeedMessage>> = userManager.state
.mapNotNull { it.authState }
.filter { it.canAccessAuthenticatedApis }
.flatMapLatest { _messages }

@OptIn(ExperimentalCoroutinesApi::class)
fun transactions(mint: Mint): Flow<PagingData<ActivityFeedMessageWithToken>> = messages.map { page ->
page.filter { message ->
message.amount?.mint == mint
}.map { msg ->
val result = msg.amount?.mint?.let { tokenProvider.getTokenMetadata(it) }?.getOrNull()
ActivityFeedMessageWithToken(msg, result?.token)
}
}

/** Reactive "has the user ever added money" — any completed deposit/buy in the feed. */
fun hasEverAddedMoney(): Flow<Boolean> = dataSource.hasEverAddedMoney()

suspend fun checkPendingMessagesForUpdates(): Result<Int> {
val pendingMessages = dataSource.query(whereClause = "state = '${NotificationState.PENDING.name}'")

if (pendingMessages.isEmpty()) {
trace(
tag = "ActivityFeedCoordinator",
message = "No pending messages found",
type = TraceType.Silent
)
return Result.success(0)
}

return activityFeedController.getNotificationsById(pendingMessages.map { it.id })
.map { notifications ->
val completedCount = notifications.count { it.state == NotificationState.COMPLETED }

trace(
tag = "ActivityFeedCoordinator",
message = "$completedCount notifications completed from batch",
type = TraceType.Silent
)

dataSource.upsert(notifications)
completedCount
}
}

suspend fun fetchSinceLatest(count: Int = 20): Result<Unit> {
val latest = dataSource.getMostRecent()
return activityFeedController.queryNotificationsFor(
type = ActivityFeedType.TransactionHistory,
queryOptions = QueryOptions(
limit = count,
token = latest?.id,
descending = latest == null,
)
).onSuccess { dataSource.upsert(it) }.map { Unit }
}
}
@Deprecated(
"Moved to :shared:transaction-history as part of the v2 (FeatureFlag.NewUi) phase-out. " +
"Import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator instead. " +
"Plan: docs/superpowers/plans/2026-08-11-activityfeed-phaseout.md",
ReplaceWith(
"ActivityFeedCoordinator",
"com.flipcash.shared.transactionhistory.ActivityFeedCoordinator",
),
)
typealias ActivityFeedCoordinator = com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.flipcash.app.activityfeed

import com.flipcash.app.core.updater.NetworkUpdater
import javax.inject.Inject

class ActivityFeedUpdater @Inject constructor(
private val coordinator: ActivityFeedCoordinator,
): NetworkUpdater() {
override suspend fun doUpdate() {
coordinator.fetchSinceLatest(count = 50)
}
}
@Deprecated(
"Moved to :shared:transaction-history as part of the v2 (FeatureFlag.NewUi) phase-out. " +
"Import com.flipcash.shared.transactionhistory.ActivityFeedUpdater instead. " +
"Plan: docs/superpowers/plans/2026-08-11-activityfeed-phaseout.md",
ReplaceWith(
"ActivityFeedUpdater",
"com.flipcash.shared.transactionhistory.ActivityFeedUpdater",
),
)
typealias ActivityFeedUpdater = com.flipcash.shared.transactionhistory.ActivityFeedUpdater
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import javax.inject.Singleton
/**
* Owns the offline-first blocklist stream and unblock action for the account's blocklist screen.
*
* Mirrors [com.flipcash.app.activityfeed.ActivityFeedCoordinator]: gated on an authenticated
* Mirrors [com.flipcash.shared.transactionhistory.ActivityFeedCoordinator]: gated on an authenticated
* session, it wires a [Pager] + [BlocklistRemoteMediator] over the Room-backed
* [BlockedUserDataSource] and maps cached entities to display [BlockedUserProfile]s.
*/
Expand Down
2 changes: 1 addition & 1 deletion apps/flipcash/shared/session/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ dependencies {
implementation(project(":apps:flipcash:shared:blocklist"))
implementation(project(":apps:flipcash:shared:chat"))
implementation(project(":apps:flipcash:shared:contacts"))
implementation(project(":apps:flipcash:shared:activityfeed"))
implementation(project(":apps:flipcash:shared:transaction-history"))
implementation(project(":apps:flipcash:shared:analytics"))
implementation(project(":apps:flipcash:shared:appsettings"))
implementation(project(":apps:flipcash:shared:google-play-billing"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.flipcash.app.session.internal

import com.flipcash.app.activityfeed.ActivityFeedCoordinator
import com.flipcash.app.activityfeed.ActivityFeedUpdater
import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
import com.flipcash.shared.transactionhistory.ActivityFeedUpdater
import com.flipcash.app.appsettings.AppSettingValue
import com.flipcash.app.appsettings.AppSettingsCoordinator
import com.flipcash.app.billing.BillingClient
Expand Down
2 changes: 1 addition & 1 deletion apps/flipcash/shared/tokens/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ dependencies {

implementation(project(":apps:flipcash:shared:amount-entry"))
implementation(project(":apps:flipcash:shared:funding"))
implementation(project(":apps:flipcash:shared:activityfeed"))
implementation(project(":apps:flipcash:shared:transaction-history"))
implementation(project(":apps:flipcash:shared:analytics"))
implementation(project(":apps:flipcash:shared:featureflags"))
implementation(project(":apps:flipcash:shared:onramp:coinbase"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.flipcash.app.tokens.ui

import androidx.lifecycle.viewModelScope
import com.flipcash.app.activityfeed.ActivityFeedCoordinator
import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
import com.flipcash.app.analytics.Analytics
import com.flipcash.app.analytics.Button
import com.flipcash.app.analytics.FlipcashAnalyticsService
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.flipcash.app.tokens.ui

import com.flipcash.app.activityfeed.ActivityFeedCoordinator
import com.flipcash.shared.transactionhistory.ActivityFeedCoordinator
import com.flipcash.app.analytics.FlipcashAnalyticsService
import com.flipcash.app.core.tokens.SwapPurpose
import com.flipcash.app.onramp.CoinbaseOnRampController
Expand Down
20 changes: 20 additions & 0 deletions apps/flipcash/shared/transaction-history/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
plugins {
alias(libs.plugins.flipcash.android.feature)
}

android {
namespace = "com.flipcash.shared.transactionhistory"
}

// Home of the transaction-history data engine (ActivityFeedCoordinator / ActivityFeedUpdater),
// consolidated out of the deprecated :shared:activityfeed. Mirrors that module's dependencies.
// See docs/superpowers/plans/2026-08-11-activityfeed-phaseout.md.
dependencies {
implementation(libs.bundles.room)
implementation(libs.androidx.paging.runtime)

compileOnly(project(":apps:flipcash:shared:persistence:db"))
implementation(project(":apps:flipcash:shared:persistence:sources"))
implementation(project(":services:flipcash"))
implementation(project(":libs:datetime"))
}
Loading
Loading