Skip to content

Commit 2cd6dd2

Browse files
authored
Merge pull request #2151 from DimensionDev/feature/discover-account-list
add account menu in discover
2 parents 3338e53 + 86d5781 commit 2cd6dd2

3 files changed

Lines changed: 174 additions & 53 deletions

File tree

app/src/main/java/dev/dimension/flare/ui/component/SearchBar.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ internal fun SearchBar(
6161
state: SearchBarState,
6262
onSearch: (String) -> Unit,
6363
modifier: Modifier = Modifier,
64+
trailingIcon: @Composable (() -> Unit)? = null,
6465
) {
6566
val keyboardController = LocalSoftwareKeyboardController.current
6667
SearchContent(
@@ -81,6 +82,7 @@ internal fun SearchBar(
8182
state.deleteSearchHistory(it)
8283
},
8384
queryTextState = state.queryTextState,
85+
trailingIcon = trailingIcon,
8486
)
8587
}
8688

@@ -97,6 +99,7 @@ private fun SearchContent(
9799
onExpandedChange: (Boolean) -> Unit,
98100
onBack: () -> Unit,
99101
modifier: Modifier = Modifier,
102+
trailingIcon: @Composable (() -> Unit)? = null,
100103
) {
101104
androidx.compose.material3.SearchBar(
102105
inputField = {
@@ -125,6 +128,7 @@ private fun SearchContent(
125128
}
126129
}
127130
},
131+
trailingIcon = trailingIcon,
128132
)
129133
},
130134
modifier = modifier,

app/src/main/java/dev/dimension/flare/ui/screen/home/DiscoverScreen.kt

Lines changed: 85 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Arrangement
66
import androidx.compose.foundation.layout.Box
77
import androidx.compose.foundation.layout.ExperimentalLayoutApi
88
import androidx.compose.foundation.layout.FlowRow
9+
import androidx.compose.foundation.layout.Row
910
import androidx.compose.foundation.layout.fillMaxSize
1011
import androidx.compose.foundation.layout.fillMaxWidth
1112
import androidx.compose.foundation.layout.padding
@@ -14,15 +15,19 @@ import androidx.compose.foundation.lazy.LazyRow
1415
import androidx.compose.foundation.lazy.items
1516
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan
1617
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
18+
import androidx.compose.material3.DropdownMenuItem
1719
import androidx.compose.material3.FilterChip
20+
import androidx.compose.material3.IconButton
1821
import androidx.compose.material3.ListItem
1922
import androidx.compose.material3.ListItemDefaults
2023
import androidx.compose.material3.Text
2124
import androidx.compose.runtime.Composable
2225
import androidx.compose.runtime.LaunchedEffect
2326
import androidx.compose.runtime.getValue
27+
import androidx.compose.runtime.mutableStateOf
2428
import androidx.compose.runtime.remember
2529
import androidx.compose.runtime.rememberCoroutineScope
30+
import androidx.compose.runtime.setValue
2631
import androidx.compose.ui.Alignment
2732
import androidx.compose.ui.Modifier
2833
import androidx.compose.ui.graphics.Color
@@ -39,11 +44,13 @@ import dev.dimension.flare.model.AccountType
3944
import dev.dimension.flare.model.MicroBlogKey
4045
import dev.dimension.flare.ui.common.items
4146
import dev.dimension.flare.ui.component.AvatarComponent
47+
import dev.dimension.flare.ui.component.FlareDropdownMenu
4248
import dev.dimension.flare.ui.component.FlareScaffold
4349
import dev.dimension.flare.ui.component.RefreshContainer
4450
import dev.dimension.flare.ui.component.SearchBar
4551
import dev.dimension.flare.ui.component.SearchBarState
4652
import dev.dimension.flare.ui.component.placeholder
53+
import dev.dimension.flare.ui.component.platform.isBigScreen
4754
import dev.dimension.flare.ui.component.searchBarPresenter
4855
import dev.dimension.flare.ui.component.searchContent
4956
import dev.dimension.flare.ui.component.status.AdaptiveCard
@@ -56,6 +63,7 @@ import dev.dimension.flare.ui.presenter.home.DiscoverPresenter
5663
import dev.dimension.flare.ui.presenter.home.DiscoverState
5764
import dev.dimension.flare.ui.presenter.home.SearchPresenter
5865
import dev.dimension.flare.ui.presenter.invoke
66+
import dev.dimension.flare.ui.theme.screenHorizontalPadding
5967
import kotlinx.coroutines.launch
6068
import moe.tlaster.precompose.molecule.producePresenter
6169

