|
|
@ -26,10 +26,9 @@ import androidx.compose.runtime.remember |
|
|
|
import androidx.compose.runtime.rememberUpdatedState |
|
|
|
import androidx.compose.runtime.rememberUpdatedState |
|
|
|
import androidx.compose.runtime.saveable.rememberSaveable |
|
|
|
import androidx.compose.runtime.saveable.rememberSaveable |
|
|
|
import androidx.compose.runtime.setValue |
|
|
|
import androidx.compose.runtime.setValue |
|
|
|
|
|
|
|
import io.element.android.features.messages.impl.pinned.IsPinnedMessagesFeatureEnabled |
|
|
|
import io.element.android.features.networkmonitor.api.NetworkMonitor |
|
|
|
import io.element.android.features.networkmonitor.api.NetworkMonitor |
|
|
|
import io.element.android.libraries.architecture.Presenter |
|
|
|
import io.element.android.libraries.architecture.Presenter |
|
|
|
import io.element.android.libraries.featureflag.api.FeatureFlagService |
|
|
|
|
|
|
|
import io.element.android.libraries.featureflag.api.FeatureFlags |
|
|
|
|
|
|
|
import io.element.android.libraries.matrix.api.room.MatrixRoom |
|
|
|
import io.element.android.libraries.matrix.api.room.MatrixRoom |
|
|
|
import kotlinx.collections.immutable.ImmutableList |
|
|
|
import kotlinx.collections.immutable.ImmutableList |
|
|
|
import kotlinx.collections.immutable.persistentListOf |
|
|
|
import kotlinx.collections.immutable.persistentListOf |
|
|
@ -46,21 +45,20 @@ import kotlin.time.Duration.Companion.milliseconds |
|
|
|
class PinnedMessagesBannerPresenter @Inject constructor( |
|
|
|
class PinnedMessagesBannerPresenter @Inject constructor( |
|
|
|
private val room: MatrixRoom, |
|
|
|
private val room: MatrixRoom, |
|
|
|
private val itemFactory: PinnedMessagesBannerItemFactory, |
|
|
|
private val itemFactory: PinnedMessagesBannerItemFactory, |
|
|
|
private val featureFlagService: FeatureFlagService, |
|
|
|
private val isFeatureEnabled: IsPinnedMessagesFeatureEnabled, |
|
|
|
private val networkMonitor: NetworkMonitor, |
|
|
|
private val networkMonitor: NetworkMonitor, |
|
|
|
) : Presenter<PinnedMessagesBannerState> { |
|
|
|
) : Presenter<PinnedMessagesBannerState> { |
|
|
|
|
|
|
|
private val pinnedItems = mutableStateOf<ImmutableList<PinnedMessagesBannerItem>>(persistentListOf()) |
|
|
|
|
|
|
|
|
|
|
|
@Composable |
|
|
|
@Composable |
|
|
|
override fun present(): PinnedMessagesBannerState { |
|
|
|
override fun present(): PinnedMessagesBannerState { |
|
|
|
val isFeatureEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.PinnedEvents).collectAsState(initial = false) |
|
|
|
val isFeatureEnabled = isFeatureEnabled() |
|
|
|
var hasTimelineFailedToLoad by rememberSaveable { mutableStateOf(false) } |
|
|
|
|
|
|
|
var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(-1) } |
|
|
|
|
|
|
|
val knownPinnedMessagesCount by remember { |
|
|
|
val knownPinnedMessagesCount by remember { |
|
|
|
room.roomInfoFlow.map { roomInfo -> roomInfo.pinnedEventIds.size } |
|
|
|
room.roomInfoFlow.map { roomInfo -> roomInfo.pinnedEventIds.size } |
|
|
|
}.collectAsState(initial = 0) |
|
|
|
}.collectAsState(initial = 0) |
|
|
|
|
|
|
|
|
|
|
|
var pinnedItems by remember { |
|
|
|
var hasTimelineFailedToLoad by rememberSaveable { mutableStateOf(false) } |
|
|
|
mutableStateOf<ImmutableList<PinnedMessagesBannerItem>>(persistentListOf()) |
|
|
|
var currentPinnedMessageIndex by rememberSaveable { mutableIntStateOf(-1) } |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PinnedMessagesBannerItemsEffect( |
|
|
|
PinnedMessagesBannerItemsEffect( |
|
|
|
isFeatureEnabled = isFeatureEnabled, |
|
|
|
isFeatureEnabled = isFeatureEnabled, |
|
|
@ -69,7 +67,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( |
|
|
|
if (currentPinnedMessageIndex >= pinnedMessageCount || currentPinnedMessageIndex < 0) { |
|
|
|
if (currentPinnedMessageIndex >= pinnedMessageCount || currentPinnedMessageIndex < 0) { |
|
|
|
currentPinnedMessageIndex = pinnedMessageCount - 1 |
|
|
|
currentPinnedMessageIndex = pinnedMessageCount - 1 |
|
|
|
} |
|
|
|
} |
|
|
|
pinnedItems = newItems |
|
|
|
pinnedItems.value = newItems |
|
|
|
}, |
|
|
|
}, |
|
|
|
onTimelineFail = { hasTimelineFailed -> |
|
|
|
onTimelineFail = { hasTimelineFailed -> |
|
|
|
hasTimelineFailedToLoad = hasTimelineFailed |
|
|
|
hasTimelineFailedToLoad = hasTimelineFailed |
|
|
@ -82,7 +80,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( |
|
|
|
if (currentPinnedMessageIndex > 0) { |
|
|
|
if (currentPinnedMessageIndex > 0) { |
|
|
|
currentPinnedMessageIndex-- |
|
|
|
currentPinnedMessageIndex-- |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
currentPinnedMessageIndex = pinnedItems.size - 1 |
|
|
|
currentPinnedMessageIndex = pinnedItems.value.size - 1 |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -92,7 +90,7 @@ class PinnedMessagesBannerPresenter @Inject constructor( |
|
|
|
isFeatureEnabled = isFeatureEnabled, |
|
|
|
isFeatureEnabled = isFeatureEnabled, |
|
|
|
hasTimelineFailed = hasTimelineFailedToLoad, |
|
|
|
hasTimelineFailed = hasTimelineFailedToLoad, |
|
|
|
realPinnedMessagesCount = knownPinnedMessagesCount, |
|
|
|
realPinnedMessagesCount = knownPinnedMessagesCount, |
|
|
|
pinnedItems = pinnedItems, |
|
|
|
pinnedItems = pinnedItems.value, |
|
|
|
currentPinnedMessageIndex = currentPinnedMessageIndex, |
|
|
|
currentPinnedMessageIndex = currentPinnedMessageIndex, |
|
|
|
eventSink = ::handleEvent |
|
|
|
eventSink = ::handleEvent |
|
|
|
) |
|
|
|
) |
|
|
@ -111,16 +109,14 @@ class PinnedMessagesBannerPresenter @Inject constructor( |
|
|
|
return when { |
|
|
|
return when { |
|
|
|
!isFeatureEnabled -> PinnedMessagesBannerState.Hidden |
|
|
|
!isFeatureEnabled -> PinnedMessagesBannerState.Hidden |
|
|
|
hasTimelineFailed -> PinnedMessagesBannerState.Hidden |
|
|
|
hasTimelineFailed -> PinnedMessagesBannerState.Hidden |
|
|
|
|
|
|
|
currentPinnedMessage != null -> PinnedMessagesBannerState.Loaded( |
|
|
|
|
|
|
|
currentPinnedMessage = currentPinnedMessage, |
|
|
|
|
|
|
|
currentPinnedMessageIndex = currentPinnedMessageIndex, |
|
|
|
|
|
|
|
knownPinnedMessagesCount = pinnedItems.size, |
|
|
|
|
|
|
|
eventSink = eventSink |
|
|
|
|
|
|
|
) |
|
|
|
realPinnedMessagesCount == 0 -> PinnedMessagesBannerState.Hidden |
|
|
|
realPinnedMessagesCount == 0 -> PinnedMessagesBannerState.Hidden |
|
|
|
currentPinnedMessage == null -> PinnedMessagesBannerState.Loading(realPinnedMessagesCount = realPinnedMessagesCount) |
|
|
|
else -> PinnedMessagesBannerState.Loading(realPinnedMessagesCount = realPinnedMessagesCount) |
|
|
|
else -> { |
|
|
|
|
|
|
|
PinnedMessagesBannerState.Loaded( |
|
|
|
|
|
|
|
currentPinnedMessage = currentPinnedMessage, |
|
|
|
|
|
|
|
currentPinnedMessageIndex = currentPinnedMessageIndex, |
|
|
|
|
|
|
|
knownPinnedMessagesCount = pinnedItems.size, |
|
|
|
|
|
|
|
eventSink = eventSink |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -136,8 +132,10 @@ class PinnedMessagesBannerPresenter @Inject constructor( |
|
|
|
val networkStatus by networkMonitor.connectivity.collectAsState() |
|
|
|
val networkStatus by networkMonitor.connectivity.collectAsState() |
|
|
|
|
|
|
|
|
|
|
|
LaunchedEffect(isFeatureEnabled, networkStatus) { |
|
|
|
LaunchedEffect(isFeatureEnabled, networkStatus) { |
|
|
|
if (!isFeatureEnabled) return@LaunchedEffect |
|
|
|
if (!isFeatureEnabled) { |
|
|
|
|
|
|
|
updatedOnItemsChange(persistentListOf()) |
|
|
|
|
|
|
|
return@LaunchedEffect |
|
|
|
|
|
|
|
} |
|
|
|
val pinnedEventsTimeline = room.pinnedEventsTimeline() |
|
|
|
val pinnedEventsTimeline = room.pinnedEventsTimeline() |
|
|
|
.onFailure { updatedOnTimelineFail(true) } |
|
|
|
.onFailure { updatedOnTimelineFail(true) } |
|
|
|
.onSuccess { updatedOnTimelineFail(false) } |
|
|
|
.onSuccess { updatedOnTimelineFail(false) } |
|
|
|