@@ -6,62 +6,37 @@ import android.content.pm.PackageManager
66import android.os.Bundle
77import android.provider.Settings
88import androidx.activity.ComponentActivity
9- import androidx.activity.compose.BackHandler
109import androidx.activity.compose.setContent
11- import androidx.compose.animation.core.TweenSpec
12- import androidx.compose.animation.core.animateFloatAsState
13- import androidx.compose.foundation.Canvas
1410import androidx.compose.foundation.Image
1511import androidx.compose.foundation.combinedClickable
16- import androidx.compose.foundation.gestures.detectTapGestures
1712import androidx.compose.foundation.layout.Arrangement
18- import androidx.compose.foundation.layout.Box
1913import androidx.compose.foundation.layout.PaddingValues
2014import androidx.compose.foundation.layout.WindowInsets
2115import androidx.compose.foundation.layout.WindowInsetsSides
22- import androidx.compose.foundation.layout.fillMaxSize
2316import androidx.compose.foundation.layout.fillMaxWidth
2417import androidx.compose.foundation.layout.navigationBars
2518import androidx.compose.foundation.layout.only
2619import androidx.compose.foundation.layout.padding
2720import androidx.compose.foundation.layout.size
28- import androidx.compose.foundation.layout.widthIn
2921import androidx.compose.foundation.layout.windowInsetsPadding
3022import androidx.compose.foundation.lazy.LazyColumn
3123import 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
3624import androidx.compose.material3.ListItem
3725import androidx.compose.material3.MaterialTheme
26+ import androidx.compose.material3.ModalBottomSheet
3827import androidx.compose.material3.Text
39- import androidx.compose.material3.surfaceColorAtElevation
4028import 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
4829import androidx.compose.ui.Modifier
49- import androidx.compose.ui.graphics.Color
5030import androidx.compose.ui.graphics.ImageBitmap
5131import androidx.compose.ui.graphics.asImageBitmap
52- import androidx.compose.ui.graphics.isSpecified
5332import androidx.compose.ui.hapticfeedback.HapticFeedbackType
54- import androidx.compose.ui.input.pointer.pointerInput
5533import androidx.compose.ui.platform.LocalHapticFeedback
5634import androidx.compose.ui.res.stringResource
57- import androidx.compose.ui.semantics.onClick
58- import androidx.compose.ui.semantics.semantics
5935import androidx.compose.ui.text.style.TextAlign
6036import androidx.compose.ui.unit.dp
6137import androidx.core.graphics.drawable.toBitmap
6238import androidx.core.net.toUri
6339import androidx.core.view.WindowCompat
64- import kotlinx.coroutines.launch
6540import xyz.ivaniskandar.shouko.R
6641import xyz.ivaniskandar.shouko.feature.LinkCleaner
6742import 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