Repository: wireapp/wire-android
Pull request #4002: feat(Cells): Create cells folder flow (WPB-17272)
Author: login: ohassine
Labels: name: size/L
Created: 2025-04-24T13:15:08Z | Merged: 2025-04-29T11:51:56Z

<!--do not remove this marker, its needed to replace info when ticket title is updated -->
<!--jira-description-action-hidden-marker-start-->

<table>
<td>
  <a href="https://wearezeta.atlassian.net/browse/WPB-17272" title="WPB-17272" target="_blank"><img alt="Task" src="https://wearezeta.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10818?size=medium" />WPB-17272</a>  [Android] Create a folder
  </td></table>
  <br />
 

<!--jira-description-action-hidden-marker-end-->
----
#### PR Submission Checklist for internal contributors

- The **PR Title**
    - [ ] conforms to the style of semantic commits messages¹ supported in Wire's Github Workflow²
    - [x] contains a reference JIRA issue number like `SQPIT-764`
    - [ ] answers the question: _If merged, this PR will: ..._ ³

- The **PR Description**
    - [ ] is free of optional paragraphs and you have filled the relevant parts to the best of your ability
----

# What's new in this PR?

### Description

- Added a new floating button
- Added a new bottom sheet
- Added a new screen for creating a new folder
- Moved to shared UI components to the shared module

