Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit318f3a4

Browse files
authored
feat: add new conversation folder [WPB-14628] (#3805)
1 parent24d57f9 commit318f3a4

File tree

6 files changed

+535
-11
lines changed

6 files changed

+535
-11
lines changed

‎app/src/main/kotlin/com/wire/android/di/accountScoped/ConversationModule.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,4 +352,9 @@ class ConversationModule {
352352
@Provides
353353
funprovideRemoveConversationFromFolderUseCase(conversationScope:ConversationScope)=
354354
conversationScope.removeConversationFromFolder
355+
356+
@ViewModelScoped
357+
@Provides
358+
funprovideCreateConversationFolderUseCase(conversationScope:ConversationScope)=
359+
conversationScope.createConversationFolder
355360
}

‎app/src/main/kotlin/com/wire/android/ui/home/conversations/folder/ConversationFoldersScreen.kt

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
*/
1818
packagecom.wire.android.ui.home.conversations.folder
1919

20-
importandroid.widget.Toast
2120
importandroidx.compose.foundation.background
2221
importandroidx.compose.foundation.layout.Box
2322
importandroidx.compose.foundation.layout.Column
@@ -37,9 +36,12 @@ import androidx.compose.ui.platform.LocalContext
3736
importandroidx.compose.ui.res.stringResource
3837
importandroidx.hilt.navigation.compose.hiltViewModel
3938
importcom.ramcosta.composedestinations.annotation.RootNavGraph
39+
importcom.ramcosta.composedestinations.result.NavResult
4040
importcom.ramcosta.composedestinations.result.ResultBackNavigator
41+
importcom.ramcosta.composedestinations.result.ResultRecipient
4142
importcom.wire.android.R
4243
importcom.wire.android.model.Clickable
44+
importcom.wire.android.navigation.NavigationCommand
4345
importcom.wire.android.navigation.Navigator
4446
importcom.wire.android.navigation.WireDestination
4547
importcom.wire.android.navigation.style.PopUpNavigationAnimation
@@ -55,6 +57,7 @@ import com.wire.android.ui.common.spacers.VerticalSpace
5557
importcom.wire.android.ui.common.topappbar.NavigationIconType
5658
importcom.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar
5759
importcom.wire.android.ui.common.typography
60+
importcom.wire.android.ui.destinations.NewConversationFolderScreenDestination
5861
importcom.wire.kalium.logic.data.conversation.ConversationFolder
5962

6063
@RootNavGraph
@@ -67,6 +70,7 @@ fun ConversationFoldersScreen(
6770
args:ConversationFoldersNavArgs,
6871
navigator:Navigator,
6972
resultNavigator:ResultBackNavigator<ConversationFoldersNavBackArgs>,
73+
resultRecipient:ResultRecipient<NewConversationFolderScreenDestination,String>,
7074
foldersViewModel:ConversationFoldersVM =
7175
hiltViewModel<ConversationFoldersVMImpl,ConversationFoldersVMImpl.Factory>(
7276
creationCallback = { it.create(ConversationFoldersStateArgs(args.currentFolderId)) }
@@ -92,8 +96,18 @@ fun ConversationFoldersScreen(
9296
foldersState= foldersViewModel.state(),
9397
onNavigationPressed= { navigator.navigateBack() },
9498
moveConversationToFolder= moveToFolderVM::moveConversationToFolder,
95-
onFolderSelected= foldersViewModel::onFolderSelected
99+
onFolderSelected= foldersViewModel::onFolderSelected,
100+
onCreateFolderPressed= { navigator.navigate(NavigationCommand(NewConversationFolderScreenDestination())) }
96101
)
102+
103+
resultRecipient.onNavResult {
104+
when (it) {
105+
NavResult.Canceled-> {}
106+
isNavResult.Value-> {
107+
foldersViewModel.onFolderSelected(it.value)
108+
}
109+
}
110+
}
97111
}
98112

99113
@Composable
@@ -103,9 +117,8 @@ private fun Content(
103117
onNavigationPressed: ()->Unit = {},
104118
moveConversationToFolder: (folder:ConversationFolder)->Unit = {},
105119
onFolderSelected: (folderId:String)->Unit = {},
120+
onCreateFolderPressed: ()->Unit = {}
106121
) {
107-
val context=LocalContext.current
108-
109122
val lazyListState= rememberLazyListState()
110123
WireScaffold(
111124
modifier=Modifier
@@ -124,13 +137,7 @@ private fun Content(
124137
WireSecondaryButton(
125138
state=WireButtonState.Default,
126139
text= stringResource(id=R.string.label_new_folder),
127-
onClick= {
128-
Toast.makeText(
129-
context,
130-
"Not implemented yet",
131-
Toast.LENGTH_SHORT
132-
).show()
133-
}
140+
onClick= onCreateFolderPressed
134141
)
135142
VerticalSpace.x8()
136143
val state=if (foldersState.selectedFolderId!=null
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* Wire
3+
* Copyright (C) 2025 Wire Swiss GmbH
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see http://www.gnu.org/licenses/.
17+
*/
18+
packagecom.wire.android.ui.home.conversations.folder
19+
20+
importandroidx.compose.foundation.layout.Box
21+
importandroidx.compose.foundation.layout.Column
22+
importandroidx.compose.foundation.layout.fillMaxSize
23+
importandroidx.compose.foundation.layout.fillMaxWidth
24+
importandroidx.compose.foundation.layout.padding
25+
importandroidx.compose.foundation.rememberScrollState
26+
importandroidx.compose.foundation.text.KeyboardOptions
27+
importandroidx.compose.foundation.text.input.InputTransformation
28+
importandroidx.compose.foundation.text.input.TextFieldLineLimits
29+
importandroidx.compose.foundation.text.input.TextFieldState
30+
importandroidx.compose.material3.MaterialTheme
31+
importandroidx.compose.material3.Surface
32+
importandroidx.compose.runtime.Composable
33+
importandroidx.compose.runtime.LaunchedEffect
34+
importandroidx.compose.ui.Alignment
35+
importandroidx.compose.ui.Modifier
36+
importandroidx.compose.ui.platform.LocalSoftwareKeyboardController
37+
importandroidx.compose.ui.res.stringResource
38+
importandroidx.hilt.navigation.compose.hiltViewModel
39+
importcom.ramcosta.composedestinations.annotation.RootNavGraph
40+
importcom.ramcosta.composedestinations.result.ResultBackNavigator
41+
importcom.wire.android.R
42+
importcom.wire.android.navigation.Navigator
43+
importcom.wire.android.navigation.WireDestination
44+
importcom.wire.android.ui.common.ShakeAnimation
45+
importcom.wire.android.ui.common.button.WireButtonState.Default
46+
importcom.wire.android.ui.common.button.WireButtonState.Disabled
47+
importcom.wire.android.ui.common.button.WirePrimaryButton
48+
importcom.wire.android.ui.common.rememberBottomBarElevationState
49+
importcom.wire.android.ui.common.rememberTopBarElevationState
50+
importcom.wire.android.ui.common.scaffold.WireScaffold
51+
importcom.wire.android.ui.common.textfield.DefaultText
52+
importcom.wire.android.ui.common.textfield.WireTextField
53+
importcom.wire.android.ui.common.textfield.WireTextFieldState
54+
importcom.wire.android.ui.common.textfield.maxLengthWithCallback
55+
importcom.wire.android.ui.common.topappbar.NavigationIconType
56+
importcom.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar
57+
importcom.wire.android.ui.home.settings.account.displayname.ChangeDisplayNameViewModel.Companion.NAME_MAX_COUNT
58+
importcom.wire.android.ui.theme.WireTheme
59+
importcom.wire.android.ui.theme.wireColorScheme
60+
importcom.wire.android.ui.theme.wireDimensions
61+
importcom.wire.android.util.ui.PreviewMultipleThemes
62+
importcom.wire.android.util.ui.SnackBarMessageHandler
63+
64+
@RootNavGraph
65+
@WireDestination
66+
@Composable
67+
funNewConversationFolderScreen(
68+
navigator:Navigator,
69+
resultNavigator:ResultBackNavigator<String>,
70+
viewModel:NewFolderViewModel = hiltViewModel()
71+
) {
72+
73+
LaunchedEffect(viewModel.folderNameState.folderId) {
74+
if (viewModel.folderNameState.folderId!=null) {
75+
resultNavigator.navigateBack(viewModel.folderNameState.folderId!!)
76+
}
77+
}
78+
79+
Content(
80+
textState= viewModel.textState,
81+
state= viewModel.folderNameState,
82+
onContinuePressed= {
83+
viewModel.createFolder(viewModel.textState.text.toString())
84+
},
85+
onBackPressed= navigator::navigateBack
86+
)
87+
88+
SnackBarMessageHandler(viewModel.infoMessage)
89+
}
90+
91+
@Composable
92+
privatefunContent(
93+
textState:TextFieldState,
94+
state:FolderNameState,
95+
onContinuePressed: ()->Unit,
96+
onBackPressed: ()->Unit,
97+
modifier:Modifier =Modifier
98+
) {
99+
val scrollState= rememberScrollState()
100+
with(state) {
101+
WireScaffold(
102+
modifier= modifier,
103+
topBar= {
104+
WireCenterAlignedTopAppBar(
105+
elevation= scrollState.rememberTopBarElevationState().value,
106+
onNavigationPressed= onBackPressed,
107+
navigationIconType=NavigationIconType.Back(),
108+
title= stringResource(id=R.string.label_new_folder)
109+
)
110+
}
111+
) { internalPadding->
112+
Column(
113+
modifier=Modifier
114+
.padding(internalPadding)
115+
.fillMaxSize()
116+
) {
117+
val keyboardController=LocalSoftwareKeyboardController.current
118+
119+
Box(
120+
modifier=Modifier
121+
.weight(weight=1f, fill=true)
122+
.fillMaxWidth()
123+
) {
124+
ShakeAnimation(modifier=Modifier.align(Alignment.Center)) { animate->
125+
WireTextField(
126+
textState= textState,
127+
labelText= stringResource(R.string.new_folder_folder_name).uppercase(),
128+
inputTransformation=InputTransformation.maxLengthWithCallback(NAME_MAX_COUNT, animate),
129+
lineLimits=TextFieldLineLimits.SingleLine,
130+
state= computeNameErrorState(error),
131+
keyboardOptions=KeyboardOptions.DefaultText,
132+
descriptionText= stringResource(id=R.string.settings_myaccount_display_name_exceeded_limit_error),
133+
onKeyboardAction= { keyboardController?.hide() },
134+
modifier=Modifier.padding(
135+
horizontal=MaterialTheme.wireDimensions.spacing16x
136+
)
137+
)
138+
}
139+
}
140+
141+
Surface(
142+
shadowElevation= scrollState.rememberBottomBarElevationState().value,
143+
color=MaterialTheme.wireColorScheme.background
144+
) {
145+
Box(modifier=Modifier.padding(MaterialTheme.wireDimensions.spacing16x)) {
146+
WirePrimaryButton(
147+
text= stringResource(R.string.new_folder_create_folder),
148+
onClick= onContinuePressed,
149+
fillMaxWidth=true,
150+
state=if (buttonEnabled)DefaultelseDisabled,
151+
loading= loading,
152+
modifier=Modifier.fillMaxWidth()
153+
)
154+
}
155+
}
156+
}
157+
}
158+
}
159+
}
160+
161+
@Composable
162+
privatefuncomputeNameErrorState(error:FolderNameState.NameError)=
163+
if (errorisFolderNameState.NameError.TextFieldError) {
164+
when (error) {
165+
FolderNameState.NameError.TextFieldError.NameEmptyError->WireTextFieldState.Error(
166+
stringResource(id=R.string.new_folder_error_name_empty)
167+
)
168+
169+
FolderNameState.NameError.TextFieldError.NameExceedLimitError->WireTextFieldState.Error(
170+
stringResource(id=R.string.new_folder_error_name_exceeded_limit_error)
171+
)
172+
173+
FolderNameState.NameError.TextFieldError.NameAlreadyExistError->WireTextFieldState.Error(
174+
stringResource(id=R.string.new_folder_error_name_exist)
175+
)
176+
}
177+
}else {
178+
WireTextFieldState.Default
179+
}
180+
181+
@PreviewMultipleThemes
182+
@Composable
183+
funPreviewNewConversationFolder()=WireTheme {
184+
Content(TextFieldState("Secret group"),FolderNameState(), {}, {})
185+
}
186+
187+
@PreviewMultipleThemes
188+
@Composable
189+
funPreviewNewConversationFolderErrorNameExist()=WireTheme {
190+
Content(
191+
TextFieldState("Secret group"),
192+
FolderNameState(error=FolderNameState.NameError.TextFieldError.NameAlreadyExistError),
193+
{},
194+
{}
195+
)
196+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp