88package com.nextcloud.client.assistant.translate
99
1010import androidx.activity.compose.BackHandler
11+ import androidx.compose.animation.core.RepeatMode
12+ import androidx.compose.animation.core.animateFloat
13+ import androidx.compose.animation.core.infiniteRepeatable
14+ import androidx.compose.animation.core.rememberInfiniteTransition
15+ import androidx.compose.animation.core.tween
1116import androidx.compose.foundation.clickable
17+ import androidx.compose.foundation.layout.Column
1218import androidx.compose.foundation.layout.Row
1319import androidx.compose.foundation.layout.Spacer
1420import androidx.compose.foundation.layout.fillMaxSize
@@ -32,6 +38,7 @@ import androidx.compose.material3.TextField
3238import androidx.compose.material3.TextFieldDefaults
3339import androidx.compose.runtime.Composable
3440import androidx.compose.runtime.DisposableEffect
41+ import androidx.compose.runtime.collectAsState
3542import androidx.compose.runtime.getValue
3643import androidx.compose.runtime.mutableStateOf
3744import androidx.compose.runtime.remember
@@ -56,9 +63,14 @@ import com.owncloud.android.utils.ClipboardUtil
5663@Suppress(" LongMethod" )
5764@OptIn(ExperimentalMaterial3Api ::class )
5865@Composable
59- fun TranslationScreen (selectedTaskType : TaskTypeData ? , viewModel : AssistantViewModel , textToTranslate : String ) {
66+ fun TranslationScreen (
67+ selectedTaskType : TaskTypeData ? ,
68+ viewModel : AssistantViewModel ,
69+ textToTranslate : String ,
70+ isTaskExists : Boolean
71+ ) {
6072 val languages = remember(selectedTaskType) { selectedTaskType?.toTranslationLanguages() }
61-
73+ val isTranslationTaskCreated by viewModel.isTranslationTaskCreated.collectAsState()
6274 var sourceState by remember {
6375 mutableStateOf(
6476 TranslationSideState (
@@ -73,16 +85,14 @@ fun TranslationScreen(selectedTaskType: TaskTypeData?, viewModel: AssistantViewM
7385 }
7486
7587 BackHandler {
76- viewModel.updateTranslationTaskState(false )
77- viewModel.selectTask(null )
88+ viewModel.onTranslationScreenDismissed()
7889 viewModel.updateScreenState(AssistantScreenState .TaskContent )
7990 }
8091
8192 // task is unselected
8293 DisposableEffect (Unit ) {
8394 onDispose {
84- viewModel.updateTranslationTaskState(false )
85- viewModel.selectTask(null )
95+ viewModel.onTranslationScreenDismissed()
8696 }
8797 }
8898
@@ -111,6 +121,7 @@ fun TranslationScreen(selectedTaskType: TaskTypeData?, viewModel: AssistantViewM
111121 state = sourceState,
112122 availableLanguages = languages?.originLanguages ? : emptyList(),
113123 maxDp = 120 .dp,
124+ shimmer = false ,
114125 onStateChange = { sourceState = it }
115126 )
116127 }
@@ -126,25 +137,31 @@ fun TranslationScreen(selectedTaskType: TaskTypeData?, viewModel: AssistantViewM
126137 item {
127138 TranslationSection (
128139 labelId = R .string.translation_screen_label_to,
129- hintId = R .string.translation_screen_hint_target,
140+ hintId = if (isTaskExists) {
141+ R .string.translation_screen_translating
142+ } else {
143+ R .string.translation_screen_start_to_translate_task
144+ },
130145 state = targetState,
131146 availableLanguages = languages?.targetLanguages ? : emptyList(),
132147 maxDp = Dp .Unspecified ,
148+ shimmer = isTaskExists || isTranslationTaskCreated,
133149 onStateChange = { targetState = it }
134150 )
135151 }
136152 }
137153 }
138154}
139155
140- @Suppress(" LongMethod" )
156+ @Suppress(" LongMethod" , " LongParameterList " )
141157@Composable
142158private fun TranslationSection (
143159 labelId : Int ,
144160 hintId : Int ,
145161 state : TranslationSideState ,
146162 availableLanguages : List <TranslationLanguage >,
147163 maxDp : Dp ,
164+ shimmer : Boolean ,
148165 onStateChange : (TranslationSideState ) -> Unit
149166) {
150167 val activity = LocalContext .current.getActivity()
@@ -199,23 +216,56 @@ private fun TranslationSection(
199216 }
200217 }
201218
202- TextField (
203- value = state.text,
204- onValueChange = { onStateChange(state.copy(text = it)) },
205- readOnly = state.isTarget,
206- modifier = Modifier
207- .fillMaxWidth()
208- .heightIn(min = 120 .dp, max = maxDp),
209- placeholder = {
210- Text (text = stringResource(hintId), style = MaterialTheme .typography.headlineSmall)
211- },
212- textStyle = MaterialTheme .typography.headlineSmall,
213- colors = TextFieldDefaults .colors(
214- focusedContainerColor = Color .Transparent ,
215- unfocusedContainerColor = Color .Transparent ,
216- disabledContainerColor = Color .Transparent ,
217- focusedIndicatorColor = Color .Transparent ,
218- unfocusedIndicatorColor = Color .Transparent
219+ if (state.isTarget && shimmer) {
220+ TranslatingShimmer (
221+ modifier = Modifier
222+ .fillMaxWidth()
223+ .heightIn(min = 120 .dp)
224+ .padding(horizontal = 16 .dp)
225+ )
226+ } else {
227+ TextField (
228+ value = state.text,
229+ onValueChange = { onStateChange(state.copy(text = it)) },
230+ readOnly = state.isTarget,
231+ modifier = Modifier
232+ .fillMaxWidth()
233+ .heightIn(min = 120 .dp, max = maxDp),
234+ placeholder = {
235+ Text (text = stringResource(hintId), style = MaterialTheme .typography.headlineSmall)
236+ },
237+ textStyle = MaterialTheme .typography.headlineSmall,
238+ colors = TextFieldDefaults .colors(
239+ focusedContainerColor = Color .Transparent ,
240+ unfocusedContainerColor = Color .Transparent ,
241+ disabledContainerColor = Color .Transparent ,
242+ focusedIndicatorColor = Color .Transparent ,
243+ unfocusedIndicatorColor = Color .Transparent
244+ )
219245 )
246+ }
247+ }
248+
249+ @Suppress(" MagicNumber" )
250+ @Composable
251+ private fun TranslatingShimmer (modifier : Modifier = Modifier ) {
252+ val transition = rememberInfiniteTransition(label = " shimmer" )
253+ val alpha by transition.animateFloat(
254+ initialValue = 0.3f ,
255+ targetValue = 1f ,
256+ animationSpec = infiniteRepeatable(
257+ animation = tween(900 ),
258+ repeatMode = RepeatMode .Reverse
259+ ),
260+ label = " alpha"
220261 )
262+
263+ Column (modifier = modifier) {
264+ Text (
265+ text = stringResource(R .string.translation_screen_translating),
266+ style = MaterialTheme .typography.headlineSmall,
267+ color = MaterialTheme .colorScheme.onSurface.copy(alpha = alpha),
268+ modifier = Modifier .padding(vertical = 4 .dp)
269+ )
270+ }
221271}
0 commit comments