Skip to content

Commit bae8796

Browse files
Merge pull request #113 from Naoki-Hidaka/replace-stateflow
Replace stateflow
2 parents 2f46b48 + 14c5a15 commit bae8796

16 files changed

Lines changed: 433 additions & 186 deletions

File tree

.idea/deploymentTargetDropDown.xml

Lines changed: 0 additions & 17 deletions
This file was deleted.

.idea/misc.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ buildscript {
66
}
77
dependencies {
88
val kotlinVersion = "1.5.10"
9-
9+
1010
classpath("com.android.tools.build:gradle:7.1.2")
1111
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
1212
classpath("com.google.dagger:hilt-android-gradle-plugin:2.40.1")

data/entity/src/main/java/jp/dosukoi/data/entity/search/SearchPageState.kt

Lines changed: 0 additions & 9 deletions
This file was deleted.

testing/src/main/java/jp/dosukoi/testing/common/MainCoroutineRule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class MainCoroutineRule(
2525

2626
override fun finished(description: Description?) {
2727
super.finished(description)
28-
testDispatcher.advanceUntilIdle()
28+
testDispatcher.scheduler.advanceUntilIdle()
2929
Dispatchers.resetMain()
3030
testDispatcher.cleanupTestCoroutines()
3131
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package jp.dosukoi.ui.view.common
2+
3+
import androidx.compose.foundation.lazy.LazyListState
4+
import androidx.compose.runtime.Composable
5+
import androidx.compose.runtime.LaunchedEffect
6+
import androidx.compose.runtime.derivedStateOf
7+
import androidx.compose.runtime.getValue
8+
import androidx.compose.runtime.remember
9+
import androidx.compose.runtime.snapshotFlow
10+
import kotlinx.coroutines.flow.filter
11+
12+
@Composable
13+
fun OnScrollEnd(
14+
lazyListState: LazyListState,
15+
onAppearLastItem: () -> Unit
16+
) {
17+
val isReachedLast by remember(lazyListState) {
18+
derivedStateOf {
19+
lazyListState.layoutInfo.visibleItemsInfo.lastOrNull()?.index == lazyListState.layoutInfo.totalItemsCount - 1
20+
}
21+
}
22+
23+
LaunchedEffect(lazyListState) {
24+
snapshotFlow { isReachedLast }
25+
.filter { it }
26+
.collect {
27+
onAppearLastItem()
28+
}
29+
}
30+
}

ui/view/src/main/java/jp/dosukoi/ui/view/myPage/MyPageComponent.kt

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package jp.dosukoi.ui.view.myPage
22

33
import androidx.compose.foundation.Image
4+
import androidx.compose.foundation.background
45
import androidx.compose.foundation.clickable
6+
import androidx.compose.foundation.layout.Box
57
import androidx.compose.foundation.layout.Column
68
import androidx.compose.foundation.layout.PaddingValues
79
import androidx.compose.foundation.layout.Row
@@ -19,8 +21,11 @@ import androidx.compose.runtime.Composable
1921
import androidx.compose.ui.Alignment
2022
import androidx.compose.ui.Modifier
2123
import androidx.compose.ui.draw.clip
24+
import androidx.compose.ui.graphics.Color
25+
import androidx.compose.ui.layout.ContentScale
2226
import androidx.compose.ui.text.TextStyle
2327
import androidx.compose.ui.text.font.FontWeight
28+
import androidx.compose.ui.tooling.preview.Preview
2429
import androidx.compose.ui.unit.dp
2530
import androidx.compose.ui.unit.sp
2631
import coil.compose.rememberImagePainter
@@ -67,25 +72,34 @@ fun UserInfoCard(user: User, onCardClick: (String) -> Unit) {
6772
elevation = 4.dp
6873
) {
6974
Row(
70-
modifier = Modifier.fillMaxWidth(),
75+
modifier = Modifier
76+
.fillMaxWidth()
77+
.padding(all = 16.dp),
7178
verticalAlignment = Alignment.CenterVertically,
7279
) {
73-
// UserIcon(user.avatarUrl)
80+
UserIcon(user.avatarUrl)
7481
UserInfo(user)
7582
}
7683
}
7784
}
7885

7986
@Composable
8087
fun UserIcon(imageUrl: String) {
81-
Image(
82-
painter = rememberImagePainter(data = imageUrl),
83-
contentDescription = null,
84-
modifier = Modifier
85-
.size(125.dp)
86-
.padding(top = 16.dp, start = 16.dp, bottom = 16.dp)
87-
.clip(CircleShape),
88-
)
88+
Box(
89+
modifier =
90+
Modifier
91+
.size(120.dp)
92+
.background(color = Color.White, shape = CircleShape)
93+
.clip(CircleShape)
94+
95+
) {
96+
Image(
97+
painter = rememberImagePainter(data = imageUrl),
98+
contentDescription = null,
99+
modifier = Modifier.fillMaxWidth(),
100+
contentScale = ContentScale.FillWidth
101+
)
102+
}
89103
}
90104

91105
@Composable
@@ -131,3 +145,23 @@ fun RepositoryItem(
131145
if (!isLastItem) Divider(color = whiteGray)
132146
}
133147
}
148+
149+
//region Preview
150+
@Preview
151+
@Composable
152+
private fun UserInfoCardPreview() {
153+
UserInfoCard(
154+
user = User(
155+
"Dosukoi",
156+
0L,
157+
"https://placehold.jp/150x150.png",
158+
"",
159+
"",
160+
null,
161+
null,
162+
null
163+
),
164+
onCardClick = {}
165+
)
166+
}
167+
//endregion
Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package jp.dosukoi.ui.view.myPage
22

33
import androidx.compose.runtime.Composable
4+
import androidx.compose.runtime.collectAsState
45
import androidx.compose.runtime.getValue
5-
import androidx.compose.runtime.livedata.observeAsState
66
import jp.dosukoi.data.entity.myPage.UserStatus
77
import jp.dosukoi.ui.view.common.LoadingAndErrorScreen
88
import jp.dosukoi.ui.viewmodel.myPage.MyPageViewModel
@@ -11,26 +11,24 @@ import jp.dosukoi.ui.viewmodel.myPage.MyPageViewModel
1111
fun MyPageScreen(
1212
viewModel: MyPageViewModel,
1313
) {
14-
val myPageState by viewModel.myPageState.observeAsState()
15-
myPageState?.let {
16-
LoadingAndErrorScreen(
17-
state = it,
18-
loadedContent = { data ->
19-
when (val state = data.userStatus) {
20-
is UserStatus.Authenticated -> MyPageComponent(
21-
state.user,
22-
data.repositoryList,
23-
viewModel::onCardClick,
24-
viewModel::onRepositoryItemClick,
25-
data.isRefreshing,
26-
viewModel::onRefresh
27-
)
28-
UserStatus.UnAuthenticated -> UnAuthenticatedUserComponent(
29-
viewModel::onLoginButtonClick
30-
)
31-
}
32-
},
33-
onRetryClick = viewModel::onRetryClick
34-
)
35-
}
14+
val myPageUiState by viewModel.myPageState.collectAsState()
15+
LoadingAndErrorScreen(
16+
state = myPageUiState,
17+
loadedContent = { data ->
18+
when (val state = data.userStatus) {
19+
is UserStatus.Authenticated -> MyPageComponent(
20+
state.user,
21+
data.repositoryList,
22+
viewModel::onCardClick,
23+
viewModel::onRepositoryItemClick,
24+
data.isRefreshing,
25+
viewModel::onRefresh
26+
)
27+
UserStatus.UnAuthenticated -> UnAuthenticatedUserComponent(
28+
viewModel::onLoginButtonClick
29+
)
30+
}
31+
},
32+
onRetryClick = viewModel::onRetryClick
33+
)
3634
}

ui/view/src/main/java/jp/dosukoi/ui/view/search/SearchComponent.kt

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
package jp.dosukoi.ui.view.search
22

3-
import androidx.compose.foundation.layout.*
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.PaddingValues
6+
import androidx.compose.foundation.layout.fillMaxSize
7+
import androidx.compose.foundation.layout.fillMaxWidth
8+
import androidx.compose.foundation.layout.padding
49
import androidx.compose.foundation.lazy.LazyColumn
510
import androidx.compose.foundation.lazy.LazyListState
611
import androidx.compose.foundation.lazy.itemsIndexed
712
import androidx.compose.foundation.text.KeyboardActions
813
import androidx.compose.foundation.text.KeyboardOptions
9-
import androidx.compose.material.*
14+
import androidx.compose.material.CircularProgressIndicator
15+
import androidx.compose.material.Icon
16+
import androidx.compose.material.IconButton
17+
import androidx.compose.material.Text
18+
import androidx.compose.material.TextField
19+
import androidx.compose.material.TextFieldDefaults
1020
import androidx.compose.material.icons.Icons
1121
import androidx.compose.material.icons.filled.Search
1222
import androidx.compose.runtime.Composable
@@ -18,18 +28,16 @@ import androidx.compose.ui.text.style.TextAlign
1828
import androidx.compose.ui.tooling.preview.Preview
1929
import androidx.compose.ui.unit.dp
2030
import jp.dosukoi.data.entity.myPage.Repository
21-
import jp.dosukoi.data.entity.search.SearchPageState
2231
import jp.dosukoi.ui.view.common.LoadingAndErrorScreen
2332
import jp.dosukoi.ui.view.common.black
2433
import jp.dosukoi.ui.view.common.white
2534
import jp.dosukoi.ui.view.myPage.RepositoryItem
26-
import jp.dosukoi.ui.viewmodel.common.LoadState
35+
import jp.dosukoi.ui.viewmodel.search.SearchState
36+
import jp.dosukoi.ui.viewmodel.search.SearchUiState
2737

2838
@Composable
2939
fun SearchComponent(
30-
searchPageState: LoadState<SearchPageState>?,
31-
searchText: String?,
32-
hasMore: Boolean?,
40+
uiState: SearchUiState,
3341
isTextError: Boolean?,
3442
listState: LazyListState,
3543
onValueChanged: (String) -> Unit,
@@ -42,14 +50,13 @@ fun SearchComponent(
4250
.fillMaxSize()
4351
) {
4452
SearchTextField(
45-
searchText = searchText ?: "",
53+
searchText = uiState.searchWord,
4654
isTextError = isTextError,
4755
onValueChanged = onValueChanged,
4856
onSearchButtonClick = onSearchButtonClick
4957
)
5058
SearchList(
51-
searchPageState = searchPageState,
52-
hasMore = hasMore,
59+
uiState = uiState,
5360
listState = listState,
5461
onRetryClick = onRetryClick,
5562
onItemClick = onItemClick
@@ -105,37 +112,34 @@ fun SearchTextField(
105112

106113
@Composable
107114
fun SearchList(
108-
searchPageState: LoadState<SearchPageState>?,
109-
hasMore: Boolean?,
115+
uiState: SearchUiState,
110116
listState: LazyListState,
111117
onRetryClick: () -> Unit,
112118
onItemClick: (String) -> Unit,
113119
) {
114-
searchPageState?.let {
115-
LoadingAndErrorScreen(
116-
state = it,
117-
loadedContent = {
118-
when (it) {
119-
SearchPageState.Initialized -> SearchInitialComponent()
120-
SearchPageState.Empty -> SearchedEmptyComponent()
121-
is SearchPageState.Data ->
122-
SearchedListComponent(
123-
it.repositoryList,
124-
hasMore,
125-
listState,
126-
onItemClick
127-
)
128-
}
129-
},
130-
onRetryClick = onRetryClick
131-
)
132-
}
120+
LoadingAndErrorScreen(
121+
state = uiState.searchState,
122+
loadedContent = {
123+
when (it) {
124+
SearchState.Initialized -> SearchInitialComponent()
125+
SearchState.Empty -> SearchedEmptyComponent()
126+
is SearchState.Data ->
127+
SearchedListComponent(
128+
it.repositoryList,
129+
it.hasMore,
130+
listState,
131+
onItemClick
132+
)
133+
}
134+
},
135+
onRetryClick = onRetryClick
136+
)
133137
}
134138

135139
@Composable
136140
fun SearchedListComponent(
137141
repositoryList: List<Repository>,
138-
hasMore: Boolean?,
142+
hasMore: Boolean,
139143
listState: LazyListState,
140144
onItemClick: (String) -> Unit
141145
) {
@@ -146,11 +150,11 @@ fun SearchedListComponent(
146150
itemsIndexed(repositoryList) { index, repository ->
147151
RepositoryItem(
148152
repository = repository,
149-
isLastItem = index == repositoryList.size && hasMore == false,
153+
isLastItem = index == repositoryList.size && !hasMore,
150154
onRepositoryItemClick = onItemClick
151155
)
152156
}
153-
if (hasMore == true) item { LoadingFooter() }
157+
if (hasMore) item { LoadingFooter() }
154158
}
155159
}
156160

0 commit comments

Comments
 (0)