Use material3 chips in app item popup
This commit is contained in:
parent
b64555d3ae
commit
2fb2e2ddda
@ -1,39 +1,79 @@
|
|||||||
package de.mm20.launcher2.ui.launcher.search.apps
|
package de.mm20.launcher2.ui.launcher.search.apps
|
||||||
|
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.LauncherApps
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.*
|
import androidx.compose.animation.SizeTransform
|
||||||
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.animation.core.snap
|
import androidx.compose.animation.core.snap
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.slideInHorizontally
|
||||||
|
import androidx.compose.animation.slideOutHorizontally
|
||||||
|
import androidx.compose.animation.with
|
||||||
|
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.IntrinsicSize
|
||||||
|
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
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.*
|
import androidx.compose.material.icons.rounded.Android
|
||||||
|
import androidx.compose.material.icons.rounded.ArrowBack
|
||||||
|
import androidx.compose.material.icons.rounded.Clear
|
||||||
|
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.Link
|
||||||
|
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.Icon
|
||||||
|
import androidx.compose.material3.InputChip
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SnackbarDuration
|
import androidx.compose.material3.SnackbarDuration
|
||||||
import androidx.compose.material3.SnackbarResult
|
import androidx.compose.material3.SnackbarResult
|
||||||
import androidx.compose.material3.Text
|
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.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.geometry.Rect
|
import androidx.compose.ui.geometry.Rect
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.TransformOrigin
|
import androidx.compose.ui.graphics.TransformOrigin
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
import androidx.compose.ui.platform.LocalLifecycleOwner
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.app.NotificationCompat
|
|
||||||
import androidx.core.content.getSystemService
|
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import coil.compose.AsyncImage
|
||||||
import coil.compose.rememberAsyncImagePainter
|
|
||||||
import com.google.accompanist.flowlayout.FlowRow
|
import com.google.accompanist.flowlayout.FlowRow
|
||||||
|
import de.mm20.launcher2.crashreporter.CrashReporter
|
||||||
import de.mm20.launcher2.search.data.LauncherApp
|
import de.mm20.launcher2.search.data.LauncherApp
|
||||||
import de.mm20.launcher2.ui.R
|
import de.mm20.launcher2.ui.R
|
||||||
import de.mm20.launcher2.ui.component.*
|
import de.mm20.launcher2.ui.component.DefaultToolbarAction
|
||||||
|
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.toDp
|
||||||
import de.mm20.launcher2.ui.ktx.toPixels
|
import de.mm20.launcher2.ui.ktx.toPixels
|
||||||
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
|
import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM
|
||||||
@ -118,27 +158,53 @@ fun AppItem(
|
|||||||
|
|
||||||
for (not in notifications) {
|
for (not in notifications) {
|
||||||
val title = not.title?.takeIf { it.isNotBlank() }
|
val title = not.title?.takeIf { it.isNotBlank() }
|
||||||
?: not.text?.takeIf { it.isNotBlank() }
|
?: not.text?.takeIf { it.isNotBlank() }
|
||||||
?: continue
|
?: continue
|
||||||
|
|
||||||
val icon =
|
val icon = remember(not.smallIcon) { not.smallIcon?.loadDrawable(context) }
|
||||||
remember { not.smallIcon?.loadDrawable(context) }?.let {
|
|
||||||
rememberAsyncImagePainter(
|
InputChip(
|
||||||
it
|
modifier = Modifier.width(IntrinsicSize.Max),
|
||||||
|
selected = false,
|
||||||
|
label = {
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
Chip(
|
|
||||||
text = title,
|
|
||||||
icon = icon,
|
|
||||||
rightIcon = Icons.Rounded.Clear,
|
|
||||||
rightAction = {
|
|
||||||
viewModel.clearNotification(not)
|
|
||||||
},
|
},
|
||||||
|
avatar = {
|
||||||
|
Box(modifier = Modifier.background(Color(not.color))) {
|
||||||
|
AsyncImage(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(3.dp)
|
||||||
|
.requiredSize(18.dp),
|
||||||
|
model = icon,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trailingIcon = if (not.isClearable) {
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
Icons.Rounded.Clear,
|
||||||
|
null,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(CircleShape)
|
||||||
|
.size(18.dp)
|
||||||
|
.clickable {
|
||||||
|
viewModel.clearNotification(not)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else null,
|
||||||
onClick = {
|
onClick = {
|
||||||
try {
|
try {
|
||||||
not.contentIntent?.send()
|
not.contentIntent?.send()
|
||||||
} catch (e: PendingIntent.CanceledException) {}
|
} catch (e: PendingIntent.CanceledException) {
|
||||||
|
CrashReporter.logException(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -161,27 +227,51 @@ fun AppItem(
|
|||||||
shortcut.launcherShortcut
|
shortcut.launcherShortcut
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
?.let {
|
|
||||||
rememberAsyncImagePainter(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
Chip(
|
InputChip(
|
||||||
text = title.toString(),
|
modifier = Modifier.width(IntrinsicSize.Max),
|
||||||
icon = icon,
|
selected = false,
|
||||||
rightIcon = if (LocalFavoritesEnabled.current) {
|
|
||||||
if (isPinned) Icons.Rounded.Star else Icons.Rounded.StarOutline
|
|
||||||
} else null,
|
|
||||||
rightAction = {
|
|
||||||
if (isPinned) {
|
|
||||||
viewModel.unpinShortcut(shortcut)
|
|
||||||
} else {
|
|
||||||
viewModel.pinShortcut(shortcut)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.launchShortcut(context, shortcut)
|
viewModel.launchShortcut(context, shortcut)
|
||||||
}
|
},
|
||||||
|
label = {
|
||||||
|
Text(
|
||||||
|
title.toString(),
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.weight(1f)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
avatar = {
|
||||||
|
AsyncImage(
|
||||||
|
model = icon,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(CircleShape)
|
||||||
|
.size(24.dp),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
trailingIcon = if (LocalFavoritesEnabled.current) {
|
||||||
|
{
|
||||||
|
Icon(
|
||||||
|
if (isPinned) Icons.Rounded.Star else Icons.Rounded.StarOutline,
|
||||||
|
null,
|
||||||
|
modifier = Modifier
|
||||||
|
.clip(CircleShape)
|
||||||
|
.requiredSize(18.dp)
|
||||||
|
.clickable {
|
||||||
|
|
||||||
|
if (isPinned) {
|
||||||
|
viewModel.unpinShortcut(shortcut)
|
||||||
|
} else {
|
||||||
|
viewModel.pinShortcut(shortcut)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else null
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ data class Notification(
|
|||||||
val key: String,
|
val key: String,
|
||||||
val packageName: String,
|
val packageName: String,
|
||||||
val postTime: Long,
|
val postTime: Long,
|
||||||
|
val isClearable: Boolean,
|
||||||
val canShowBadge: Boolean,
|
val canShowBadge: Boolean,
|
||||||
val number: Int,
|
val number: Int,
|
||||||
val color: Int,
|
val color: Int,
|
||||||
@ -29,6 +30,7 @@ data class Notification(
|
|||||||
key = sbn.key,
|
key = sbn.key,
|
||||||
packageName = sbn.packageName,
|
packageName = sbn.packageName,
|
||||||
postTime = sbn.postTime,
|
postTime = sbn.postTime,
|
||||||
|
isClearable = sbn.isClearable,
|
||||||
canShowBadge = ranking.canShowBadge(),
|
canShowBadge = ranking.canShowBadge(),
|
||||||
number = sbn.notification.number,
|
number = sbn.notification.number,
|
||||||
color = sbn.notification.color,
|
color = sbn.notification.color,
|
||||||
@ -49,6 +51,7 @@ data class Notification(
|
|||||||
canShowBadge = ranking.canShowBadge(),
|
canShowBadge = ranking.canShowBadge(),
|
||||||
number = notification.number,
|
number = notification.number,
|
||||||
color = notification.color,
|
color = notification.color,
|
||||||
|
isClearable = notification.isClearable,
|
||||||
smallIcon = notification.smallIcon,
|
smallIcon = notification.smallIcon,
|
||||||
extras = notification.extras,
|
extras = notification.extras,
|
||||||
contentIntent = notification.contentIntent
|
contentIntent = notification.contentIntent
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user