Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
3b353bd
feat: new loading behavior
ohassine Apr 23, 2026
6704b01
Merge remote-tracking branch 'origin/develop' into new-loading-behavior
ohassine Apr 24, 2026
5d97f06
Merge remote-tracking branch 'origin/develop' into new-loading-behavior
ohassine Apr 24, 2026
43c0418
feat: remove download to external storage option
ohassine Apr 27, 2026
9ea06e7
feat: cleanup
ohassine Apr 28, 2026
fa81683
feat: detekt
ohassine Apr 28, 2026
dcf676f
Merge remote-tracking branch 'origin/develop' into new-loading-behavior
ohassine Apr 28, 2026
ca33415
Merge remote-tracking branch 'origin/develop' into new-loading-behavior
ohassine Apr 28, 2026
ff7f3b5
feat: cleanup
ohassine Apr 28, 2026
8d57c00
feat: cleanup
ohassine Apr 28, 2026
5296036
feat: cleanup
ohassine Apr 28, 2026
add26ee
fix: cleanup
ohassine Apr 29, 2026
942a6e2
fix: cleanup
ohassine Apr 29, 2026
a9e6d8c
feat: refactor
ohassine Apr 29, 2026
2bb96f2
feat: unit test
ohassine Apr 29, 2026
d403848
Merge branch 'develop' into new-loading-behavior
ohassine Apr 29, 2026
771b73d
feat: detekt
ohassine Apr 29, 2026
3f458b1
Merge remote-tracking branch 'origin/new-loading-behavior' into new-l…
ohassine Apr 30, 2026
784c3d3
feat: detekt
ohassine Apr 30, 2026
24a0eea
Merge branch 'develop' into new-loading-behavior
ohassine Apr 30, 2026
f8a0d11
Merge branch 'develop' into new-loading-behavior
ohassine May 4, 2026
d76da05
chore: test
ohassine May 4, 2026
1a25574
Merge branch 'develop' into new-loading-behavior
ohassine May 4, 2026
defa808
feat(drive): Make files available offline
ohassine May 6, 2026
57eb842
Merge remote-tracking branch 'origin/develop' into Make-files-availab…
ohassine May 6, 2026
ed03ad9
feat(drive): Make files available offline
ohassine May 7, 2026
e45ce22
Merge remote-tracking branch 'origin/develop' into Make-files-availab…
ohassine May 7, 2026
e629614
chore: cleanup
ohassine May 7, 2026
a6852d9
chore: cleanup
ohassine May 7, 2026
5db198b
chore: detekt
ohassine May 7, 2026
2a1bd5f
chore: detekt
ohassine May 8, 2026
fcd8bb1
chore: cleanup
ohassine May 8, 2026
e7589b7
Merge remote-tracking branch 'origin/develop' into Make-files-availab…
ohassine May 8, 2026
66771b7
feat: modifiedAt from String to Long
ohassine May 12, 2026
6576a50
feat: cleanup
ohassine May 12, 2026
6343f92
Merge branch 'develop' into Make-files-available-offline
ohassine May 12, 2026
c4c8be5
feat: cleanup
ohassine May 12, 2026
22fd15f
feat: kalium reference
ohassine May 12, 2026
d050772
feat: cleanup
ohassine May 12, 2026
d2d0998
feat: test
ohassine May 12, 2026
b9ff6a8
Merge branch 'develop' into Make-files-available-offline
ohassine May 12, 2026
12e6365
fix: incorrect icon usage
ohassine May 12, 2026
a30de5a
Merge remote-tracking branch 'origin/Make-files-available-offline' in…
ohassine May 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ import com.wire.kalium.cells.domain.usecase.publiclink.SetPublicLinkExpirationUs
import com.wire.kalium.cells.domain.usecase.publiclink.UpdatePublicLinkPasswordUseCase
import com.wire.kalium.cells.domain.usecase.versioning.GetNodeVersionsUseCase
import com.wire.kalium.cells.domain.usecase.versioning.RestoreNodeVersionUseCase
import com.wire.kalium.cells.domain.usecase.offline.DeleteOfflineFileUseCase
import com.wire.kalium.cells.domain.usecase.offline.GetOfflineFileUseCase
import com.wire.kalium.cells.domain.usecase.offline.ObserveOfflineFilesUseCase
import com.wire.kalium.cells.domain.usecase.offline.SaveOfflineFileUseCase
import com.wire.kalium.cells.paginatedConversationsFlowUseCase
import com.wire.kalium.cells.paginatedFilesFlowUseCase
import com.wire.kalium.logic.CoreLogic
Expand Down Expand Up @@ -259,4 +263,20 @@ class CellsModule {
@Provides
fun provideGetPaginatedConversationsFlowUseCase(cellsScope: CellsScope): GetPaginatedCellConversationsFlowUseCase =
cellsScope.paginatedConversationsFlowUseCase

@ViewModelScoped
@Provides
fun provideSaveOfflineFileUseCase(cellsScope: CellsScope): SaveOfflineFileUseCase = cellsScope.saveOfflineFile

@ViewModelScoped
@Provides
fun provideDeleteOfflineFileUseCase(cellsScope: CellsScope): DeleteOfflineFileUseCase = cellsScope.deleteOfflineFile

@ViewModelScoped
@Provides
fun provideObserveOfflineFilesUseCase(cellsScope: CellsScope): ObserveOfflineFilesUseCase = cellsScope.observeOfflineFiles

@ViewModelScoped
@Provides
fun provideGetOfflineFileUseCase(cellsScope: CellsScope): GetOfflineFileUseCase = cellsScope.getOfflineFile
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ package com.wire.android.feature.cells.ui

import com.wire.android.feature.cells.ui.model.CellNodeUi
import com.wire.android.feature.cells.ui.model.NodeBottomSheetAction
import com.wire.android.feature.cells.ui.model.OpenLoadState
import com.wire.android.feature.cells.ui.model.isEditSupported
import com.wire.android.feature.cells.ui.model.localFileAvailable
import com.wire.kalium.logic.featureFlags.KaliumConfigs
Expand All @@ -36,64 +35,115 @@ class CellFileActionsMenu @Inject constructor(
isAllFiles: Boolean,
isSearching: Boolean,
isCollaboraEnabled: Boolean,
): List<NodeBottomSheetAction> =
when {
isRecycleBin -> {
buildList {
add(NodeBottomSheetAction.RESTORE)
add(NodeBottomSheetAction.DELETE_PERMANENTLY)
}
}
): List<NodeBottomSheetAction> {
return when {
isRecycleBin -> recycleBinActions()

isAllFiles || isSearching -> {
buildList {
if (cellNode is CellNodeUi.File && cellNode.openLoadState is OpenLoadState.Loading) {
add(NodeBottomSheetAction.CANCEL_LOADING)
} else {
if (cellNode is CellNodeUi.File && cellNode.localFileAvailable()) {
add(NodeBottomSheetAction.SHARE)
}
add(NodeBottomSheetAction.PUBLIC_LINK)
}
}
commonActions(cellNode)
}

isConversationFiles -> {
buildList {
if (cellNode is CellNodeUi.File && cellNode.openLoadState is OpenLoadState.Loading) {
add(NodeBottomSheetAction.CANCEL_LOADING)
} else {
if (cellNode is CellNodeUi.File && cellNode.localFileAvailable()) {
add(NodeBottomSheetAction.SHARE)
}
add(NodeBottomSheetAction.PUBLIC_LINK)

if (isCollaboraEnabled && featureFlags.collaboraIntegration && cellNode.isEditSupported()) {
add(NodeBottomSheetAction.EDIT)
}

if (featureFlags.collaboraIntegration && cellNode.isEditSupported()) {
add(NodeBottomSheetAction.VERSION_HISTORY)
}

add(NodeBottomSheetAction.ADD_REMOVE_TAGS)
add(NodeBottomSheetAction.MOVE)
add(NodeBottomSheetAction.RENAME)
add(NodeBottomSheetAction.DELETE)
}
val common = commonActions(cellNode)
val isTerminal = cellNode is CellNodeUi.File &&
(cellNode.isOpenLoading || cellNode.downloadProgress != null)
if (isTerminal) {
common
} else {
common + conversationActions(
cellNode = cellNode,
isCollaboraEnabled = isCollaboraEnabled,
)
}
}

else -> {
emptyList()
else -> emptyList()
}
}

private fun recycleBinActions(): List<NodeBottomSheetAction> = listOf(
NodeBottomSheetAction.RESTORE,
NodeBottomSheetAction.DELETE_PERMANENTLY,
)

private fun commonActions(
cellNode: CellNodeUi,
): List<NodeBottomSheetAction> = buildList {

if (cellNode is CellNodeUi.File) {

when {
cellNode.isOpenLoading -> {
add(NodeBottomSheetAction.CANCEL_LOADING)
return@buildList
}

cellNode.downloadProgress != null -> {
add(NodeBottomSheetAction.CANCEL_DOWNLOAD)
return@buildList
}

else -> {
if (cellNode.localFileAvailable()) {
add(NodeBottomSheetAction.SHARE)
}

add(NodeBottomSheetAction.PUBLIC_LINK)

add(
if (cellNode.isAvailableOffline) {
NodeBottomSheetAction.REMOVE_OFFLINE_ACCESS
} else {
NodeBottomSheetAction.MAKE_AVAILABLE_OFFLINE
},
)
}
}
} else {
add(NodeBottomSheetAction.PUBLIC_LINK)
}
}

private fun conversationActions(
cellNode: CellNodeUi,
isCollaboraEnabled: Boolean,
): List<NodeBottomSheetAction> = buildList {

val canEdit = cellNode is CellNodeUi.File &&
isCollaboraEnabled &&
featureFlags.collaboraIntegration &&
cellNode.isEditSupported()

if (canEdit) {
add(NodeBottomSheetAction.EDIT)
}

if (
cellNode is CellNodeUi.File &&
featureFlags.collaboraIntegration &&
cellNode.isEditSupported()
) {
add(NodeBottomSheetAction.VERSION_HISTORY)
}

addAll(
listOf(
NodeBottomSheetAction.ADD_REMOVE_TAGS,
NodeBottomSheetAction.MOVE,
NodeBottomSheetAction.RENAME,
NodeBottomSheetAction.DELETE,
),
)
}

internal sealed interface MenuActionResult
internal data class Action(val action: CellViewAction) : MenuActionResult
internal data class Share(val node: CellNodeUi.File) : MenuActionResult
internal data class Edit(val node: CellNodeUi) : MenuActionResult
internal data class CancelLoading(val node: CellNodeUi) : MenuActionResult
internal data class CancelDownload(val node: CellNodeUi) : MenuActionResult
internal data class MakeAvailableOffline(val node: CellNodeUi.File) : MenuActionResult
internal data class RemoveOfflineAccess(val node: CellNodeUi.File) : MenuActionResult

internal fun onMenuItemAction(
conversationId: String?,
Expand Down Expand Up @@ -137,6 +187,22 @@ class CellFileActionsMenu @Inject constructor(
NodeBottomSheetAction.EDIT -> Edit(node)
NodeBottomSheetAction.VERSION_HISTORY -> Action(ShowVersionHistoryScreen(node.uuid, node.name ?: ""))
NodeBottomSheetAction.CANCEL_LOADING -> CancelLoading(node)
NodeBottomSheetAction.CANCEL_DOWNLOAD -> CancelDownload(node)
NodeBottomSheetAction.MAKE_AVAILABLE_OFFLINE -> {
if (node is CellNodeUi.File) {
MakeAvailableOffline(node)
} else {
Action(ShowPublicLinkScreen(node))
}
}

NodeBottomSheetAction.REMOVE_OFFLINE_ACCESS -> {
if (node is CellNodeUi.File) {
RemoveOfflineAccess(node)
} else {
Action(ShowPublicLinkScreen(node))
}
}
}

onResult(result)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import javax.inject.Singleton
*
* - [fileReadyEvents]: emitted when a slow download finishes so the UI can show a snackbar.
* - [openLoadStates]: per-uuid Loading / Ready / Error state consumed by paging combines.
* - [downloadProgresses]: per-uuid offline-download progress
*/
@Singleton
class CellFileLocalPathCache @Inject constructor() {
Expand All @@ -47,6 +48,9 @@ class CellFileLocalPathCache @Inject constructor() {
private val _openLoadStates = MutableStateFlow<Map<String, OpenLoadState>>(emptyMap())
internal val openLoadStates: StateFlow<Map<String, OpenLoadState>> = _openLoadStates.asStateFlow()

private val _downloadProgresses = MutableStateFlow<Map<String, Float?>>(emptyMap())
internal val downloadProgresses: StateFlow<Map<String, Float?>> = _downloadProgresses.asStateFlow()

// Session-level guard: records the local path once a download completes so that a
// subsequent tap opens the file immediately, even if the paging source hasn't refreshed
// yet with the new localPath from the DB.
Expand All @@ -57,6 +61,10 @@ class CellFileLocalPathCache @Inject constructor() {

internal fun getCompletedPath(uuid: String): String? = completedPaths[uuid]

internal fun clearCompletedPath(uuid: String) {
completedPaths.remove(uuid)
}

fun emitFileReady(file: CellNodeUi.File) {
_fileReadyChannel.trySend(file)
}
Expand All @@ -65,4 +73,10 @@ class CellFileLocalPathCache @Inject constructor() {
_openLoadStates.update { it + (uuid to state) }

internal fun clearOpenLoadState(uuid: String) = _openLoadStates.update { it - uuid }

internal fun setDownloadProgress(uuid: String, progress: Float?) =
_downloadProgresses.update { it + (uuid to progress) }

internal fun clearDownloadProgress(uuid: String) =
_downloadProgresses.update { it - uuid }
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
Expand Down
Loading
Loading