[Screen_recording_20250424_151220.webm](https://github.com/user-attachments/assets/ca9ec1d6-537a-40aa-8c1f-49ed8da1ea0a)

Needs releases with:

- [ ] GitHub link to other pull request

### Testing

#### Test Coverage (Optional)

- [ ] I have added automated test to this contribution

#### How to Test

_Briefly describe how this change was tested and if applicable the exact steps taken to verify that it works as expected._

### Notes (Optional)

_Specify here any other facts that you think are important for this issue._

### Attachments (Optional)

_Attachments like images, videos, etc. (drag and drop in the text box)_ 
<!-- Uncomment the brackets and place your screenshots on the table below. -->
<!--
| Before | After |
| ----------- | ------------ |
|   |   |
-->

----
#### PR Post Submission Checklist for internal contributors (Optional)

- [ ] Wire's Github Workflow has automatically linked the PR to a JIRA issue
----
#### PR Post Merge Checklist for internal contributors

- [ ] If any soft of configuration variable was introduced by this PR, it has been added to the relevant documents and the CI jobs have been updated.
----
##### References
1. https://sparkbox.com/foundry/semantic_commit_messages
1. https://github.com/wireapp/.github#usage
1. E.g. `feat(conversation-list): Sort conversations by most emojis in the title #SQPIT-764`.



Diff:
diff --git a/app/src/main/kotlin/com/wire/android/navigation/WireMainNavGraph.kt b/app/src/main/kotlin/com/wire/android/navigation/WireMainNavGraph.kt
index d71d8c08cdd..020e4765688 100644
--- a/app/src/main/kotlin/com/wire/android/navigation/WireMainNavGraph.kt
+++ b/app/src/main/kotlin/com/wire/android/navigation/WireMainNavGraph.kt
@@ -20,6 +20,7 @@ package com.wire.android.navigation
 import com.ramcosta.composedestinations.spec.DestinationSpec
 import com.ramcosta.composedestinations.spec.NavGraphSpec
 import com.wire.android.feature.cells.ui.destinations.ConversationFilesScreenDestination
+import com.wire.android.feature.cells.ui.destinations.CreateFolderScreenDestination
 import com.wire.android.feature.cells.ui.destinations.PublicLinkScreenDestination
 import com.wire.android.feature.sketch.destinations.DrawingCanvasScreenDestination
 import com.wire.android.ui.NavGraphs
@@ -31,6 +32,7 @@ object WireMainNavGraph : NavGraphSpec {
         .plus(DrawingCanvasScreenDestination)
         .plus(PublicLinkScreenDestination)
         .plus(ConversationFilesScreenDestination)
+        .plus(CreateFolderScreenDestination)
     override val destinationsByRoute = destinations.associateBy { it.route }
     override val nestedNavGraphs = NavGraphs.root.nestedNavGraphs
 }
diff --git a/app/src/main/kotlin/com/wire/android/ui/home/HomeScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/HomeScreen.kt
index 7e2f78a811f..b93cee1fde6 100644
--- a/app/src/main/kotlin/com/wire/android/ui/home/HomeScreen.kt
+++ b/app/src/main/kotlin/com/wire/android/ui/home/HomeScreen.kt
@@ -73,9 +73,9 @@ import com.wire.android.navigation.handleNavigation
 import com.wire.android.ui.NavGraphs
 import com.wire.android.ui.analytics.AnalyticsUsageViewModel
 import com.wire.android.ui.common.CollapsingTopBarScaffold
-import com.wire.android.ui.common.FloatingActionButton
 import com.wire.android.ui.common.bottomsheet.WireModalSheetLayout
 import com.wire.android.ui.common.bottomsheet.rememberWireModalSheetState
+import com.wire.android.ui.common.button.FloatingActionButton
 import com.wire.android.ui.common.dialogs.PermissionPermanentlyDeniedDialog
 import com.wire.android.ui.common.dimensions
 import com.wire.android.ui.common.snackbar.LocalSnackbarHostState
diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/CreateGuestLinkBottomSheet.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/CreateGuestLinkBottomSheet.kt
index 1f0f917fffd..4eb20b67192 100644
--- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/CreateGuestLinkBottomSheet.kt
+++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/details/editguestaccess/CreateGuestLinkBottomSheet.kt
@@ -19,7 +19,6 @@ package com.wire.android.ui.home.conversations.details.editguestaccess
 
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.tooling.preview.Preview
 import com.wire.android.R
 import com.wire.android.ui.common.ArrowRightIcon
 import com.wire.android.ui.common.bottomsheet.MenuBottomSheetItem
@@ -27,7 +26,10 @@ import com.wire.android.ui.common.bottomsheet.MenuModalSheetHeader
 import com.wire.android.ui.common.bottomsheet.WireMenuModalSheetContent
 import com.wire.android.ui.common.bottomsheet.WireModalSheetLayout
 import com.wire.android.ui.common.bottomsheet.WireModalSheetState
+import com.wire.android.ui.common.bottomsheet.WireSheetValue
 import com.wire.android.ui.common.bottomsheet.rememberWireModalSheetState
+import com.wire.android.ui.common.preview.MultipleThemePreviews
+import com.wire.android.ui.theme.WireTheme
 
 @Composable
 fun CreateGuestLinkBottomSheet(
@@ -74,22 +76,26 @@ private fun CreateInviteLinkSheetItem(
     )
 }
 
-@Preview
+@MultipleThemePreviews
 @Composable
-fun PreviewCreateGuestLinkBottomSheet() {
-    CreateGuestLinkBottomSheet(
-        sheetState = rememberWireModalSheetState(),
-        onItemClick = {},
-        isPasswordInviteLinksAllowed = true,
-    )
+private fun PreviewCreateGuestLinkBottomSheet() {
+    WireTheme {
+        CreateGuestLinkBottomSheet(
+            sheetState = rememberWireModalSheetState(WireSheetValue.Expanded(value = Unit)),
+            onItemClick = {},
+            isPasswordInviteLinksAllowed = true,
+        )
+    }
 }
 
-@Preview
+@MultipleThemePreviews
 @Composable
-fun PreviewCreateGuestLinkBottomSheetDisabled() {
-    CreateGuestLinkBottomSheet(
-        sheetState = rememberWireModalSheetState(),
-        onItemClick = {},
-        isPasswordInviteLinksAllowed = false,
-    )
+private fun PreviewCreateGuestLinkBottomSheetDisabled() {
+    WireTheme {
+        CreateGuestLinkBottomSheet(
+            sheetState = rememberWireModalSheetState(WireSheetValue.Expanded(value = Unit)),
+            onItemClick = {},
+            isPasswordInviteLinksAllowed = false,
+        )
+    }
 }
diff --git a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt
index 1ff7fb10cdc..2c90300382d 100644
--- a/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt
+++ b/app/src/main/kotlin/com/wire/android/ui/home/messagecomposer/MessageComposerInput.kt
@@ -18,6 +18,7 @@
 
 package com.wire.android.ui.home.messagecomposer
 
+import android.view.KeyEvent
 import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.foundation.background
 import androidx.compose.foundation.focusable
@@ -317,7 +318,7 @@ private fun MessageComposerTextInput(
                 }
             }
             .onPreInterceptKeyBeforeSoftKeyboard { event ->
-                if (event.key.nativeKeyCode == android.view.KeyEvent.KEYCODE_BACK) {
+                if (event.key.nativeKeyCode == KeyEvent.KEYCODE_BACK) {
                     onClearFocus()
                     if (isTextExpanded) {
                         onTextCollapse()
diff --git a/app/src/main/kotlin/com/wire/android/util/StringUtil.kt b/app/src/main/kotlin/com/wire/android/util/StringUtil.kt
index 14dee701d41..a75ab0b1f66 100644
--- a/app/src/main/kotlin/com/wire/android/util/StringUtil.kt
+++ b/app/src/main/kotlin/com/wire/android/util/StringUtil.kt
@@ -1,53 +1,6 @@
-/*
- * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/.
- */
-
 package com.wire.android.util
 
 import com.wire.android.ui.markdown.isNotBlank
 import com.wire.android.ui.markdown.toMarkdownDocument
-import java.math.BigInteger
-import java.security.MessageDigest
-
-val String.Companion.EMPTY get() = ""
-
-val String.Companion.WHITE_SPACE get() = " "
-
-val String.Companion.MENTION_SYMBOL get() = "@"
-
-val String.Companion.NEW_LINE_SYMBOL get() = "\n"
-
-fun String?.orDefault(default: String) = this ?: default
-
-inline fun String.ifNotEmpty(transform: () -> String): String = if (!isEmpty()) transform() else this
-
-@Suppress("MagicNumber")
-fun String.sha256(): String {
-    val md = MessageDigest.getInstance("SHA-256")
-    return BigInteger(1, md.digest(toByteArray())).toString(16).padStart(32, '0')
-}
-
-fun String.toTitleCase(delimiter: String = " ", separator: String = " "): String =
-    this.split(delimiter).joinToString(separator = separator) {
-        it.lowercase().replaceFirstChar(Char::titlecaseChar)
-    }
-
-fun String.capitalizeFirstLetter(): String = lowercase().replaceFirstChar(Char::titlecaseChar)
-
-fun String.normalizeFileName(): String = this.replace("/", "")
 
 fun CharSequence.isNotMarkdownBlank(): Boolean = this.isNotBlank() && this.toString().toMarkdownDocument().isNotBlank()
diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml
index 8588b884600..854b89328dd 100644
--- a/app/src/main/res/values/integers.xml
+++ b/app/src/main/res/values/integers.xml
@@ -20,5 +20,4 @@
 <resources>
     <integer name="welcome_carousel_item_time_ms">3000</integer>
     <integer name="splashscreen_animation_ms">1000</integer>
-    <integer name="code_length">6</integer>
 </resources>
diff --git a/core/navigation/src/main/kotlin/com/wire/android/navigation/PreviewNavigator.kt b/core/navigation/src/main/kotlin/com/wire/android/navigation/PreviewNavigator.kt
new file mode 100644
index 00000000000..82d580e527e
--- /dev/null
+++ b/core/navigation/src/main/kotlin/com/wire/android/navigation/PreviewNavigator.kt
@@ -0,0 +1,23 @@
+/*
+ * Wire
+ * Copyright (C) 2025 Wire Swiss GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ */
+package com.wire.android.navigation
+
+object PreviewNavigator : WireNavigator {
+    override fun navigate(navigationCommand: NavigationCommand, onlyIfResumed: Boolean) { /* No-op */ }
+    override fun navigateBack(onlyIfResumed: Boolean) { /* No-op */ }
+}
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/FloatingActionButton.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/FloatingActionButton.kt
similarity index 97%
rename from app/src/main/kotlin/com/wire/android/ui/common/FloatingActionButton.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/FloatingActionButton.kt
index 54b3bf2e357..4e92b808308 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/FloatingActionButton.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/button/FloatingActionButton.kt
@@ -16,7 +16,7 @@
  * along with this program. If not, see http://www.gnu.org/licenses/.
  */
 
-package com.wire.android.ui.common
+package com.wire.android.ui.common.button
 
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Add
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextField.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextField.kt
similarity index 97%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextField.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextField.kt
index af7d5553dde..7a06677d651 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextField.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextField.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -38,11 +38,11 @@ import androidx.compose.ui.text.TextStyle
 import androidx.compose.ui.text.input.ImeAction
 import androidx.compose.ui.text.input.KeyboardType
 import androidx.compose.ui.unit.Dp
-import com.wire.android.R
+import com.wire.android.ui.common.R
 import com.wire.android.ui.theme.WireTheme
 import com.wire.android.ui.theme.wireDimensions
 import com.wire.android.ui.theme.wireTypography
-import com.wire.android.util.ui.PreviewMultipleThemes
+import com.wire.android.util.PreviewMultipleThemes
 
 @Composable
 fun CodeTextField(
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextFieldLayout.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextFieldLayout.kt
similarity index 99%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextFieldLayout.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextFieldLayout.kt
index d84925299ec..ce9a44aaa50 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextFieldLayout.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/CodeTextFieldLayout.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/InputTransformations.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/InputTransformations.kt
similarity index 97%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/InputTransformations.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/InputTransformations.kt
index e6c31c049ca..5d8e2ce903a 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/InputTransformations.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/InputTransformations.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -46,7 +46,9 @@ class MaxLengthDigitsFilter(private val maxLength: Int) : InputTransformation {
 }
 
 @Stable
-fun InputTransformation.maxLengthDigits(maxLength: Int): InputTransformation = this.then(MaxLengthDigitsFilter(maxLength))
+fun InputTransformation.maxLengthDigits(maxLength: Int): InputTransformation = this.then(
+    MaxLengthDigitsFilter(maxLength)
+)
 
 class MaxLengthFilterWithCallback(private val maxLength: Int, private val onIncorrectChangesFound: () -> Unit) : InputTransformation {
     init {
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireLabel.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireLabel.kt
similarity index 95%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/WireLabel.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireLabel.kt
index 4f9aabd3dfe..c79290acf34 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireLabel.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireLabel.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,11 +29,11 @@ import androidx.compose.runtime.remember
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.res.vectorResource
-import com.wire.android.R
+import com.wire.android.ui.common.R
 import com.wire.android.ui.common.dimensions
 import com.wire.android.ui.theme.WireTheme
 import com.wire.android.ui.theme.wireTypography
-import com.wire.android.util.ui.PreviewMultipleThemes
+import com.wire.android.util.PreviewMultipleThemes
 
 @Composable
 fun WireLabel(
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WirePasswordTextField.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WirePasswordTextField.kt
similarity index 97%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/WirePasswordTextField.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WirePasswordTextField.kt
index 87626e8f3aa..d219461d26c 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WirePasswordTextField.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WirePasswordTextField.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -58,13 +58,14 @@ import androidx.compose.ui.text.style.TextAlign
 import androidx.compose.ui.text.style.TextDirection
 import androidx.compose.ui.unit.Dp
 import androidx.compose.ui.unit.dp
-import com.wire.android.R
+import com.wire.android.ui.common.R
 import com.wire.android.ui.common.dimensions
 import com.wire.android.ui.theme.WireTheme
 import com.wire.android.ui.theme.wireDimensions
 import com.wire.android.ui.theme.wireTypography
 import com.wire.android.util.EMPTY
-import com.wire.android.util.ui.PreviewMultipleThemes
+import com.wire.android.util.PreviewMultipleThemes
+import java.util.Locale
 
 @Composable
 fun WirePasswordTextField(
@@ -95,7 +96,7 @@ fun WirePasswordTextField(
     WireTextFieldLayout(
         shouldShowPlaceholder = textState.text.isEmpty(),
         placeholderText = placeholderText,
-        labelText = labelText,
+        labelText = labelText?.uppercase(Locale.getDefault()),
         labelMandatoryIcon = labelMandatoryIcon,
         descriptionText = descriptionText,
         semanticDescription = semanticDescription,
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt
similarity index 98%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt
index e50889c5706..61a9332eb1b 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextField.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -61,10 +61,10 @@ import com.wire.android.ui.theme.WireTheme
 import com.wire.android.ui.theme.wireDimensions
 import com.wire.android.ui.theme.wireTypography
 import com.wire.android.util.EMPTY
-import com.wire.android.util.ui.PreviewMultipleThemes
+import com.wire.android.util.PreviewMultipleThemes
 
 @Composable
-internal fun WireTextField(
+fun WireTextField(
     textState: TextFieldState,
     modifier: Modifier = Modifier,
     placeholderText: String? = null,
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldAutoFill.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldAutoFill.kt
similarity index 98%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldAutoFill.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldAutoFill.kt
index f8510f44f95..6f2de4cf788 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldAutoFill.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldAutoFill.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldDefaults.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldDefaults.kt
similarity index 99%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldDefaults.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldDefaults.kt
index c561b967438..00a826ac399 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldDefaults.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldDefaults.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt
similarity index 99%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt
index b99c98af954..d59ef2f037e 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldLayout.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldState.kt b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldState.kt
similarity index 97%
rename from app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldState.kt
rename to core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldState.kt
index b26bf6c6a1f..0556953b4a5 100644
--- a/app/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldState.kt
+++ b/core/ui-common/src/main/kotlin/com/wire/android/ui/common/textfield/WireTextFieldState.kt
@@ -1,6 +1,6 @@
 /*
  * Wire
- * Copyright (C) 2024 Wire Swiss GmbH
+ * Copyright (C) 2025 Wire Swiss GmbH
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
diff --git a/core/ui-common/src/main/kotlin/com/wire/android/util/StringUtils.kt b/core/ui-common/src/main/kotlin/com/wire/android/util/StringUtils.kt
new file mode 100644
index 00000000000..296c8dcacf2
--- /dev/null
+++ b/core/ui-common/src/main/kotlin/com/wire/android/util/StringUtils.kt
@@ -0,0 +1,49 @@
+/*
+ * Wire
+ * Copyright (C) 2024 Wire Swiss GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ */
+
+package com.wire.android.util
+
+import java.math.BigInteger
+import java.security.MessageDigest
+
+val String.Companion.EMPTY get() = ""
+
+val String.Companion.WHITE_SPACE get() = " "
+
+val String.Companion.MENTION_SYMBOL get() = "@"
+
+val String.Companion.NEW_LINE_SYMBOL get() = "\n"
+
+fun String?.orDefault(default: String) = this ?: default
+
+inline fun String.ifNotEmpty(transform: () -> String): String = if (!isEmpty()) transform() else this
+
+@Suppress("MagicNumber")
+fun String.sha256(): String {
+    val md = MessageDigest.getInstance("SHA-256")
+    return BigInteger(1, md.digest(toByteArray())).toString(16).padStart(32, '0')
+}
+
+fun String.toTitleCase(delimiter: String = " ", separator: String = " "): String =
+    this.split(delimiter).joinToString(separator = separator) {
+        it.lowercase().replaceFirstChar(Char::titlecaseChar)
+    }
+
+fun String.capitalizeFirstLetter(): String = lowercase().replaceFirstChar(Char::titlecaseChar)
+
+fun String.normalizeFileName(): String = this.replace("/", "")
diff --git a/app/src/main/res/drawable/ic_input_mandatory.xml b/core/ui-common/src/main/res/drawable/ic_input_mandatory.xml
similarity index 100%
rename from app/src/main/res/drawable/ic_input_mandatory.xml
rename to core/ui-common/src/main/res/drawable/ic_input_mandatory.xml
diff --git a/core/ui-common/src/main/res/drawable/ic_plus.xml b/core/ui-common/src/main/res/drawable/ic_plus.xml
new file mode 100644
index 00000000000..d482e4dfad0
--- /dev/null
+++ b/core/ui-common/src/main/res/drawable/ic_plus.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="16dp"
+    android:height="16dp"
+    android:viewportWidth="16"
+    android:viewportHeight="16">
+  <path
+      android:pathData="M0,7V9H7V16H9V9H16V7H9V0H7V7H0Z"
+      android:fillColor="#ffffff"
+      android:fillType="evenOdd"/>
+</vector>
diff --git a/core/ui-common/src/main/res/values/integers.xml b/core/ui-common/src/main/res/values/integers.xml
new file mode 100644
index 00000000000..e90752bba04
--- /dev/null
+++ b/core/ui-common/src/main/res/values/integers.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Wire
+  ~ Copyright (C) 2024 Wire Swiss GmbH
+  ~
+  ~ This program is free software: you can redistribute it and/or modify
+  ~ it under the terms of the GNU General Public License as published by
+  ~ the Free Software Foundation, either version 3 of the License, or
+  ~ (at your option) any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  ~ GNU General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU General Public License
+  ~ along with this program. If not, see http://www.gnu.org/licenses/.
+  -->
+
+<resources>
+    <integer name="code_length">6</integer>
+</resources>
diff --git a/core/ui-common/src/main/res/values/strings.xml b/core/ui-common/src/main/res/values/strings.xml
index ae450d738d4..5bd14972bd1 100644
--- a/core/ui-common/src/main/res/values/strings.xml
+++ b/core/ui-common/src/main/res/values/strings.xml
@@ -17,6 +17,10 @@
   -->
 <resources>
     <string name="module_name" translatable="false">ui commons</string>
+    <string name="login_password_placeholder">Password</string>
+    <string name="login_password_label">Password</string>
+    <string name="content_description_reveal_password">Show password</string>
+    <string name="content_description_hide_password">Hide password</string>
     <string name="label_wait_until_synchronised">Please wait until the app is synchronized</string>
     <string name="label_wait_until_connected">Please wait until the Internet connection is restored</string>
     <string name="content_description_back_button">Back button</string>
diff --git a/features/cells/src/main/java/com/wire/android/feature/cells/ui/CellFilesScreen.kt b/features/cells/src/main/java/com/wire/android/feature/cells/ui/CellFilesScreen.kt
index c3b8139ee4a..f576ac6c41e 100644
--- a/features/cells/src/main/java/com/wire/android/feature/cells/ui/CellFilesScreen.kt
+++ b/features/cells/src/main/java/com/wire/android/feature/cells/ui/CellFilesScreen.kt
@@ -24,9 +24,12 @@ import androidx.compose.foundation.lazy.LazyColumn
 import androidx.compose.foundation.lazy.items
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
+import com.wire.android.feature.cells.domain.model.AttachmentFileType
 import com.wire.android.feature.cells.ui.model.CellFileUi
 import com.wire.android.ui.common.colorsScheme
 import com.wire.android.ui.common.divider.WireDivider
+import com.wire.android.ui.common.preview.MultipleThemePreviews
+import com.wire.android.ui.theme.WireTheme
 
 @Composable
 internal fun CellFilesScreen(
@@ -41,24 +44,53 @@ internal fun CellFilesScreen(
 //        isRefreshing = state.refreshing,
 //        onRefresh = { onRefresh() }
 //    ) {
-        LazyColumn(
-            modifier = Modifier
-                .background(color = colorsScheme().surface)
-                .fillMaxWidth(),
-        ) {
-            items(
-                items = files,
-                key = { it.uuid },
-            ) { file ->
-                CellListItem(
-                    modifier = Modifier
-                        .animateItem()
-                        .clickable { onFileClick(file) },
-                    file = file,
-                    onMenuClick = { onFileMenuClick(file) }
-                )
-                WireDivider(modifier = Modifier.fillMaxWidth())
-            }
+    LazyColumn(
+        modifier = Modifier
+            .background(color = colorsScheme().surface)
+            .fillMaxWidth(),
+    ) {
+        items(
+            items = files,
+            key = { it.uuid },
+        ) { file ->
+            CellListItem(
+                modifier = Modifier
+                    .animateItem()
+                    .clickable { onFileClick(file) },
+                file = file,
+                onMenuClick = { onFileMenuClick(file) }
+            )
+            WireDivider(modifier = Modifier.fillMaxWidth())
         }
+    }
 //    }
 }
+
+@MultipleThemePreviews
+@Composable
+fun PreviewCellFilesScreen() {
+    WireTheme {
+        CellFilesScreen(
+            files = listOf(
+                CellFileUi(
+                    uuid = "uuid",
+                    fileName = "Image name",
+                    mimeType = "image/png",
+                    assetType = AttachmentFileType.IMAGE,
+                    assetSize = 1234L,
+                    localPath = "path/to/local/file",
+                ),
+                CellFileUi(
+                    uuid = "uuid2",
+                    fileName = "PDF name",
+                    mimeType = "application/pdf",
+                    assetType = AttachmentFileType.PDF,
+                    assetSize = 99234L,
+                    localPath = "path/to/local/file",
+                )
+            ),
+            onFileClick = {},
+            onFileMenuClick = {}
+        )
+    }
+}
diff --git a/features/cells/src/main/java/com/wire/android/feature/cells/ui/ConversationFilesScreen.kt b/features/cells/src/main/java/com/wire/android/feature/cells/ui/ConversationFilesScreen.kt
index 8a10d139fc4..881d50ae37c 100644
--- a/features/cells/src/main/java/com/wire/android/feature/cells/ui/ConversationFilesScreen.kt
+++ b/features/cells/src/main/java/com/wire/android/feature/cells/ui/ConversationFilesScreen.kt
@@ -17,20 +17,34 @@
  */
 package com.wire.android.feature.cells.ui
 
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.foundation.Image
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.MaterialTheme
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.res.painterResource
 import androidx.compose.ui.res.stringResource
 import androidx.hilt.navigation.compose.hiltViewModel
 import com.ramcosta.composedestinations.annotation.Destination
 import com.wire.android.feature.cells.R
+import com.wire.android.feature.cells.ui.destinations.CreateFolderScreenDestination
 import com.wire.android.feature.cells.ui.destinations.PublicLinkScreenDestination
+import com.wire.android.feature.cells.ui.dialog.FilesNewActionsBottomSheet
 import com.wire.android.navigation.NavigationCommand
 import com.wire.android.navigation.WireNavigator
 import com.wire.android.navigation.style.PopUpNavigationAnimation
+import com.wire.android.ui.common.bottomsheet.rememberWireModalSheetState
+import com.wire.android.ui.common.bottomsheet.show
+import com.wire.android.ui.common.button.FloatingActionButton
 import com.wire.android.ui.common.dimensions
 import com.wire.android.ui.common.scaffold.WireScaffold
 import com.wire.android.ui.common.topappbar.NavigationIconType
@@ -52,7 +66,17 @@ fun ConversationFilesScreen(
 ) {
 
     val state by viewModel.state.collectAsState()
+    val sheetState = rememberWireModalSheetState<Unit>()
 
+    FilesNewActionsBottomSheet(
+        sheetState = sheetState,
+        onDismiss = {
+            sheetState.hide()
+        },
+        onCreateFolder = {
+            navigator.navigate(NavigationCommand(CreateFolderScreenDestination()))
+        }
+    )
     WireScaffold(
         modifier = modifier,
         topBar = {
@@ -62,6 +86,34 @@ fun ConversationFilesScreen(
                 navigationIconType = NavigationIconType.Close(),
                 elevation = dimensions().spacing0x
             )
+        },
+        floatingActionButton = {
+            if (state is CellViewState.Files) {
+                AnimatedVisibility(
+                    visible = true,
+                    enter = fadeIn(),
+                    exit = fadeOut(),
+                ) {
+                    FloatingActionButton(
+                        text = stringResource(R.string.cells_new_label),
+                        icon = {
+                            Image(
+                                painter = painterResource(id = com.wire.android.ui.common.R.drawable.ic_plus),
+                                contentDescription = stringResource(R.string.cells_new_label_content_description),
+                                contentScale = ContentScale.FillBounds,
+                                colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onPrimary),
+                                modifier = Modifier
+                                    .padding(
+                                        start = dimensions().spacing4x,
+                                        top = dimensions().spacing2x
+                                    )
+                                    .size(dimensions().fabIconSize)
+                            )
+                        },
+                        onClick = { sheetState.show() }
+                    )
+                }
+            }
         }
     ) { innerPadding ->
         Box(modifier = Modifier.padding(innerPadding)) {
diff --git a/features/cells/src/main/java/com/wire/android/feature/cells/ui/createfolder/CreateFolderScreen.kt b/features/cells/src/main/java/com/wire/android/feature/cells/ui/createfolder/CreateFolderScreen.kt
new file mode 100644
index 00000000000..7b8bda1d514
--- /dev/null
+++ b/features/cells/src/main/java/com/wire/android/feature/cells/ui/createfolder/CreateFolderScreen.kt
@@ -0,0 +1,118 @@
+/*
+ * Wire
+ * Copyright (C) 2025 Wire Swiss GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ */
+package com.wire.android.feature.cells.ui.createfolder
+
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.expandVertically
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.shrinkVertically
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.input.TextFieldState
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import com.ramcosta.composedestinations.annotation.Destination
+import com.wire.android.feature.cells.R
+import com.wire.android.model.ClickBlockParams
+import com.wire.android.navigation.PreviewNavigator
+import com.wire.android.navigation.WireNavigator
+import com.wire.android.navigation.style.PopUpNavigationAnimation
+import com.wire.android.ui.common.button.WireButtonState
+import com.wire.android.ui.common.button.WirePrimaryButton
+import com.wire.android.ui.common.dimensions
+import com.wire.android.ui.common.preview.MultipleThemePreviews
+import com.wire.android.ui.common.scaffold.WireScaffold
+import com.wire.android.ui.common.textfield.WireTextField
+import com.wire.android.ui.common.topappbar.NavigationIconType
+import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar
+import com.wire.android.ui.theme.WireTheme
+import com.wire.android.ui.theme.wireColorScheme
+import com.wire.android.ui.theme.wireDimensions
+import java.util.Locale
+
+@Destination(
+    style = PopUpNavigationAnimation::class
+)
+@Composable
+fun CreateFolderScreen(
+    navigator: WireNavigator,
+    modifier: Modifier = Modifier,
+) {
+    WireScaffold(
+        modifier = modifier,
+        topBar = {
+            WireCenterAlignedTopAppBar(
+                onNavigationPressed = { navigator.navigateBack() },
+                navigationIconType = NavigationIconType.Close(),
+                elevation = dimensions().spacing0x,
+                title = stringResource(id = R.string.cells_create_folder),
+            )
+        },
+        bottomBar = {
+            AnimatedVisibility(
+                visible = true,
+                enter = fadeIn() + expandVertically(),
+                exit = shrinkVertically() + fadeOut(),
+            ) {
+                Surface(
+                    color = MaterialTheme.wireColorScheme.background,
+                    shadowElevation = MaterialTheme.wireDimensions.bottomNavigationShadowElevation
+                ) {
+                    Column(
+                        verticalArrangement = Arrangement.Center,
+                        modifier = Modifier
+                            .padding(dimensions().spacing16x)
+                    ) {
+                        WirePrimaryButton(
+                            text = stringResource(R.string.cells_create_folder),
+                            onClick = {},
+                            state = WireButtonState.Default,
+                            clickBlockParams = ClickBlockParams(blockWhenSyncing = true, blockWhenConnecting = true),
+                        )
+                    }
+                }
+            }
+        }
+    ) {
+        WireTextField(
+            textState = TextFieldState(),
+            placeholderText = stringResource(R.string.cells_folder_name),
+            labelText = stringResource(R.string.cells_folder_name).uppercase(Locale.getDefault()),
+            modifier = Modifier
+                .padding(it)
+                .padding(
+                    top = dimensions().spacing32x,
+                    start = dimensions().spacing16x,
+                    end = dimensions().spacing16x
+                )
+        )
+    }
+}
+
+@MultipleThemePreviews
+@Composable
+fun PreviewCreateFolderScreen() {
+    WireTheme {
+        CreateFolderScreen(navigator = PreviewNavigator)
+    }
+}
diff --git a/features/cells/src/main/java/com/wire/android/feature/cells/ui/dialog/FilesNewActionsBottomSheet.kt b/features/cells/src/main/java/com/wire/android/feature/cells/ui/dialog/FilesNewActionsBottomSheet.kt
new file mode 100644
index 00000000000..2728736d63e
--- /dev/null
+++ b/features/cells/src/main/java/com/wire/android/feature/cells/ui/dialog/FilesNewActionsBottomSheet.kt
@@ -0,0 +1,95 @@
+/*
+ * Wire
+ * Copyright (C) 2025 Wire Swiss GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ */
+package com.wire.android.feature.cells.ui.dialog
+
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.Icon
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import com.wire.android.feature.cells.R
+import com.wire.android.feature.cells.ui.util.PreviewMultipleThemes
+import com.wire.android.ui.common.bottomsheet.MenuBottomSheetItem
+import com.wire.android.ui.common.bottomsheet.WireMenuModalSheetContent
+import com.wire.android.ui.common.bottomsheet.WireModalSheetLayout
+import com.wire.android.ui.common.bottomsheet.WireModalSheetState
+import com.wire.android.ui.common.bottomsheet.WireSheetValue
+import com.wire.android.ui.common.bottomsheet.rememberWireModalSheetState
+import com.wire.android.ui.theme.WireTheme
+import com.wire.android.ui.theme.wireDimensions
+
+@Composable
+internal fun FilesNewActionsBottomSheet(
+    sheetState: WireModalSheetState<Unit>,
+    onDismiss: () -> Unit,
+    onCreateFolder: () -> Unit,
+) {
+    WireModalSheetLayout(
+        onDismissRequest = {
+            onDismiss()
+        },
+        sheetState = sheetState
+    ) {
+        WireMenuModalSheetContent(
+            menuItems = buildList {
+                add {
+                    CreateFolderSheetItem(
+                        title = stringResource(R.string.cells_create_folder),
+                        onClicked = onCreateFolder,
+                        enabled = true
+                    )
+                }
+            }
+        )
+    }
+}
+
+@Composable
+private fun CreateFolderSheetItem(
+    title: String,
+    onClicked: () -> Unit,
+    enabled: Boolean,
+) {
+    MenuBottomSheetItem(
+        title = title,
+        onItemClick = onClicked,
+        leading = {
+            Icon(
+                painter = painterResource(id = R.drawable.ic_folder),
+                contentDescription = null,
+                modifier = Modifier
+                    .size(MaterialTheme.wireDimensions.wireIconButtonSize)
+            )
+        },
+        enabled = enabled
+    )
+}
+
+@PreviewMultipleThemes
+@Composable
+private fun PreviewFilesNewActionsBottomSheet() {
+    WireTheme {
+        FilesNewActionsBottomSheet(
+            sheetState = rememberWireModalSheetState(WireSheetValue.Expanded(value = Unit)),
+            onDismiss = {},
+            onCreateFolder = {}
+        )
+    }
+}
diff --git a/features/cells/src/main/res/drawable/ic_folder.xml b/features/cells/src/main/res/drawable/ic_folder.xml
new file mode 100644
index 00000000000..47bc7074da5
--- /dev/null
+++ b/features/cells/src/main/res/drawable/ic_folder.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="16dp"
+    android:height="15dp"
+    android:viewportWidth="16"
+    android:viewportHeight="15">
+  <path
+      android:pathData="M14.584,3.732C14.584,3.732 8.182,3.704 5.554,3.747C4.742,3.76 3.224,3.949 2.927,5.662C2.614,7.463 2.139,14.025 2.194,13.28C2.194,13.28 2.849,12.795 2.957,12.119C3.142,10.968 3.38,9.086 3.441,8.352C3.503,7.62 3.553,5.932 5.066,5.886C6.289,5.849 12.144,5.785 14.416,5.886C15.451,5.932 15.631,6.574 15.439,7.812C15.213,9.262 14.832,12.185 14.731,12.679C14.665,13.002 14.072,14.457 12.705,14.503C10.559,14.575 2.804,14.503 2.194,14.503C1.583,14.503 0.177,14.136 0.054,12.609C-0.068,11.081 0.054,2.244 0.054,1.67C0.054,0.775 0.253,0.02 1.215,0.02C3.034,0.02 4.338,-0 4.753,-0C5.967,-0 5.738,2.052 8.304,1.978L12.918,1.97C13.289,1.975 14.566,2.02 14.599,2.877C14.623,3.472 14.584,3.732 14.584,3.732Z"
+      android:fillColor="#000000"
+      android:fillType="evenOdd"/>
+</vector>
diff --git a/features/cells/src/main/res/values/strings.xml b/features/cells/src/main/res/values/strings.xml
index 2583d79ebed..6202a1828b5 100644
--- a/features/cells/src/main/res/values/strings.xml
+++ b/features/cells/src/main/res/values/strings.xml
@@ -50,4 +50,8 @@
     <string name="error_share_link">Failed to share link.</string>
     <string name="conversation_files_title">Files</string>
     <string name="creating_link">Creating public link…</string>
+    <string name="cells_new_label">New</string>
+    <string name="cells_new_label_content_description">New</string>
+    <string name="cells_create_folder">Create Folder</string>
+    <string name="cells_folder_name">Folder Name</string>
 </resources>


Reviews:
user: login: sbakhtiarov
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T10:49:22Z
user: login: saleniuk
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T10:50:46Z
user: login: saleniuk
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T10:52:20Z
user: login: ohassine
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-29T11:21:16Z

Review comments:
diff_hunk: @@ -52,7 +66,17 @@ fun ConversationFilesScreen(
 ) {
 
     val state by viewModel.state.collectAsState()
+    val sheetState = rememberWireModalSheetState<Unit>()
 
+    FilesNewActionsBottomSheet(
path: features/cells/src/main/java/com/wire/android/feature/cells/ui/ConversationFilesScreen.kt
user: login: sbakhtiarov
body: Do we have this menu only for conversation files? Maybe we could move it to the "CellScreenContent" so that this bottom sheet will be available also on the all files screen?
created_at: 2025-04-29T10:45:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -62,6 +86,34 @@ fun ConversationFilesScreen(
                 navigationIconType = NavigationIconType.Close(),
                 elevation = dimensions().spacing0x
             )
+        },
+        floatingActionButton = {
path: features/cells/src/main/java/com/wire/android/feature/cells/ui/ConversationFilesScreen.kt
user: login: sbakhtiarov
body: Same as for the menu. We could move this also to "CellScreenContent" to make the FAB available for all file list screens.
created_at: 2025-04-29T10:46:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,127 @@
+/*
+ * Wire
+ * Copyright (C) 2025 Wire Swiss GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+ */
+package com.wire.android.feature.cells.ui.createfolder
+
+import androidx.compose.animation.AnimatedVisibility
+import androidx.compose.animation.expandVertically
+import androidx.compose.animation.fadeIn
+import androidx.compose.animation.fadeOut
+import androidx.compose.animation.shrinkVertically
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.text.input.TextFieldState
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import com.ramcosta.composedestinations.annotation.Destination
+import com.wire.android.feature.cells.R
+import com.wire.android.model.ClickBlockParams
+import com.wire.android.navigation.NavigationCommand
+import com.wire.android.navigation.WireNavigator
+import com.wire.android.navigation.style.PopUpNavigationAnimation
+import com.wire.android.ui.common.button.WireButtonState
+import com.wire.android.ui.common.button.WirePrimaryButton
+import com.wire.android.ui.common.dimensions
+import com.wire.android.ui.common.preview.MultipleThemePreviews
+import com.wire.android.ui.common.scaffold.WireScaffold
+import com.wire.android.ui.common.textfield.WireTextField
+import com.wire.android.ui.common.topappbar.NavigationIconType
+import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar
+import com.wire.android.ui.theme.WireTheme
+import com.wire.android.ui.theme.wireColorScheme
+import com.wire.android.ui.theme.wireDimensions
+import java.util.Locale
+
+@Destination(
+    style = PopUpNavigationAnimation::class
+)
+@Composable
+fun CreateFolderScreen(
+    navigator: WireNavigator,
+    modifier: Modifier = Modifier,
+) {
+    WireScaffold(
+        modifier = modifier,
+        topBar = {
+            WireCenterAlignedTopAppBar(
+                onNavigationPressed = { navigator.navigateBack() },
+                navigationIconType = NavigationIconType.Close(),
+                elevation = dimensions().spacing0x,
+                title = stringResource(id = R.string.cells_create_folder),
+            )
+        },
+        bottomBar = {
+            AnimatedVisibility(
+                visible = true,
+                enter = fadeIn() + expandVertically(),
+                exit = shrinkVertically() + fadeOut(),
+            ) {
+                Surface(
+                    color = MaterialTheme.wireColorScheme.background,
+                    shadowElevation = MaterialTheme.wireDimensions.bottomNavigationShadowElevation
+                ) {
+                    Column(
+                        verticalArrangement = Arrangement.Center,
+                        modifier = Modifier
+                            .padding(dimensions().spacing16x)
+                    ) {
+                        WirePrimaryButton(
+                            text = stringResource(R.string.cells_create_folder),
+                            onClick = {},
+                            state = WireButtonState.Default,
+                            clickBlockParams = ClickBlockParams(blockWhenSyncing = true, blockWhenConnecting = true),
+                        )
+                    }
+                }
+            }
+        }
+    ) {
+        WireTextField(
+            textState = TextFieldState(),
+            placeholderText = stringResource(R.string.cells_folder_name),
+            labelText = stringResource(R.string.cells_folder_name).uppercase(Locale.getDefault()),
+            modifier = Modifier
+                .padding(it)
+                .padding(
+                    top = dimensions().spacing32x,
+                    start = dimensions().spacing16x,
+                    end = dimensions().spacing16x
+                )
+        )
+    }
+}
+
+@MultipleThemePreviews
+@Composable
+fun PreviewCreateFolderScreen() {
+    val dummyNavigator = object : WireNavigator {
+        override fun navigate(navigationCommand: NavigationCommand, onlyIfResumed: Boolean) {
+            TODO("Not yet implemented")
+        }
+
+        override fun navigateBack(onlyIfResumed: Boolean) {
+            TODO("Not yet implemented")
+        }
+    }
path: features/cells/src/main/java/com/wire/android/feature/cells/ui/createfolder/CreateFolderScreen.kt
user: login: saleniuk
body: I would suggest to create such object in the `WireNavigator.kt`, something like:
```
object PreviewNavigator : WireNavigator {
    override fun navigate(navigationCommand: NavigationCommand, onlyIfResumed: Boolean) { /* No-op */ }
    override fun navigateBack(onlyIfResumed: Boolean) { /* No-op */ }
}
```
so that we could reuse it everywhere 💪 
created_at: 2025-04-29T10:50:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -52,7 +66,17 @@ fun ConversationFilesScreen(
 ) {
 
     val state by viewModel.state.collectAsState()
+    val sheetState = rememberWireModalSheetState<Unit>()
 
+    FilesNewActionsBottomSheet(
path: features/cells/src/main/java/com/wire/android/feature/cells/ui/ConversationFilesScreen.kt
user: login: ohassine
body: Yes only for conversation files.
created_at: 2025-04-29T11:19:36Z
author_association: MEMBER
diff_hunk: @@ -62,6 +86,34 @@ fun ConversationFilesScreen(
                 navigationIconType = NavigationIconType.Close(),
                 elevation = dimensions().spacing0x
             )
+        },
+        floatingActionButton = {
path: features/cells/src/main/java/com/wire/android/feature/cells/ui/ConversationFilesScreen.kt
user: login: ohassine
body: We don't want to show it there, only in conversation files
created_at: 2025-04-29T11:20:21Z
author_association: MEMBER

PR comments:
user: login: codecov[bot]
created_at: 2025-04-24T13:25:32Z
body: ## [Codecov](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp) Report
Attention: Patch coverage is `46.15385%` with `7 lines` in your changes missing coverage. Please review.
> Project coverage is 46.04%. Comparing base [(`dd82370`)](https://app.codecov.io/gh/wireapp/wire-android/commit/dd82370b8bdba091f462da1c085d78df06b239bf?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp) to head [(`e5601fd`)](https://app.codecov.io/gh/wireapp/wire-android/commit/e5601fddd56b296d36cbd61d9682bd7319a70118?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp).
> Report is 1 commits behind head on develop.

| [Files with missing lines](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp) | Patch % | Lines |
|---|---|---|
| [...c/main/kotlin/com/wire/android/util/StringUtils.kt](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?src=pr&el=tree&filepath=core%2Fui-common%2Fsrc%2Fmain%2Fkotlin%2Fcom%2Fwire%2Fandroid%2Futil%2FStringUtils.kt&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp#diff-Y29yZS91aS1jb21tb24vc3JjL21haW4va290bGluL2NvbS93aXJlL2FuZHJvaWQvdXRpbC9TdHJpbmdVdGlscy5rdA==) | 46.15% | [4 Missing and 3 partials :warning: ](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp) |

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff            @@
##           develop    #4002   +/-   ##
========================================
  Coverage    46.04%   46.04%           
========================================
  Files          518      519    +1     
  Lines        18081    18081           
  Branches      3037     3037           
========================================
  Hits          8326     8326           
  Misses        8891     8891           
  Partials       864      864           
```

| [Files with missing lines](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp) | Coverage Δ | |
|---|---|---|
| [...rc/main/kotlin/com/wire/android/util/StringUtil.kt](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?src=pr&el=tree&filepath=app%2Fsrc%2Fmain%2Fkotlin%2Fcom%2Fwire%2Fandroid%2Futil%2FStringUtil.kt&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp#diff-YXBwL3NyYy9tYWluL2tvdGxpbi9jb20vd2lyZS9hbmRyb2lkL3V0aWwvU3RyaW5nVXRpbC5rdA==) | `100.00% <ø> (+50.00%)` | :arrow_up: |
| [...c/main/kotlin/com/wire/android/util/StringUtils.kt](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?src=pr&el=tree&filepath=core%2Fui-common%2Fsrc%2Fmain%2Fkotlin%2Fcom%2Fwire%2Fandroid%2Futil%2FStringUtils.kt&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp#diff-Y29yZS91aS1jb21tb24vc3JjL21haW4va290bGluL2NvbS93aXJlL2FuZHJvaWQvdXRpbC9TdHJpbmdVdGlscy5rdA==) | `46.15% <46.15%> (ø)` | |

------

[Continue to review full report in Codecov by Sentry](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?dropdown=coverage&src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp). Last update [dd82370...e5601fd](https://app.codecov.io/gh/wireapp/wire-android/pull/4002?dropdown=coverage&src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=wireapp).

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-24T14:01:36Z
body: Built [wire-android-staging-compat-pr-4002.apk]() is available for download
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-24T14:03:16Z
body: Built [wire-android-dev-debug-pr-4002.apk]() is available for download
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-24T15:47:52Z
body: Built [wire-android-staging-compat-pr-4002.apk]() is available for download
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-24T15:48:14Z
body: Built [wire-android-dev-debug-pr-4002.apk]() is available for download
author_association: CONTRIBUTOR
user: login: sonarqubecloud[bot]
created_at: 2025-04-29T11:26:56Z
body: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=wireapp_wire-android&pullRequest=4002) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [8 New issues](https://sonarcloud.io/project/issues?id=wireapp_wire-android&pullRequest=4002&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=wireapp_wire-android&pullRequest=4002&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=wireapp_wire-android&pullRequest=4002&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=wireapp_wire-android&pullRequest=4002&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=wireapp_wire-android&pullRequest=4002&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=wireapp_wire-android&pullRequest=4002)


author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-29T11:58:38Z
body: Built [wire-android-staging-compat-pr-4002.apk]() is available for download
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-29T11:58:59Z
body: Built [wire-android-dev-debug-pr-4002.apk]() is available for download
author_association: CONTRIBUTOR