Skip to content

Commit 8b645d9

Browse files
committed
AppLinkChooserSheet: use material3 bottom sheet
1 parent 140b359 commit 8b645d9

File tree

2 files changed

+39
-138
lines changed

2 files changed

+39
-138
lines changed

app/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ dependencies {
8585

8686
implementation platform("androidx.compose:compose-bom-alpha:$compose_bom_version")
8787
implementation "androidx.compose.ui:ui"
88-
implementation "androidx.compose.material:material"
8988
implementation "androidx.compose.material:material-icons-extended"
9089
implementation "androidx.compose.material3:material3"
9190
implementation "androidx.compose.ui:ui-text-google-fonts"

app/src/main/java/xyz/ivaniskandar/shouko/activity/LinkTargetChooserActivity.kt

Lines changed: 39 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -6,62 +6,37 @@ import android.content.pm.PackageManager
66
import android.os.Bundle
77
import android.provider.Settings
88
import androidx.activity.ComponentActivity
9-
import androidx.activity.compose.BackHandler
109
import androidx.activity.compose.setContent
11-
import androidx.compose.animation.core.TweenSpec
12-
import androidx.compose.animation.core.animateFloatAsState
13-
import androidx.compose.foundation.Canvas
1410
import androidx.compose.foundation.Image
1511
import androidx.compose.foundation.combinedClickable
16-
import androidx.compose.foundation.gestures.detectTapGestures
1712
import androidx.compose.foundation.layout.Arrangement
18-
import androidx.compose.foundation.layout.Box
1913
import androidx.compose.foundation.layout.PaddingValues
2014
import androidx.compose.foundation.layout.WindowInsets
2115
import androidx.compose.foundation.layout.WindowInsetsSides
22-
import androidx.compose.foundation.layout.fillMaxSize
2316
import androidx.compose.foundation.layout.fillMaxWidth
2417
import androidx.compose.foundation.layout.navigationBars
2518
import androidx.compose.foundation.layout.only
2619
import androidx.compose.foundation.layout.padding
2720
import androidx.compose.foundation.layout.size
28-
import androidx.compose.foundation.layout.widthIn
2921
import androidx.compose.foundation.layout.windowInsetsPadding
3022
import androidx.compose.foundation.lazy.LazyColumn
3123
import androidx.compose.foundation.lazy.items
32-
import androidx.compose.foundation.shape.RoundedCornerShape
33-
import androidx.compose.material.ModalBottomSheetLayout
34-
import androidx.compose.material.ModalBottomSheetValue
35-
import androidx.compose.material.rememberModalBottomSheetState
3624
import androidx.compose.material3.ListItem
3725
import androidx.compose.material3.MaterialTheme
26+
import androidx.compose.material3.ModalBottomSheet
3827
import androidx.compose.material3.Text
39-
import androidx.compose.material3.surfaceColorAtElevation
4028
import androidx.compose.runtime.Composable
41-
import androidx.compose.runtime.LaunchedEffect
42-
import androidx.compose.runtime.getValue
43-
import androidx.compose.runtime.mutableStateOf
44-
import androidx.compose.runtime.remember
45-
import androidx.compose.runtime.rememberCoroutineScope
46-
import androidx.compose.runtime.setValue
47-
import androidx.compose.ui.Alignment
4829
import androidx.compose.ui.Modifier
49-
import androidx.compose.ui.graphics.Color
5030
import androidx.compose.ui.graphics.ImageBitmap
5131
import androidx.compose.ui.graphics.asImageBitmap
52-
import androidx.compose.ui.graphics.isSpecified
5332
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
54-
import androidx.compose.ui.input.pointer.pointerInput
5533
import androidx.compose.ui.platform.LocalHapticFeedback
5634
import androidx.compose.ui.res.stringResource
57-
import androidx.compose.ui.semantics.onClick
58-
import androidx.compose.ui.semantics.semantics
5935
import androidx.compose.ui.text.style.TextAlign
6036
import androidx.compose.ui.unit.dp
6137
import androidx.core.graphics.drawable.toBitmap
6238
import androidx.core.net.toUri
6339
import androidx.core.view.WindowCompat
64-
import kotlinx.coroutines.launch
6540
import xyz.ivaniskandar.shouko.R
6641
import xyz.ivaniskandar.shouko.feature.LinkCleaner
6742
import xyz.ivaniskandar.shouko.ui.IconDrawableShadowWrapper
@@ -159,123 +134,50 @@ private fun AppLinkChooserSheet(
159134
onItemLongClick: (ComponentName) -> Unit,
160135
onFinish: () -> Unit,
161136
) {
162-
val state = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden)
163-
val scope = rememberCoroutineScope()
164137
val haptic = LocalHapticFeedback.current
165-
166-
Box {
167-
Scrim(
168-
color = MaterialTheme.colorScheme.scrim.copy(alpha = 0.32f),
169-
onDismiss = {
170-
scope.launch { state.hide() }
171-
},
172-
visible = state.targetValue != ModalBottomSheetValue.Hidden,
173-
)
174-
ModalBottomSheetLayout(
138+
ModalBottomSheet(onDismissRequest = onFinish) {
139+
Text(
140+
text = stringResource(R.string.link_chooser_dialog_title),
175141
modifier = Modifier
176-
.widthIn(max = 640.dp)
177-
.align(Alignment.BottomCenter),
178-
scrimColor = Color.Transparent,
179-
sheetState = state,
180-
sheetShape = RoundedCornerShape(topStart = 28.dp, topEnd = 28.dp),
181-
sheetElevation = 0.dp,
182-
sheetBackgroundColor = MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp),
183-
sheetContentColor = MaterialTheme.colorScheme.onSurface,
184-
sheetContent = {
185-
Text(
186-
text = stringResource(R.string.link_chooser_dialog_title),
142+
.fillMaxWidth()
143+
.padding(bottom = 16.dp),
144+
color = MaterialTheme.colorScheme.onSurface,
145+
textAlign = TextAlign.Center,
146+
style = MaterialTheme.typography.titleMedium,
147+
)
148+
SoftDivider()
149+
LazyColumn(
150+
modifier = Modifier.windowInsetsPadding(WindowInsets.navigationBars.only(WindowInsetsSides.Bottom)),
151+
contentPadding = PaddingValues(vertical = 8.dp),
152+
verticalArrangement = Arrangement.spacedBy(2.dp),
153+
) {
154+
items(targets) { item ->
155+
ListItem(
187156
modifier = Modifier
188-
.fillMaxWidth()
189-
.padding(vertical = 16.dp),
190-
color = MaterialTheme.colorScheme.onSurface,
191-
textAlign = TextAlign.Center,
192-
style = MaterialTheme.typography.titleMedium,
193-
)
194-
SoftDivider(modifier = Modifier.padding(horizontal = 16.dp))
195-
LazyColumn(
196-
modifier = Modifier.windowInsetsPadding(WindowInsets.navigationBars.only(WindowInsetsSides.Bottom)),
197-
contentPadding = PaddingValues(vertical = 8.dp),
198-
verticalArrangement = Arrangement.spacedBy(2.dp),
199-
) {
200-
items(targets) { item ->
201-
ListItem(
202-
modifier = Modifier
203-
.combinedClickable(
204-
onLongClick = {
205-
scope.launch { state.hide() }
206-
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
207-
onItemLongClick(item.component)
208-
},
209-
onClick = {
210-
scope.launch { state.hide() }
211-
onItemClick(item.component)
212-
},
213-
),
214-
leadingContent = {
215-
Image(
216-
bitmap = item.icon,
217-
contentDescription = null,
218-
modifier = Modifier.size(36.dp),
219-
)
157+
.combinedClickable(
158+
onLongClick = {
159+
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
160+
onItemLongClick(item.component)
220161
},
221-
headlineContent = {
222-
Text(
223-
text = item.title,
224-
style = MaterialTheme.typography.bodyLarge,
225-
)
162+
onClick = {
163+
onItemClick(item.component)
226164
},
227-
tonalElevation = 1.dp,
165+
),
166+
leadingContent = {
167+
Image(
168+
bitmap = item.icon,
169+
contentDescription = null,
170+
modifier = Modifier.size(36.dp),
228171
)
229-
}
230-
}
231-
},
232-
content = { /* Empty */ },
233-
)
234-
}
235-
var opened by remember { mutableStateOf(false) }
236-
LaunchedEffect(state.currentValue, onFinish) {
237-
if (!opened) scope.launch { state.show() }
238-
when (state.currentValue) {
239-
ModalBottomSheetValue.Hidden -> if (opened) onFinish()
240-
ModalBottomSheetValue.Expanded, ModalBottomSheetValue.HalfExpanded -> opened = true
241-
}
242-
}
243-
BackHandler {
244-
scope.launch { state.hide() }
245-
}
246-
}
247-
248-
@Composable
249-
private fun Scrim(
250-
color: Color,
251-
onDismiss: () -> Unit,
252-
visible: Boolean,
253-
) {
254-
if (color.isSpecified) {
255-
val alpha by animateFloatAsState(
256-
targetValue = if (visible) 1f else 0f,
257-
animationSpec = TweenSpec(),
258-
label = "scrim",
259-
)
260-
val dismissModifier = if (visible) {
261-
Modifier
262-
.pointerInput(onDismiss) { detectTapGestures { onDismiss() } }
263-
.semantics(mergeDescendants = true) {
264-
onClick {
265-
onDismiss()
266-
true
267-
}
268-
}
269-
} else {
270-
Modifier
271-
}
272-
273-
Canvas(
274-
Modifier
275-
.fillMaxSize()
276-
.then(dismissModifier),
277-
) {
278-
drawRect(color = color, alpha = alpha)
172+
},
173+
headlineContent = {
174+
Text(
175+
text = item.title,
176+
style = MaterialTheme.typography.bodyLarge,
177+
)
178+
},
179+
)
180+
}
279181
}
280182
}
281183
}

0 commit comments

Comments
 (0)