2
2
3
3
package com.kip.reykunyu.ui.screens
4
4
5
- import android.util.Log
6
5
import androidx.compose.animation.AnimatedContent
7
6
import androidx.compose.animation.Crossfade
8
7
import androidx.compose.animation.ExperimentalAnimationApi
@@ -16,6 +15,7 @@ import androidx.compose.foundation.BorderStroke
16
15
import androidx.compose.foundation.ExperimentalFoundationApi
17
16
import androidx.compose.foundation.background
18
17
import androidx.compose.foundation.border
18
+ import androidx.compose.foundation.clickable
19
19
import androidx.compose.foundation.layout.Arrangement
20
20
import androidx.compose.foundation.layout.Box
21
21
import androidx.compose.foundation.layout.Column
@@ -38,7 +38,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
38
38
import androidx.compose.material.icons.Icons
39
39
import androidx.compose.material.icons.filled.Menu
40
40
import androidx.compose.material.icons.filled.Search
41
- import androidx.compose.material.icons.filled.Star
41
+ import androidx.compose.material.icons.filled.Warning
42
42
import androidx.compose.material.icons.rounded.Info
43
43
import androidx.compose.material.icons.rounded.Search
44
44
import androidx.compose.material3.Button
@@ -95,8 +95,12 @@ import androidx.lifecycle.viewmodel.compose.viewModel
95
95
import com.kip.reykunyu.R
96
96
import com.kip.reykunyu.data.dict.Language
97
97
import com.kip.reykunyu.data.dict.Navi
98
+ import com.kip.reykunyu.data.dict.NaviSuggestion
98
99
import com.kip.reykunyu.data.dict.SearchMode
100
+ import com.kip.reykunyu.data.dict.SuggestionsResult
101
+ import com.kip.reykunyu.data.dict.SuggestionsStatus
99
102
import com.kip.reykunyu.ui.components.NaviCard
103
+ import com.kip.reykunyu.ui.components.WordTypeCard
100
104
import com.kip.reykunyu.viewmodels.DictionarySearchViewModel
101
105
import com.kip.reykunyu.viewmodels.OfflineDictState
102
106
import com.kip.reykunyu.viewmodels.OfflineDictionaryViewModel
@@ -119,28 +123,36 @@ fun DictionaryScreen(
119
123
val dictState = offlineDictViewModel.offlineDictState
120
124
val preferenceState = preferenceViewModel.preferenceState.collectAsState().value
121
125
126
+ val onQueryUpdate = { text: String ->
127
+ searchViewModel.updateSearchInput(text)
128
+ searchViewModel.updateSuggestions(preferenceState.searchLanguage)
129
+ }
122
130
val onSearch = {
123
131
focusManager.clearFocus()
124
132
searchViewModel.search(preferenceState.searchLanguage)
125
133
}
126
134
127
- Box (Modifier .fillMaxSize().semantics { isTraversalGroup = true })
135
+ Box (
136
+ Modifier
137
+ .fillMaxSize()
138
+ .semantics { isTraversalGroup = true })
128
139
{
129
140
DictionarySearchBar (
130
141
searchString = searchViewModel.searchInput,
131
142
enabled = (dictState == OfflineDictState .Loaded ),
132
- onInputChanged = {
133
- searchViewModel.updateSearchInput(it)
134
- searchViewModel.updateSuggestions(preferenceState.searchLanguage)
135
- },
143
+ onInputChanged = onQueryUpdate,
144
+ suggestions = searchViewModel.searchSuggestions,
136
145
focusManager = focusManager,
137
146
onSearch = onSearch,
147
+ onSuggestionSelect = {
148
+ onQueryUpdate(it)
149
+ onSearch()
150
+ },
138
151
modifier = Modifier
139
152
.align(Alignment .TopCenter )
140
153
.semantics { traversalIndex = - 1f }
141
154
.padding(top = 57 .dp)
142
155
.padding(horizontal = 50 .dp)
143
-
144
156
)
145
157
146
158
Scaffold (
@@ -208,8 +220,7 @@ fun DictionaryScreen(
208
220
toNavi = state.result.toNavi,
209
221
language = preferenceState.searchLanguage,
210
222
naviAction = {
211
- Log .i(" REYKUNYU" , " NAVI REF: $it " )
212
- searchViewModel.updateSearchInput(it)
223
+ onQueryUpdate(it)
213
224
onSearch()
214
225
}
215
226
)
@@ -406,10 +417,39 @@ fun DictionarySearchBar(
406
417
enabled : Boolean ,
407
418
onInputChanged : (String ) -> Unit ,
408
419
onSearch : () -> Unit ,
420
+ suggestions : SuggestionsResult ,
421
+ onSuggestionSelect : (String ) -> Unit ,
409
422
focusManager : FocusManager ,
410
423
modifier : Modifier = Modifier
411
424
) {
425
+ @Composable
426
+ fun SuggestionItem (suggestion : NaviSuggestion , onSuggestionSelect : (String ) -> Unit ){
427
+ ListItem (
428
+ headlineContent = { Text (suggestion.word) },
429
+ supportingContent = {
430
+ suggestion.explanation?.let {
431
+ Text (
432
+ text = it
433
+ )
434
+ }
435
+ },
436
+ leadingContent = {
437
+ suggestion.type?.let {
438
+ WordTypeCard (
439
+ typeDetails = suggestion.typeDetails(),
440
+ typeDisplay = it
441
+ )
442
+ }
443
+ },
444
+ modifier = Modifier .clickable{onSuggestionSelect(suggestion.word)}
445
+ )
446
+ }
447
+
412
448
var active by rememberSaveable { mutableStateOf(false ) }
449
+ val suggestionSelectAction = { text: String ->
450
+ onSuggestionSelect(text)
451
+ active = false
452
+ }
413
453
414
454
// Search bar
415
455
ProvideTextStyle (value = MaterialTheme .typography.titleMedium.copy(fontSize = 20 .sp)) {
@@ -448,19 +488,89 @@ fun DictionarySearchBar(
448
488
449
489
450
490
) {
451
- repeat(4 ) { idx ->
452
- val resultText = " Suggestion $idx "
453
- ListItem (
454
- headlineContent = { Text (resultText) },
455
- supportingContent = { Text (" Additional info" ) },
456
- leadingContent = { Icon (Icons .Filled .Star , contentDescription = null ) },
457
- modifier = Modifier
491
+ when (suggestions.status){
492
+ SuggestionsStatus .Standby -> {
493
+ Box (contentAlignment = Alignment .Center , modifier = Modifier
458
494
.fillMaxWidth()
459
- // .padding(horizontal = 16.dp, vertical = 4.dp)
460
- )
495
+ .padding(top = 100 .dp)){
496
+ Text (text = " No suggestions..." )
497
+ }
498
+ }
499
+ SuggestionsStatus .Loading -> {
500
+ Box (contentAlignment = Alignment .Center , modifier = Modifier
501
+ .fillMaxWidth()
502
+ .padding(top = 100 .dp)){
503
+ CircularProgressIndicator ()
504
+ }
505
+ }
506
+ SuggestionsStatus .Success -> {
507
+ if (suggestions.fromNavi.isNullOrEmpty() && suggestions.toNavi.isNullOrEmpty()){
508
+ Box (contentAlignment = Alignment .Center , modifier = Modifier
509
+ .fillMaxWidth()
510
+ .padding(top = 100 .dp)){
511
+ Text (text = " No suggestions..." )
512
+ }
513
+ }
514
+
515
+ val state: LazyListState = rememberLazyListState()
516
+ LazyColumn (
517
+ state = state,
518
+ modifier = Modifier .simpleVerticalScrollbar(state)
519
+ ) {
520
+ if (! suggestions.fromNavi.isNullOrEmpty()){
521
+ item{
522
+ Spacer (Modifier .padding(7 .dp))
523
+ Text (
524
+ text = " from Na'vi" ,
525
+ style = MaterialTheme .typography.labelLarge,
526
+ modifier = Modifier .padding(horizontal = 20 .dp)
527
+ )
528
+
529
+ }
530
+ for (suggestion in suggestions.fromNavi) {
531
+ item {
532
+ SuggestionItem (suggestion = suggestion, onSuggestionSelect = suggestionSelectAction)
533
+ }
534
+ }
535
+ }
536
+
537
+ if (! suggestions.toNavi.isNullOrEmpty()){
538
+ item{
539
+ Spacer (Modifier .padding(7 .dp))
540
+ Text (
541
+ text = " to Na'vi" ,
542
+ style = MaterialTheme .typography.labelLarge,
543
+ modifier = Modifier .padding(horizontal = 20 .dp)
544
+ )
545
+
546
+ }
547
+
548
+ for (suggestion in suggestions.toNavi) {
549
+ item {
550
+ SuggestionItem (suggestion = suggestion, onSuggestionSelect = suggestionSelectAction)
551
+ }
552
+ }
553
+
554
+
555
+ }
556
+
557
+ }
558
+
559
+
560
+ }
561
+ SuggestionsStatus .Error -> {
562
+ ListItem (
563
+ headlineContent = { Text (stringResource(id = R .string.error)) },
564
+ supportingContent = { Text (text = suggestions.info ? : " " )},
565
+ leadingContent = { Icon (Icons .Filled .Warning , contentDescription = null )}
566
+ )
567
+ }
461
568
}
462
569
570
+
463
571
}
572
+
573
+
464
574
}
465
575
466
576
// OutlinedTextField(
@@ -750,3 +860,5 @@ fun FancyIndicator(color: Color, modifier: Modifier = Modifier) {
750
860
.border(BorderStroke (2 .dp, color), RoundedCornerShape (5 .dp))
751
861
)
752
862
}
863
+
864
+
0 commit comments