forked from melod1n/fast-messenger
switch to compose-bom-alpha
This commit is contained in:
@@ -50,7 +50,6 @@ import dev.meloda.fast.ui.theme.LocalThemeConfig
|
|||||||
import dev.meloda.fast.ui.theme.LocalUser
|
import dev.meloda.fast.ui.theme.LocalUser
|
||||||
import dev.meloda.fast.ui.util.isNeedToEnableDarkMode
|
import dev.meloda.fast.ui.util.isNeedToEnableDarkMode
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
import org.koin.compose.KoinContext
|
|
||||||
import org.koin.compose.koinInject
|
import org.koin.compose.koinInject
|
||||||
import dev.meloda.fast.ui.R as UiR
|
import dev.meloda.fast.ui.R as UiR
|
||||||
|
|
||||||
@@ -89,7 +88,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
requestNotificationPermissions()
|
requestNotificationPermissions()
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
KoinContext {
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val userSettings: UserSettings = koinInject()
|
val userSettings: UserSettings = koinInject()
|
||||||
@@ -253,7 +251,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun createNotificationChannels() {
|
private fun createNotificationChannels() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
package dev.meloda.fast.ui.components
|
package dev.meloda.fast.ui.components
|
||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Indication
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.material.ripple.rememberRipple
|
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.IconButtonColors
|
import androidx.compose.material3.IconButtonColors
|
||||||
import androidx.compose.material3.IconButtonDefaults
|
import androidx.compose.material3.IconButtonDefaults
|
||||||
import androidx.compose.material3.LocalContentColor
|
import androidx.compose.material3.LocalContentColor
|
||||||
import androidx.compose.material3.LocalUseFallbackRippleImplementation
|
|
||||||
import androidx.compose.material3.minimumInteractiveComponentSize
|
import androidx.compose.material3.minimumInteractiveComponentSize
|
||||||
import androidx.compose.material3.ripple
|
import androidx.compose.material3.ripple
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
@@ -23,10 +20,9 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun IconButton(
|
fun IconButton(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
@@ -49,10 +45,7 @@ fun IconButton(
|
|||||||
onLongClick = onLongClick,
|
onLongClick = onLongClick,
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
interactionSource = interactionSource,
|
interactionSource = interactionSource,
|
||||||
indication = rippleOrFallbackImplementation(
|
indication = ripple()
|
||||||
bounded = false,
|
|
||||||
radius = IconButtonTokens.StateLayerSize / 2
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
) {
|
||||||
@@ -61,21 +54,6 @@ fun IconButton(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION_ERROR")
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
internal fun rippleOrFallbackImplementation(
|
|
||||||
bounded: Boolean = true,
|
|
||||||
radius: Dp = Dp.Unspecified,
|
|
||||||
color: Color = Color.Unspecified
|
|
||||||
): Indication {
|
|
||||||
return if (LocalUseFallbackRippleImplementation.current) {
|
|
||||||
rememberRipple(bounded, radius, color)
|
|
||||||
} else {
|
|
||||||
ripple(bounded, radius, color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal object IconButtonTokens {
|
internal object IconButtonTokens {
|
||||||
val StateLayerShape = CircleShape
|
val StateLayerShape = CircleShape
|
||||||
val StateLayerSize = 40.0.dp
|
val StateLayerSize = 40.0.dp
|
||||||
|
|||||||
+39
-262
@@ -1,11 +1,6 @@
|
|||||||
package dev.meloda.fast.messageshistory.presentation
|
package dev.meloda.fast.messageshistory.presentation
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuItem
|
|
||||||
import android.view.View
|
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.annotation.VisibleForTesting
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.animation.animateColorAsState
|
import androidx.compose.animation.animateColorAsState
|
||||||
@@ -41,6 +36,8 @@ import androidx.compose.foundation.layout.width
|
|||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.contextmenu.builder.item
|
||||||
|
import androidx.compose.foundation.text.contextmenu.modifier.addTextContextMenuComponents
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
||||||
import androidx.compose.material.icons.outlined.MoreVert
|
import androidx.compose.material.icons.outlined.MoreVert
|
||||||
@@ -62,7 +59,6 @@ import androidx.compose.material3.TopAppBar
|
|||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.surfaceColorAtElevation
|
import androidx.compose.material3.surfaceColorAtElevation
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.CompositionLocalProvider
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -74,15 +70,12 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.geometry.Rect
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalTextToolbar
|
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.platform.TextToolbar
|
|
||||||
import androidx.compose.ui.platform.TextToolbarStatus
|
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
@@ -149,6 +142,7 @@ fun MessagesHistoryScreen(
|
|||||||
onItalicRequested: () -> Unit = {},
|
onItalicRequested: () -> Unit = {},
|
||||||
onUnderlineRequested: () -> Unit = {},
|
onUnderlineRequested: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
val view = LocalView.current
|
val view = LocalView.current
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val theme = LocalThemeConfig.current
|
val theme = LocalThemeConfig.current
|
||||||
@@ -574,20 +568,42 @@ fun MessagesHistoryScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val view = LocalView.current
|
TextField(
|
||||||
val textToolbar = remember {
|
modifier = Modifier
|
||||||
CustomTextToolbar(
|
.weight(1f)
|
||||||
view = view,
|
.addTextContextMenuComponents {
|
||||||
onBoldRequested = onBoldRequested,
|
separator()
|
||||||
onItalicRequested = onItalicRequested,
|
|
||||||
onUnderlineRequested = onUnderlineRequested,
|
item(
|
||||||
onLinkRequested = {}
|
key = "Bold",
|
||||||
)
|
label = context.getString(UiR.string.bold)
|
||||||
|
) {
|
||||||
|
onBoldRequested()
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
item(
|
||||||
|
key = "Italic",
|
||||||
|
label = context.getString(UiR.string.italic)
|
||||||
|
) {
|
||||||
|
onItalicRequested()
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
item(
|
||||||
|
key = "Underline",
|
||||||
|
label = context.getString(UiR.string.underline)
|
||||||
|
) {
|
||||||
|
onUnderlineRequested()
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
item(
|
||||||
|
key = "Link",
|
||||||
|
label = context.getString(UiR.string.link)
|
||||||
|
) {
|
||||||
|
close()
|
||||||
}
|
}
|
||||||
|
|
||||||
CompositionLocalProvider(LocalTextToolbar provides textToolbar) {
|
separator()
|
||||||
TextField(
|
},
|
||||||
modifier = Modifier.weight(1f),
|
|
||||||
value = screenState.message,
|
value = screenState.message,
|
||||||
onValueChange = onMessageInputChanged,
|
onValueChange = onMessageInputChanged,
|
||||||
colors = TextFieldDefaults.colors(
|
colors = TextFieldDefaults.colors(
|
||||||
@@ -604,7 +620,7 @@ fun MessagesHistoryScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val attachmentRotation = remember { Animatable(0f) }
|
val attachmentRotation = remember { Animatable(0f) }
|
||||||
@@ -717,242 +733,3 @@ fun MessagesHistoryScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CustomTextToolbar(
|
|
||||||
private val view: View,
|
|
||||||
private var onBoldRequested: (() -> Unit)? = null,
|
|
||||||
private var onItalicRequested: (() -> Unit)? = null,
|
|
||||||
private var onUnderlineRequested: (() -> Unit)? = null,
|
|
||||||
private var onLinkRequested: (() -> Unit)? = null
|
|
||||||
) : TextToolbar {
|
|
||||||
private var actionMode: android.view.ActionMode? = null
|
|
||||||
private val textActionModeCallback: TextActionModeCallback =
|
|
||||||
TextActionModeCallback(onActionModeDestroy = { actionMode = null })
|
|
||||||
override var status: TextToolbarStatus = TextToolbarStatus.Hidden
|
|
||||||
private set
|
|
||||||
|
|
||||||
override fun showMenu(
|
|
||||||
rect: Rect,
|
|
||||||
onCopyRequested: (() -> Unit)?,
|
|
||||||
onPasteRequested: (() -> Unit)?,
|
|
||||||
onCutRequested: (() -> Unit)?,
|
|
||||||
onSelectAllRequested: (() -> Unit)?,
|
|
||||||
onAutofillRequested: (() -> Unit)?
|
|
||||||
) {
|
|
||||||
textActionModeCallback.rect = rect
|
|
||||||
textActionModeCallback.onCopyRequested = onCopyRequested
|
|
||||||
textActionModeCallback.onCutRequested = onCutRequested
|
|
||||||
textActionModeCallback.onPasteRequested = onPasteRequested
|
|
||||||
textActionModeCallback.onSelectAllRequested = onSelectAllRequested
|
|
||||||
textActionModeCallback.onAutofillRequested = onAutofillRequested
|
|
||||||
textActionModeCallback.onBoldRequested = onBoldRequested
|
|
||||||
textActionModeCallback.onItalicRequested = onItalicRequested
|
|
||||||
textActionModeCallback.onUnderlineRequested = onUnderlineRequested
|
|
||||||
textActionModeCallback.onLinkRequested = onLinkRequested
|
|
||||||
|
|
||||||
if (actionMode == null) {
|
|
||||||
status = TextToolbarStatus.Shown
|
|
||||||
actionMode =
|
|
||||||
TextToolbarHelperMethods.startActionMode(
|
|
||||||
view,
|
|
||||||
FloatingTextActionModeCallback(textActionModeCallback),
|
|
||||||
android.view.ActionMode.TYPE_FLOATING
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
actionMode?.invalidate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showMenu(
|
|
||||||
rect: Rect,
|
|
||||||
onCopyRequested: (() -> Unit)?,
|
|
||||||
onPasteRequested: (() -> Unit)?,
|
|
||||||
onCutRequested: (() -> Unit)?,
|
|
||||||
onSelectAllRequested: (() -> Unit)?
|
|
||||||
) {
|
|
||||||
showMenu(
|
|
||||||
rect = rect,
|
|
||||||
onCopyRequested = onCopyRequested,
|
|
||||||
onPasteRequested = onPasteRequested,
|
|
||||||
onCutRequested = onCutRequested,
|
|
||||||
onSelectAllRequested = onSelectAllRequested,
|
|
||||||
onAutofillRequested = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hide() {
|
|
||||||
status = TextToolbarStatus.Hidden
|
|
||||||
actionMode?.finish()
|
|
||||||
actionMode = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is here to ensure that the classes that use this API will get verified and can be AOT
|
|
||||||
* compiled. It is expected that this class will soft-fail verification, but the classes which use
|
|
||||||
* this method will pass.
|
|
||||||
*/
|
|
||||||
internal object TextToolbarHelperMethods {
|
|
||||||
fun startActionMode(
|
|
||||||
view: View,
|
|
||||||
actionModeCallback: android.view.ActionMode.Callback,
|
|
||||||
type: Int
|
|
||||||
): android.view.ActionMode? {
|
|
||||||
return view.startActionMode(actionModeCallback, type)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun invalidateContentRect(actionMode: android.view.ActionMode) {
|
|
||||||
actionMode.invalidateContentRect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class FloatingTextActionModeCallback(private val callback: TextActionModeCallback) :
|
|
||||||
android.view.ActionMode.Callback2() {
|
|
||||||
override fun onActionItemClicked(mode: android.view.ActionMode?, item: MenuItem?): Boolean {
|
|
||||||
return callback.onActionItemClicked(mode, item)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
|
|
||||||
return callback.onCreateActionMode(mode, menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPrepareActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
|
|
||||||
return callback.onPrepareActionMode(mode, menu)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyActionMode(mode: android.view.ActionMode?) {
|
|
||||||
callback.onDestroyActionMode()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onGetContentRect(
|
|
||||||
mode: android.view.ActionMode?,
|
|
||||||
view: View?,
|
|
||||||
outRect: android.graphics.Rect?
|
|
||||||
) {
|
|
||||||
val rect = callback.rect
|
|
||||||
outRect?.set(rect.left.toInt(), rect.top.toInt(), rect.right.toInt(), rect.bottom.toInt())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TextActionModeCallback(
|
|
||||||
val onActionModeDestroy: (() -> Unit)? = null,
|
|
||||||
var rect: Rect = Rect.Zero,
|
|
||||||
var onCopyRequested: (() -> Unit)? = null,
|
|
||||||
var onPasteRequested: (() -> Unit)? = null,
|
|
||||||
var onCutRequested: (() -> Unit)? = null,
|
|
||||||
var onSelectAllRequested: (() -> Unit)? = null,
|
|
||||||
var onAutofillRequested: (() -> Unit)? = null,
|
|
||||||
var onBoldRequested: (() -> Unit)? = null,
|
|
||||||
var onItalicRequested: (() -> Unit)? = null,
|
|
||||||
var onUnderlineRequested: (() -> Unit)? = null,
|
|
||||||
var onLinkRequested: (() -> Unit)? = null
|
|
||||||
) {
|
|
||||||
fun onCreateActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
|
|
||||||
requireNotNull(menu) { "onCreateActionMode requires a non-null menu" }
|
|
||||||
requireNotNull(mode) { "onCreateActionMode requires a non-null mode" }
|
|
||||||
|
|
||||||
onCopyRequested?.let { addMenuItem(menu, MenuItemOption.Copy) }
|
|
||||||
onPasteRequested?.let { addMenuItem(menu, MenuItemOption.Paste) }
|
|
||||||
onCutRequested?.let { addMenuItem(menu, MenuItemOption.Cut) }
|
|
||||||
onSelectAllRequested?.let { addMenuItem(menu, MenuItemOption.SelectAll) }
|
|
||||||
if (onAutofillRequested != null && Build.VERSION.SDK_INT >= 26) {
|
|
||||||
addMenuItem(menu, MenuItemOption.Autofill)
|
|
||||||
}
|
|
||||||
onBoldRequested?.let { addMenuItem(menu, MenuItemOption.Bold) }
|
|
||||||
onItalicRequested?.let { addMenuItem(menu, MenuItemOption.Italic) }
|
|
||||||
onUnderlineRequested?.let { addMenuItem(menu, MenuItemOption.Underline) }
|
|
||||||
onLinkRequested?.let { addMenuItem(menu, MenuItemOption.Link) }
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// this method is called to populate new menu items when the actionMode was invalidated
|
|
||||||
fun onPrepareActionMode(mode: android.view.ActionMode?, menu: Menu?): Boolean {
|
|
||||||
if (mode == null || menu == null) return false
|
|
||||||
updateMenuItems(menu)
|
|
||||||
// should return true so that new menu items are populated
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onActionItemClicked(mode: android.view.ActionMode?, item: MenuItem?): Boolean {
|
|
||||||
when (item!!.itemId) {
|
|
||||||
MenuItemOption.Copy.ordinal -> onCopyRequested?.invoke()
|
|
||||||
MenuItemOption.Paste.ordinal -> onPasteRequested?.invoke()
|
|
||||||
MenuItemOption.Cut.ordinal -> onCutRequested?.invoke()
|
|
||||||
MenuItemOption.SelectAll.ordinal -> onSelectAllRequested?.invoke()
|
|
||||||
MenuItemOption.Autofill.ordinal -> onAutofillRequested?.invoke()
|
|
||||||
MenuItemOption.Bold.ordinal -> onBoldRequested?.invoke()
|
|
||||||
MenuItemOption.Italic.ordinal -> onItalicRequested?.invoke()
|
|
||||||
MenuItemOption.Underline.ordinal -> onUnderlineRequested?.invoke()
|
|
||||||
MenuItemOption.Link.ordinal -> onLinkRequested?.invoke()
|
|
||||||
else -> return false
|
|
||||||
}
|
|
||||||
mode?.finish()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onDestroyActionMode() {
|
|
||||||
onActionModeDestroy?.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
internal fun updateMenuItems(menu: Menu) {
|
|
||||||
addOrRemoveMenuItem(menu, MenuItemOption.Copy, onCopyRequested)
|
|
||||||
addOrRemoveMenuItem(menu, MenuItemOption.Paste, onPasteRequested)
|
|
||||||
addOrRemoveMenuItem(menu, MenuItemOption.Cut, onCutRequested)
|
|
||||||
addOrRemoveMenuItem(menu, MenuItemOption.SelectAll, onSelectAllRequested)
|
|
||||||
addOrRemoveMenuItem(menu, MenuItemOption.Autofill, onAutofillRequested)
|
|
||||||
addOrRemoveMenuItem(menu, MenuItemOption.Bold, onBoldRequested)
|
|
||||||
addOrRemoveMenuItem(menu, MenuItemOption.Italic, onItalicRequested)
|
|
||||||
addOrRemoveMenuItem(menu, MenuItemOption.Underline, onUnderlineRequested)
|
|
||||||
addOrRemoveMenuItem(menu, MenuItemOption.Link, onLinkRequested)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addMenuItem(menu: Menu, item: MenuItemOption) {
|
|
||||||
menu
|
|
||||||
.add(0, item.ordinal, item.order, item.titleResource)
|
|
||||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addOrRemoveMenuItem(menu: Menu, item: MenuItemOption, callback: (() -> Unit)?) {
|
|
||||||
when {
|
|
||||||
callback != null && menu.findItem(item.ordinal) == null -> addMenuItem(menu, item)
|
|
||||||
callback == null && menu.findItem(item.ordinal) != null -> menu.removeItem(item.ordinal)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal enum class MenuItemOption {
|
|
||||||
Copy,
|
|
||||||
Paste,
|
|
||||||
Cut,
|
|
||||||
SelectAll,
|
|
||||||
Autofill,
|
|
||||||
Bold,
|
|
||||||
Italic,
|
|
||||||
Underline,
|
|
||||||
Link;
|
|
||||||
|
|
||||||
val titleResource: Int
|
|
||||||
get() =
|
|
||||||
when (this) {
|
|
||||||
Copy -> android.R.string.copy
|
|
||||||
Paste -> android.R.string.paste
|
|
||||||
Cut -> android.R.string.cut
|
|
||||||
SelectAll -> android.R.string.selectAll
|
|
||||||
Autofill ->
|
|
||||||
if (Build.VERSION.SDK_INT <= 26) {
|
|
||||||
UiR.string.autofill
|
|
||||||
} else {
|
|
||||||
android.R.string.autofill
|
|
||||||
}
|
|
||||||
|
|
||||||
Bold -> UiR.string.bold
|
|
||||||
Italic -> UiR.string.italic
|
|
||||||
Underline -> UiR.string.underline
|
|
||||||
Link -> UiR.string.link
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This item will be shown before all items that have order greater than this value. */
|
|
||||||
val order = ordinal
|
|
||||||
}
|
|
||||||
|
|||||||
+4
-4
@@ -33,8 +33,8 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.LayoutDirection
|
import androidx.compose.ui.unit.LayoutDirection
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import dev.chrisbanes.haze.HazeState
|
import dev.chrisbanes.haze.HazeState
|
||||||
import dev.chrisbanes.haze.haze
|
import dev.chrisbanes.haze.hazeEffect
|
||||||
import dev.chrisbanes.haze.hazeChild
|
import dev.chrisbanes.haze.hazeSource
|
||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import dev.chrisbanes.haze.materials.HazeMaterials
|
import dev.chrisbanes.haze.materials.HazeMaterials
|
||||||
import dev.meloda.fast.data.UserConfig
|
import dev.meloda.fast.data.UserConfig
|
||||||
@@ -159,7 +159,7 @@ fun SettingsScreen(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.then(
|
.then(
|
||||||
if (themeConfig.enableBlur) {
|
if (themeConfig.enableBlur) {
|
||||||
Modifier.hazeChild(
|
Modifier.hazeEffect(
|
||||||
state = hazeState,
|
state = hazeState,
|
||||||
style = HazeMaterials.thick()
|
style = HazeMaterials.thick()
|
||||||
)
|
)
|
||||||
@@ -175,7 +175,7 @@ fun SettingsScreen(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.then(
|
.then(
|
||||||
if (themeConfig.enableBlur) {
|
if (themeConfig.enableBlur) {
|
||||||
Modifier.haze(state = hazeState)
|
Modifier.hazeSource(state = hazeState)
|
||||||
} else Modifier
|
} else Modifier
|
||||||
)
|
)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ haze = "1.6.4"
|
|||||||
kotlin = "2.1.21"
|
kotlin = "2.1.21"
|
||||||
ksp = "2.1.21-2.0.2"
|
ksp = "2.1.21-2.0.2"
|
||||||
|
|
||||||
compose-bom = "2025.06.01"
|
compose-bom = "2025.06.00"
|
||||||
koin = "4.1.0"
|
koin = "4.1.0"
|
||||||
|
|
||||||
accompanist = "0.37.3"
|
accompanist = "0.37.3"
|
||||||
@@ -68,7 +68,8 @@ nanokt-jvm = { module = "com.conena.nanokt:nanokt-jvm", version.ref = "nanokt" }
|
|||||||
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }
|
androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "androidx-navigation" }
|
||||||
kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
|
kotlin-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
|
||||||
|
|
||||||
compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" }
|
compose-bom = { module = "androidx.compose:compose-bom-alpha", version.ref = "compose-bom" }
|
||||||
|
compose-material-icons = { module = "androidx.compose.material:material-icons-core" }
|
||||||
compose-material3 = { module = "androidx.compose.material3:material3" }
|
compose-material3 = { module = "androidx.compose.material3:material3" }
|
||||||
compose-ui = { module = "androidx.compose.ui:ui" }
|
compose-ui = { module = "androidx.compose.ui:ui" }
|
||||||
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
|
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
|
||||||
@@ -95,6 +96,7 @@ room-gradlePlugin = { group = "androidx.room", name = "room-gradle-plugin", vers
|
|||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
compose = [
|
compose = [
|
||||||
|
"compose-material-icons",
|
||||||
"compose-material3",
|
"compose-material3",
|
||||||
"compose-material3-windowsize",
|
"compose-material3-windowsize",
|
||||||
"compose-ui",
|
"compose-ui",
|
||||||
|
|||||||
Reference in New Issue
Block a user