@@ -64,6 +72,7 @@ import moe.tlaster.precompose.molecule.producePresenter
6472
internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) {
6573
val state by producePresenter("discover") { discoverPresenter() }
6674
val lazyListState = rememberLazyStaggeredGridState()
75+
val isBigScreen = isBigScreen()
6776
RegisterTabCallback(
6877
lazyListState = lazyListState,
6978
onRefresh = {
@@ -75,17 +84,64 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) {
7584
}
7685
FlareScaffold(
7786
topBar = {
78-
Box(
87+
Row(
7988
modifier =
8089
Modifier
81-
.fillMaxWidth(),
82-
contentAlignment = Alignment.Center,
90+
.fillMaxWidth()
91+
.padding(horizontal = screenHorizontalPadding),
92+
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally),
93+
verticalAlignment = Alignment.CenterVertically,
8394
) {
8495
SearchBar(
8596
state = state,
8697
onSearch = {
8798
state.commitSearch(it)
8899
},
100+
trailingIcon =
101+
state.selectedAccount?.let { account ->
102+
if (!isBigScreen) {
103+
{
104+
state.accounts.onSuccess { accounts ->
105+
var showMenu by remember { mutableStateOf(false) }
106+
IconButton(
107+
onClick = {
108+
if (accounts.size > 1) {
109+
showMenu = true
110+
}
111+
},
112+
) {
113+
AvatarComponent(
114+
data = account.avatar,
115+
)
116+
}
117+
FlareDropdownMenu(
118+
expanded = showMenu,
119+
onDismissRequest = { showMenu = false },
120+
) {
121+
accounts.forEach { profile ->
122+
DropdownMenuItem(
123+
text = {
124+
Text(profile.handle.canonical)
125+
},
126+
leadingIcon = {
127+
AvatarComponent(
128+
data = profile.avatar,
129+
size = 18.dp,
130+
)
131+
},
132+
onClick = {
133+
state.setAccount(profile)
134+
showMenu = false
135+
},
136+
)
137+
}
138+
}
139+
}
140+
}
141+
} else {
142+
null
143+
}
144+
},
89145
)
90146
}
91147
},
@@ -103,31 +159,33 @@ internal fun DiscoverScreen(onUserClick: (AccountType, MicroBlogKey) -> Unit) {
103159
contentPadding = contentPadding,
104160
forceCardMode = true,
105161
) {
106-
state.accounts.onSuccess { accounts ->
107-
if (accounts.size > 1) {
108-
item(
109-
span = StaggeredGridItemSpan.FullLine,
110-
) {
111-
LazyRow(
112-
horizontalArrangement = Arrangement.spacedBy(8.dp),
113-
modifier = Modifier.padding(bottom = 8.dp),
162+
if (isBigScreen) {
163+
state.accounts.onSuccess { accounts ->
164+
if (accounts.size > 1) {
165+
item(
166+
span = StaggeredGridItemSpan.FullLine,
114167
) {
115-
items(accounts) { profile ->
116-
FilterChip(
117-
selected = state.selectedAccount?.key == profile.key,
118-
onClick = {
119-
state.setAccount(profile)
120-
},
121-
label = {
122-
Text(profile.handle.canonical)
123-
},
124-
leadingIcon = {
125-
AvatarComponent(
126-
data = profile.avatar,
127-
size = 18.dp,
128-
)
129-
},
130-
)
168+
LazyRow(
169+
horizontalArrangement = Arrangement.spacedBy(8.dp),
170+
modifier = Modifier.padding(bottom = 8.dp),
171+
) {
172+
items(accounts) { profile ->
173+
FilterChip(
174+
selected = state.selectedAccount?.key == profile.key,
175+
onClick = {
176+
state.setAccount(profile)
177+
},
178+
label = {
179+
Text(profile.handle.canonical)
180+
},
181+
leadingIcon = {
182+
AvatarComponent(
183+
data = profile.avatar,
184+
size = 18.dp,
185+
)
186+
},
187+
)
188+
}
131189
}
132190
}
133191
}

app/src/main/java/dev/dimension/flare/ui/screen/home/SearchScreen.kt

Lines changed: 85 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,28 @@ import androidx.compose.foundation.layout.padding
88
import androidx.compose.foundation.lazy.LazyRow
99
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridItemSpan
1010
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
11+
import androidx.compose.material3.DropdownMenuItem
1112
import androidx.compose.material3.FilterChip
13+
import androidx.compose.material3.IconButton
1214
import androidx.compose.material3.Text
1315
import androidx.compose.runtime.Composable
1416
import androidx.compose.runtime.getValue
17+
import androidx.compose.runtime.mutableStateOf
1518
import androidx.compose.runtime.remember
19+
import androidx.compose.runtime.setValue
1620
import androidx.compose.ui.Alignment
1721
import androidx.compose.ui.Modifier
1822
import androidx.compose.ui.unit.dp
1923
import dev.dimension.flare.common.isRefreshing
2024
import dev.dimension.flare.model.AccountType
2125
import dev.dimension.flare.model.MicroBlogKey
2226
import dev.dimension.flare.ui.component.AvatarComponent
27+
import dev.dimension.flare.ui.component.FlareDropdownMenu
2328
import dev.dimension.flare.ui.component.FlareScaffold
2429
import dev.dimension.flare.ui.component.RefreshContainer
2530
import dev.dimension.flare.ui.component.SearchBar
2631
import dev.dimension.flare.ui.component.SearchBarState
32+
import dev.dimension.flare.ui.component.platform.isBigScreen
2733
import dev.dimension.flare.ui.component.searchBarPresenter
2834
import dev.dimension.flare.ui.component.searchContent
2935
import dev.dimension.flare.ui.component.status.LazyStatusVerticalStaggeredGrid
@@ -38,8 +44,14 @@ internal fun SearchScreen(
3844
accountType: AccountType,
3945
onUserClick: (AccountType, MicroBlogKey) -> Unit,
4046
) {
41-
val state by producePresenter("search_${accountType}_$initialQuery") { presenter(accountType, initialQuery) }
47+
val state by producePresenter("search_${accountType}_$initialQuery") {
48+
presenter(
49+
accountType,
50+
initialQuery,
51+
)
52+
}
4253
val lazyListState = rememberLazyStaggeredGridState()
54+
val isBigScreen = isBigScreen()
4355
RegisterTabCallback(
4456
lazyListState = lazyListState,
4557
onRefresh = {
@@ -59,6 +71,51 @@ internal fun SearchScreen(
5971
onSearch = {
6072
state.commitSearch(it)
6173
},
74+
trailingIcon =
75+
state.searchState.selectedAccount?.let { account ->
76+
if (!isBigScreen) {
77+
{
78+
state.searchState.accounts.onSuccess { accounts ->
79+
var showMenu by remember { mutableStateOf(false) }
80+
IconButton(
81+
onClick = {
82+
if (accounts.size > 1) {
83+
showMenu = true
84+
}
85+
},
86+
) {
87+
AvatarComponent(
88+
data = account.avatar,
89+
)
90+
}
91+
FlareDropdownMenu(
92+
expanded = showMenu,
93+
onDismissRequest = { showMenu = false },
94+
) {
95+
accounts.forEach { profile ->
96+
DropdownMenuItem(
97+
text = {
98+
Text(profile.handle.canonical)
99+
},
100+
leadingIcon = {
101+
AvatarComponent(
102+
data = profile.avatar,
103+
size = 18.dp,
104+
)
105+
},
106+
onClick = {
107+
state.searchState.setAccount(profile)
108+
showMenu = false
109+
},
110+
)
111+
}
112+
}
113+
}
114+
}
115+
} else {
116+
null
117+
}
118+
},
62119
)
63120
}
64121
},
@@ -75,32 +132,34 @@ internal fun SearchScreen(
75132
state = lazyListState,
76133
contentPadding = contentPadding,
77134
) {
78-
state.searchState.accounts.onSuccess { accounts ->
79-
if (accounts.size > 1) {
80-
item(
81-
span = StaggeredGridItemSpan.FullLine,
82-
) {
83-
LazyRow(
84-
horizontalArrangement = Arrangement.spacedBy(8.dp),
85-
modifier = Modifier.padding(bottom = 8.dp),
135+
if (isBigScreen) {
136+
state.searchState.accounts.onSuccess { accounts ->
137+
if (accounts.size > 1) {
138+
item(
139+
span = StaggeredGridItemSpan.FullLine,
86140
) {
87-
items(accounts.size) { index ->
88-
val profile = accounts[index]
89-
FilterChip(
90-
selected = state.searchState.selectedAccount?.key == profile.key,
91-
onClick = {
92-
state.searchState.setAccount(profile)
93-
},
94-
label = {
95-
Text(profile.handle.canonical)
96-
},
97-
leadingIcon = {
98-
AvatarComponent(
99-
data = profile.avatar,
100-
size = 18.dp,
101-
)
102-
},
103-
)
141+
LazyRow(
142+
horizontalArrangement = Arrangement.spacedBy(8.dp),
143+
modifier = Modifier.padding(bottom = 8.dp),
144+
) {
145+
items(accounts.size) { index ->
146+
val profile = accounts[index]
147+
FilterChip(
148+
selected = state.searchState.selectedAccount?.key == profile.key,
149+
onClick = {
150+
state.searchState.setAccount(profile)
151+
},
152+
label = {
153+
Text(profile.handle.canonical)
154+
},
155+
leadingIcon = {
156+
AvatarComponent(
157+
data = profile.avatar,
158+
size = 18.dp,
159+
)
160+
},
161+
)
162+
}
104163
}
105164
}
106165
}

0 commit comments

Comments
 (0)