Rewrite popup animations, fix crash

This commit is contained in:
MM20 2023-08-11 12:58:29 +02:00
parent 039f49749f
commit 57c081229b
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
7 changed files with 279 additions and 284 deletions

View File

@ -2,15 +2,11 @@ package de.mm20.launcher2.ui.launcher.search.apps
import android.app.PendingIntent
import android.content.Intent
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.with
import androidx.compose.animation.expandIn
import androidx.compose.animation.shrinkOut
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
@ -20,9 +16,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
@ -52,6 +46,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Rect
@ -62,6 +57,7 @@ import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.roundToIntRect
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import coil.compose.AsyncImage
@ -74,7 +70,6 @@ import de.mm20.launcher2.ui.component.ShapedLauncherIcon
import de.mm20.launcher2.ui.component.SubmenuToolbarAction
import de.mm20.launcher2.ui.component.Toolbar
import de.mm20.launcher2.ui.component.ToolbarAction
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
@ -85,7 +80,6 @@ import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
import de.mm20.launcher2.ui.modifier.scale
import kotlinx.coroutines.launch
import kotlin.math.pow
import kotlin.math.roundToInt
@Composable
fun AppItem(
@ -438,41 +432,30 @@ fun AppItemGridPopup(
origin: Rect,
onDismiss: () -> Unit
) {
AnimatedContent(
targetState = show,
transitionSpec = {
slideInHorizontally(
tween(300),
initialOffsetX = { -it + origin.width.roundToInt() }) with
slideOutHorizontally(
tween(300),
targetOffsetX = { -it + origin.width.roundToInt() }) + fadeOut(snap(400)) using
SizeTransform { _, _ ->
tween(300)
}
}
) { targetState ->
if (targetState) {
AppItem(
modifier = Modifier
.fillMaxWidth()
.scale(
1 - (1 - LocalGridSettings.current.iconSize / 84f) * (1 - animationProgress),
transformOrigin = TransformOrigin(1f, 0f)
)
.offset(
x = 16.dp * (1 - animationProgress).pow(10),
y = -16.dp * (1 - animationProgress),
),
app = app,
onBack = onDismiss
)
} else {
Box(
modifier = Modifier
.requiredWidth(origin.width.toDp())
.requiredHeight(origin.height.toDp())
)
}
AnimatedVisibility(
show,
enter = expandIn(
animationSpec = tween(300),
expandFrom = Alignment.TopEnd,
) { origin.roundToIntRect().size },
exit = shrinkOut(
animationSpec = tween(300),
shrinkTowards = Alignment.TopEnd,
) { origin.roundToIntRect().size },
) {
AppItem(
modifier = Modifier
.fillMaxWidth()
.scale(
1 - (1 - LocalGridSettings.current.iconSize / 84f) * (1 - animationProgress),
transformOrigin = TransformOrigin(1f, 0f)
)
.offset(
x = 16.dp * (1 - animationProgress).pow(10),
y = -16.dp * (1 - animationProgress),
),
app = app,
onBack = onDismiss
)
}
}

View File

@ -2,24 +2,17 @@ package de.mm20.launcher2.ui.launcher.search.calendar
import android.content.Context
import android.text.format.DateUtils
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.with
import androidx.compose.animation.expandIn
import androidx.compose.animation.shrinkOut
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Edit
@ -51,6 +44,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.roundToIntRect
import androidx.lifecycle.lifecycleScope
import de.mm20.launcher2.search.data.CalendarEvent
import de.mm20.launcher2.ui.R
@ -58,7 +52,6 @@ import de.mm20.launcher2.ui.animation.animateTextStyleAsState
import de.mm20.launcher2.ui.component.DefaultToolbarAction
import de.mm20.launcher2.ui.component.Toolbar
import de.mm20.launcher2.ui.component.ToolbarAction
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
@ -313,32 +306,25 @@ fun CalendarItemGridPopup(
origin: Rect,
onDismiss: () -> Unit
) {
AnimatedContent(
targetState = show,
transitionSpec = {
fadeIn(snap()) with
fadeOut(snap(400)) using
SizeTransform { _, _ ->
tween(300)
}
}
) { targetState ->
if (targetState) {
CalendarItem(
modifier = Modifier
.fillMaxWidth()
.background(Color(calendar.color).copy(alpha = 1f - animationProgress)),
calendar = calendar,
showDetails = true,
onBack = onDismiss
)
} else {
Box(
modifier = Modifier
.requiredWidth(origin.width.toDp())
.requiredHeight(origin.height.toDp())
)
}
AnimatedVisibility(
show,
enter = expandIn(
animationSpec = tween(300),
expandFrom = Alignment.Center,
) { origin.roundToIntRect().size },
exit = shrinkOut(
animationSpec = tween(300),
shrinkTowards = Alignment.Center,
) { origin.roundToIntRect().size },
) {
CalendarItem(
modifier = Modifier
.fillMaxWidth()
.background(Color(calendar.color).copy(alpha = 1f - animationProgress)),
calendar = calendar,
showDetails = true,
onBack = onDismiss
)
}
}

View File

@ -2,24 +2,17 @@ package de.mm20.launcher2.ui.launcher.search.contacts
import android.content.Intent
import android.net.Uri
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.with
import androidx.compose.foundation.layout.Box
import androidx.compose.animation.expandIn
import androidx.compose.animation.shrinkOut
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
@ -51,6 +44,7 @@ import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.roundToIntRect
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import de.mm20.launcher2.ktx.tryStartActivity
@ -64,7 +58,6 @@ import de.mm20.launcher2.ui.component.Toolbar
import de.mm20.launcher2.ui.component.ToolbarAction
import de.mm20.launcher2.ui.icons.Telegram
import de.mm20.launcher2.ui.icons.WhatsApp
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
@ -386,38 +379,31 @@ fun ContactItemGridPopup(
origin: Rect,
onDismiss: () -> Unit
) {
AnimatedContent(
targetState = show,
transitionSpec = {
fadeIn(snap()) with
fadeOut(snap(400)) using
SizeTransform { _, _ ->
tween(300)
}
}
) { targetState ->
if (targetState) {
ContactItem(
modifier = Modifier
.fillMaxWidth()
.scale(
1 - (1 - LocalGridSettings.current.iconSize / 48f) * (1 - animationProgress),
transformOrigin = TransformOrigin(0f, 0f)
)
.offset(
x = -16.dp * (1 - animationProgress),
y = -16.dp * (1 - animationProgress)
),
contact = contact,
showDetails = true,
onBack = onDismiss
)
} else {
Box(
modifier = Modifier
.requiredWidth(origin.width.toDp())
.requiredHeight(origin.height.toDp())
)
}
AnimatedVisibility(
show,
enter = expandIn(
animationSpec = tween(300),
expandFrom = Alignment.TopStart,
) { origin.roundToIntRect().size },
exit = shrinkOut(
animationSpec = tween(300),
shrinkTowards = Alignment.TopStart,
) { origin.roundToIntRect().size },
) {
ContactItem(
modifier = Modifier
.fillMaxWidth()
.scale(
1 - (1 - LocalGridSettings.current.iconSize / 48f) * (1 - animationProgress),
transformOrigin = TransformOrigin(0f, 0f)
)
.offset(
x = -16.dp * (1 - animationProgress),
y = -16.dp * (1 - animationProgress)
),
contact = contact,
showDetails = true,
onBack = onDismiss
)
}
}

View File

@ -1,15 +1,39 @@
package de.mm20.launcher2.ui.launcher.search.files
import androidx.compose.animation.*
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.snap
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.layout.*
import androidx.compose.animation.expandIn
import androidx.compose.animation.shrinkOut
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Delete
import androidx.compose.material.icons.rounded.Edit
import androidx.compose.material.icons.rounded.OpenInNew
import androidx.compose.material.icons.rounded.Share
import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.StarOutline
import androidx.compose.material.icons.rounded.Visibility
import androidx.compose.material.icons.rounded.VisibilityOff
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
@ -19,9 +43,9 @@ import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.roundToIntRect
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.search.data.File
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.animation.animateTextStyleAsState
@ -29,7 +53,6 @@ import de.mm20.launcher2.ui.component.DefaultToolbarAction
import de.mm20.launcher2.ui.component.ShapedLauncherIcon
import de.mm20.launcher2.ui.component.Toolbar
import de.mm20.launcher2.ui.component.ToolbarAction
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
@ -40,7 +63,6 @@ import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
import de.mm20.launcher2.ui.modifier.scale
import kotlinx.coroutines.launch
import java.text.DecimalFormat
import kotlin.math.roundToInt
@Composable
fun FileItem(
@ -265,11 +287,14 @@ fun FileItem(
onBack()
lifecycleOwner.lifecycleScope.launch {
val result = snackbarHostState.showSnackbar(
message = context.getString(R.string.msg_item_hidden, file.label),
message = context.getString(
R.string.msg_item_hidden,
file.label
),
actionLabel = context.getString(R.string.action_undo),
duration = SnackbarDuration.Short,
)
if(result == SnackbarResult.ActionPerformed) {
)
if (result == SnackbarResult.ActionPerformed) {
viewModel.unhide()
}
}
@ -302,43 +327,32 @@ fun FileItemGridPopup(
origin: Rect,
onDismiss: () -> Unit
) {
AnimatedContent(
targetState = show,
transitionSpec = {
slideInHorizontally(
tween(300),
initialOffsetX = { -it + origin.width.roundToInt() }) with
slideOutHorizontally(
tween(300),
targetOffsetX = { -it + origin.width.roundToInt() }) + fadeOut(snap(400)) using
SizeTransform { _, _ ->
tween(300)
}
}
) { targetState ->
if (targetState) {
FileItem(
modifier = Modifier
.fillMaxWidth()
.scale(
1 - (1 - LocalGridSettings.current.iconSize / 48f) * (1 - animationProgress),
transformOrigin = TransformOrigin(1f, 0f)
)
.offset(
x = 16.dp * (1 - animationProgress),
y = -16.dp * (1 - animationProgress)
),
file = file,
showDetails = true,
onBack = onDismiss
)
} else {
Box(
modifier = Modifier
.requiredWidth(origin.width.toDp())
.requiredHeight(origin.height.toDp())
)
}
AnimatedVisibility(
show,
enter = expandIn(
animationSpec = tween(300),
expandFrom = Alignment.TopEnd,
) { origin.roundToIntRect().size },
exit = shrinkOut(
animationSpec = tween(300),
shrinkTowards = Alignment.TopEnd,
) { origin.roundToIntRect().size },
) {
FileItem(
modifier = Modifier
.fillMaxWidth()
.scale(
1 - (1 - LocalGridSettings.current.iconSize / 48f) * (1 - animationProgress),
transformOrigin = TransformOrigin(1f, 0f)
)
.offset(
x = 16.dp * (1 - animationProgress),
y = -16.dp * (1 - animationProgress)
),
file = file,
showDetails = true,
onBack = onDismiss
)
}
}

View File

@ -4,13 +4,41 @@ package de.mm20.launcher2.ui.launcher.search.shortcut
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.compose.animation.*
import androidx.compose.animation.core.*
import androidx.compose.foundation.layout.*
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
import androidx.compose.animation.expandIn
import androidx.compose.animation.shrinkOut
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Delete
import androidx.compose.material.icons.rounded.Edit
import androidx.compose.material.icons.rounded.Info
import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.StarOutline
import androidx.compose.material.icons.rounded.Visibility
import androidx.compose.material.icons.rounded.VisibilityOff
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarResult
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.graphics.TransformOrigin
@ -19,9 +47,9 @@ import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.roundToIntRect
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.ktx.tryStartActivity
import de.mm20.launcher2.search.data.AppShortcut
import de.mm20.launcher2.search.data.LauncherShortcut
@ -32,7 +60,6 @@ import de.mm20.launcher2.ui.component.DefaultToolbarAction
import de.mm20.launcher2.ui.component.ShapedLauncherIcon
import de.mm20.launcher2.ui.component.Toolbar
import de.mm20.launcher2.ui.component.ToolbarAction
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
@ -43,7 +70,6 @@ import de.mm20.launcher2.ui.locals.LocalSnackbarHostState
import de.mm20.launcher2.ui.modifier.scale
import kotlinx.coroutines.launch
import kotlin.math.pow
import kotlin.math.roundToInt
@Composable
fun AppShortcutItem(
@ -263,43 +289,32 @@ fun ShortcutItemGridPopup(
origin: Rect,
onDismiss: () -> Unit
) {
AnimatedContent(
targetState = show,
transitionSpec = {
slideInHorizontally(
tween(300),
initialOffsetX = { -it + origin.width.roundToInt() }) with
slideOutHorizontally(
tween(300),
targetOffsetX = { -it + origin.width.roundToInt() }) + fadeOut(snap(400)) using
SizeTransform { _, _ ->
tween(300)
}
}
) { targetState ->
if (targetState) {
AppShortcutItem(
modifier = Modifier
.fillMaxWidth()
.scale(
1 - (1 - LocalGridSettings.current.iconSize / 84f) * (1 - animationProgress),
transformOrigin = TransformOrigin(1f, 0f)
)
.offset(
x = 16.dp * (1 - animationProgress).pow(10),
y = -16.dp * (1 - animationProgress),
),
shortcut = shortcut,
showDetails = true,
onBack = onDismiss
)
} else {
Box(
modifier = Modifier
.requiredWidth(origin.width.toDp())
.requiredHeight(origin.height.toDp())
)
}
AnimatedVisibility(
show,
enter = expandIn(
animationSpec = tween(300),
expandFrom = Alignment.TopEnd,
) { origin.roundToIntRect().size },
exit = shrinkOut(
animationSpec = tween(300),
shrinkTowards = Alignment.TopEnd,
) { origin.roundToIntRect().size },
) {
AppShortcutItem(
modifier = Modifier
.fillMaxWidth()
.scale(
1 - (1 - LocalGridSettings.current.iconSize / 84f) * (1 - animationProgress),
transformOrigin = TransformOrigin(1f, 0f)
)
.offset(
x = 16.dp * (1 - animationProgress).pow(10),
y = -16.dp * (1 - animationProgress),
),
shortcut = shortcut,
showDetails = true,
onBack = onDismiss
)
}
}

View File

@ -1,29 +1,41 @@
package de.mm20.launcher2.ui.launcher.search.website
import androidx.compose.animation.*
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandIn
import androidx.compose.animation.shrinkOut
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.*
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Edit
import androidx.compose.material.icons.rounded.Share
import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.StarOutline
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.compose.ui.unit.roundToIntRect
import coil.compose.AsyncImage
import de.mm20.launcher2.search.data.Website
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.DefaultToolbarAction
import de.mm20.launcher2.ui.component.Toolbar
import de.mm20.launcher2.ui.component.ToolbarAction
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
@ -59,7 +71,8 @@ fun WebsiteItem(
.background(MaterialTheme.colorScheme.secondaryContainer),
model = website.image,
contentScale = ContentScale.Crop,
contentDescription = null)
contentDescription = null
)
}
Column(
modifier = Modifier.padding(16.dp),
@ -111,7 +124,7 @@ fun WebsiteItem(
toolbarActions.add(
DefaultToolbarAction(
label = stringResource(R.string.menu_share),
icon= Icons.Rounded.Share,
icon = Icons.Rounded.Share,
action = {
website.share(context)
}
@ -146,29 +159,22 @@ fun WebsiteItemGridPopup(
origin: Rect,
onDismiss: () -> Unit
) {
AnimatedContent(
targetState = show,
transitionSpec = {
fadeIn(tween(200)) with
fadeOut(tween(200, 200)) using
SizeTransform { _, _ ->
tween(300)
}
}
) { targetState ->
if (targetState) {
WebsiteItem(
modifier = Modifier
.fillMaxWidth(),
website = website,
onBack = onDismiss
)
} else {
Box(
modifier = Modifier
.requiredWidth(origin.width.toDp())
.requiredHeight(origin.height.toDp())
)
}
AnimatedVisibility(
show,
enter = expandIn(
animationSpec = tween(300),
expandFrom = Alignment.Center,
) { origin.roundToIntRect().size },
exit = shrinkOut(
animationSpec = tween(300),
shrinkTowards = Alignment.Center,
) { origin.roundToIntRect().size },
) {
WebsiteItem(
modifier = Modifier
.fillMaxWidth(),
website = website,
onBack = onDismiss
)
}
}

View File

@ -1,29 +1,41 @@
package de.mm20.launcher2.ui.launcher.search.wikipedia
import androidx.compose.animation.*
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandIn
import androidx.compose.animation.shrinkOut
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.*
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Edit
import androidx.compose.material.icons.rounded.Share
import androidx.compose.material.icons.rounded.Star
import androidx.compose.material.icons.rounded.StarOutline
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Rect
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.compose.ui.unit.roundToIntRect
import coil.compose.AsyncImage
import de.mm20.launcher2.search.data.Wikipedia
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.DefaultToolbarAction
import de.mm20.launcher2.ui.component.Toolbar
import de.mm20.launcher2.ui.component.ToolbarAction
import de.mm20.launcher2.ui.ktx.toDp
import de.mm20.launcher2.ui.ktx.toPixels
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
import de.mm20.launcher2.ui.launcher.search.listItemViewModel
@ -154,29 +166,22 @@ fun WikipediaItemGridPopup(
origin: Rect,
onDismiss: () -> Unit
) {
AnimatedContent(
targetState = show,
transitionSpec = {
fadeIn(tween(200)) with
fadeOut(tween(200, 200)) using
SizeTransform { _, _ ->
tween(300)
}
}
) { targetState ->
if (targetState) {
WikipediaItem(
modifier = Modifier
.fillMaxWidth(),
wikipedia = wikipedia,
onBack = onDismiss
)
} else {
Box(
modifier = Modifier
.requiredWidth(origin.width.toDp())
.requiredHeight(origin.height.toDp())
)
}
AnimatedVisibility(
show,
enter = expandIn(
animationSpec = tween(300),
expandFrom = Alignment.Center,
) { origin.roundToIntRect().size },
exit = shrinkOut(
animationSpec = tween(300),
shrinkTowards = Alignment.Center,
) { origin.roundToIntRect().size },
) {
WikipediaItem(
modifier = Modifier
.fillMaxWidth(),
wikipedia = wikipedia,
onBack = onDismiss
)
}
}