mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Add a button to clear clipboard history
This commit is contained in:
parent
1ae29aa9f1
commit
ed550eec4b
@ -6,7 +6,12 @@ import android.view.View
|
||||
import android.view.inputmethod.InputConnection
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import org.futo.inputmethod.latin.uix.theme.ThemeOption
|
||||
import java.util.Locale
|
||||
@ -17,6 +22,11 @@ interface ActionInputTransaction {
|
||||
fun cancel()
|
||||
}
|
||||
|
||||
data class DialogRequestItem(
|
||||
val option: String,
|
||||
val onClick: () -> Unit
|
||||
)
|
||||
|
||||
interface KeyboardManagerForAction {
|
||||
fun getContext(): Context
|
||||
fun getLifecycleScope(): LifecycleCoroutineScope
|
||||
@ -48,6 +58,8 @@ interface KeyboardManagerForAction {
|
||||
|
||||
fun overrideInputConnection(inputConnection: InputConnection)
|
||||
fun unsetInputConnection()
|
||||
|
||||
fun requestDialog(text: String, options: List<DialogRequestItem>, onCancel: () -> Unit)
|
||||
}
|
||||
|
||||
interface ActionWindow {
|
||||
@ -57,6 +69,14 @@ interface ActionWindow {
|
||||
@Composable
|
||||
fun WindowContents(keyboardShown: Boolean)
|
||||
|
||||
@Composable
|
||||
fun WindowTitleBar(rowScope: RowScope) {
|
||||
with(rowScope) {
|
||||
Text(windowName(), modifier = Modifier.align(Alignment.CenterVertically))
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
}
|
||||
}
|
||||
|
||||
fun close()
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,9 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.IconButtonDefaults
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
@ -61,7 +61,6 @@ import androidx.compose.ui.graphics.drawscope.translate
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
@ -674,7 +673,7 @@ fun ActionBar(
|
||||
|
||||
@Composable
|
||||
fun ActionWindowBar(
|
||||
windowName: String,
|
||||
windowTitleBar: @Composable RowScope.() -> Unit,
|
||||
canExpand: Boolean,
|
||||
onBack: () -> Unit,
|
||||
onExpand: () -> Unit
|
||||
@ -693,13 +692,9 @@ fun ActionWindowBar(
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
windowName,
|
||||
style = Typography.titleMedium,
|
||||
modifier = Modifier.align(CenterVertically)
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1.0f))
|
||||
CompositionLocalProvider(LocalTextStyle provides Typography.titleMedium) {
|
||||
windowTitleBar()
|
||||
}
|
||||
|
||||
if(canExpand) {
|
||||
IconButton(onClick = onExpand) {
|
||||
|
@ -46,7 +46,6 @@ import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
@ -70,6 +69,7 @@ import org.futo.inputmethod.latin.uix.actions.AllActions
|
||||
import org.futo.inputmethod.latin.uix.actions.EmojiAction
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingsActivity
|
||||
import org.futo.inputmethod.latin.uix.theme.ThemeOption
|
||||
import org.futo.inputmethod.latin.uix.theme.Typography
|
||||
import org.futo.inputmethod.latin.uix.theme.UixThemeAuto
|
||||
import org.futo.inputmethod.latin.uix.theme.UixThemeWrapper
|
||||
import org.futo.inputmethod.updates.DISABLE_UPDATE_REMINDER
|
||||
@ -236,6 +236,11 @@ class UixActionKeyboardManager(val uixManager: UixManager, val latinIME: LatinIM
|
||||
latinIME.latinIMELegacy.mSettings.current)
|
||||
}
|
||||
|
||||
override fun requestDialog(text: String, options: List<DialogRequestItem>, onCancel: () -> Unit) {
|
||||
uixManager.activeDialogRequest.value = ActiveDialogRequest(text, options, onCancel)
|
||||
uixManager.activeDialogRequestDismissed.value = false
|
||||
}
|
||||
|
||||
override fun announce(s: String) {
|
||||
AccessibilityUtils.init(getContext())
|
||||
if(AccessibilityUtils.getInstance().isAccessibilityEnabled) {
|
||||
@ -244,6 +249,12 @@ class UixActionKeyboardManager(val uixManager: UixManager, val latinIME: LatinIM
|
||||
}
|
||||
}
|
||||
|
||||
data class ActiveDialogRequest(
|
||||
val text: String,
|
||||
val options: List<DialogRequestItem>,
|
||||
val onCancel: () -> Unit
|
||||
)
|
||||
|
||||
class UixManager(private val latinIME: LatinIME) {
|
||||
private var shouldShowSuggestionStrip: Boolean = true
|
||||
private var suggestedWords: SuggestedWords? = null
|
||||
@ -372,7 +383,7 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
onBack = { returnBackToMainKeyboardViewFromAction() },
|
||||
canExpand = currWindowAction!!.canShowKeyboard,
|
||||
onExpand = { toggleExpandAction() },
|
||||
windowName = windowImpl.windowName()
|
||||
windowTitleBar = { windowImpl.WindowTitleBar(this) }
|
||||
)
|
||||
}
|
||||
|
||||
@ -404,18 +415,18 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
}
|
||||
}
|
||||
|
||||
private val wordBeingForgotten: MutableState<SuggestedWordInfo?> = mutableStateOf(null)
|
||||
private val forgetWordDismissed: MutableState<Boolean> = mutableStateOf(true)
|
||||
val activeDialogRequest: MutableState<ActiveDialogRequest?> = mutableStateOf(null)
|
||||
val activeDialogRequestDismissed: MutableState<Boolean> = mutableStateOf(true)
|
||||
|
||||
@Composable
|
||||
fun BoxScope.ForgetWordDialog() {
|
||||
AnimatedVisibility(
|
||||
visible = !forgetWordDismissed.value,
|
||||
visible = !activeDialogRequestDismissed.value,
|
||||
modifier = Modifier.matchParentSize(),
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut()
|
||||
) {
|
||||
if (wordBeingForgotten.value != null) {
|
||||
if (activeDialogRequest.value != null) {
|
||||
Box(modifier = Modifier.matchParentSize()) {
|
||||
Surface(
|
||||
color = Color.Black.copy(alpha = 0.66f),
|
||||
@ -423,50 +434,34 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
.matchParentSize()
|
||||
.pointerInput(Unit) {
|
||||
this.detectTapGestures(onPress = {
|
||||
forgetWordDismissed.value = true
|
||||
activeDialogRequestDismissed.value = true
|
||||
activeDialogRequest.value?.onCancel?.invoke()
|
||||
})
|
||||
}
|
||||
) { }
|
||||
|
||||
Surface(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
color = MaterialTheme.colorScheme.primaryContainer,
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Text(
|
||||
stringResource(
|
||||
R.string.blacklist_from_suggestions,
|
||||
wordBeingForgotten.value?.mWord!!
|
||||
))
|
||||
Box(modifier = Modifier.matchParentSize().padding(8.dp)) {
|
||||
Surface(
|
||||
shape = RoundedCornerShape(16.dp),
|
||||
color = MaterialTheme.colorScheme.primaryContainer,
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
Text(
|
||||
activeDialogRequest.value?.text ?: "",
|
||||
style = Typography.bodyMedium
|
||||
)
|
||||
|
||||
Row {
|
||||
TextButton(
|
||||
onClick = {
|
||||
forgetWordDismissed.value = true
|
||||
}
|
||||
) {
|
||||
Text(stringResource(R.string.cancel))
|
||||
}
|
||||
|
||||
TextButton(
|
||||
onClick = {
|
||||
latinIME.forceForgetWord(wordBeingForgotten.value!!)
|
||||
forgetWordDismissed.value = true
|
||||
}
|
||||
) {
|
||||
Text(stringResource(R.string.blacklist))
|
||||
}
|
||||
|
||||
if(wordBeingForgotten.value!!.mKindAndFlags == SuggestedWordInfo.KIND_EMOJI_SUGGESTION) {
|
||||
TextButton(
|
||||
onClick = {
|
||||
runBlocking { latinIME.setSetting(SHOW_EMOJI_SUGGESTIONS, false) }
|
||||
forgetWordDismissed.value = true
|
||||
latinIME.refreshSuggestions()
|
||||
Row {
|
||||
activeDialogRequest.value?.options?.forEach {
|
||||
TextButton(
|
||||
onClick = {
|
||||
it.onClick()
|
||||
activeDialogRequestDismissed.value = true
|
||||
}
|
||||
) {
|
||||
Text(it.option)
|
||||
}
|
||||
) {
|
||||
Text(stringResource(R.string.disable_emoji))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -670,8 +665,25 @@ class UixManager(private val latinIME: LatinIME) {
|
||||
}
|
||||
|
||||
fun requestForgetWord(suggestedWordInfo: SuggestedWords.SuggestedWordInfo) {
|
||||
wordBeingForgotten.value = suggestedWordInfo
|
||||
forgetWordDismissed.value = false
|
||||
keyboardManagerForAction.requestDialog(
|
||||
latinIME.getString(R.string.blacklist_from_suggestions, suggestedWordInfo.mWord),
|
||||
listOf(
|
||||
DialogRequestItem(latinIME.getString(R.string.cancel)) { },
|
||||
DialogRequestItem(latinIME.getString(R.string.blacklist)) {
|
||||
latinIME.forceForgetWord(suggestedWordInfo)
|
||||
},
|
||||
) + if(suggestedWordInfo.mKindAndFlags == SuggestedWordInfo.KIND_EMOJI_SUGGESTION) {
|
||||
listOf(
|
||||
DialogRequestItem(latinIME.getString(R.string.disable_emoji)) {
|
||||
runBlocking { latinIME.setSetting(SHOW_EMOJI_SUGGESTIONS, false) }
|
||||
latinIME.refreshSuggestions()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
listOf()
|
||||
},
|
||||
{ }
|
||||
)
|
||||
|
||||
val v = latinIME.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator?
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
|
@ -13,6 +13,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
@ -54,6 +55,7 @@ import org.futo.inputmethod.latin.R
|
||||
import org.futo.inputmethod.latin.common.Constants
|
||||
import org.futo.inputmethod.latin.uix.Action
|
||||
import org.futo.inputmethod.latin.uix.ActionWindow
|
||||
import org.futo.inputmethod.latin.uix.DialogRequestItem
|
||||
import org.futo.inputmethod.latin.uix.PersistentActionState
|
||||
import org.futo.inputmethod.latin.uix.PersistentStateInitialization
|
||||
import org.futo.inputmethod.latin.uix.SettingsKey
|
||||
@ -100,7 +102,8 @@ fun ClipboardEntryView(modifier: Modifier, clipboardEntry: ClipboardEntry, onPas
|
||||
Surface(
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
border = BorderStroke(2.dp, MaterialTheme.colorScheme.outlineVariant),
|
||||
modifier = modifier.padding(2.dp)
|
||||
modifier = modifier
|
||||
.padding(2.dp)
|
||||
.combinedClickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = androidx.compose.material.ripple.rememberRipple(),
|
||||
@ -360,6 +363,62 @@ val ClipboardHistoryAction = Action(
|
||||
return stringResource(R.string.clipboard_manager_action_title)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun WindowTitleBar(rowScope: RowScope) {
|
||||
super.WindowTitleBar(rowScope)
|
||||
|
||||
val clipboardHistory = useDataStore(ClipboardHistoryEnabled, blocking = true)
|
||||
if(!clipboardHistory.value) return
|
||||
|
||||
IconButton(onClick = {
|
||||
val numUnpinnedItems = clipboardHistoryManager.clipboardHistory.count { !it.pinned }
|
||||
if(clipboardHistoryManager.clipboardHistory.size == 0) {
|
||||
manager.requestDialog(
|
||||
"There are no items to clear. Disable clipboard history?",
|
||||
listOf(
|
||||
DialogRequestItem("Cancel") {},
|
||||
DialogRequestItem("Disable") {
|
||||
clipboardHistory.setValue(false)
|
||||
},
|
||||
),
|
||||
{}
|
||||
)
|
||||
} else if(numUnpinnedItems == 0) {
|
||||
manager.requestDialog(
|
||||
"There are no unpinned items to clear. Unpin all items?",
|
||||
listOf(
|
||||
DialogRequestItem("Cancel") {},
|
||||
DialogRequestItem("Unpin") {
|
||||
clipboardHistoryManager.clipboardHistory.toList().forEach {
|
||||
if(it.pinned) {
|
||||
clipboardHistoryManager.onPin(it)
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
{}
|
||||
)
|
||||
} else {
|
||||
manager.requestDialog(
|
||||
"Clear all unpinned items?",
|
||||
listOf(
|
||||
DialogRequestItem("Cancel") {},
|
||||
DialogRequestItem("Clear") {
|
||||
clipboardHistoryManager.clipboardHistory.toList().forEach {
|
||||
if (!it.pinned) {
|
||||
clipboardHistoryManager.onRemove(it)
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
{}
|
||||
)
|
||||
}
|
||||
}) {
|
||||
Icon(painterResource(id = R.drawable.close), contentDescription = "Clear clipboard")
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun WindowContents(keyboardShown: Boolean) {
|
||||
val view = LocalView.current
|
||||
@ -370,7 +429,9 @@ val ClipboardHistoryAction = Action(
|
||||
ParagraphText("Clipboard history is not enabled. To save clipboard items, you can enable clipboard history. This will keep up to 25 items for 3 days unless pinned. Passwords and other items marked sensitive are excluded from history.")
|
||||
Button(onClick = {
|
||||
clipboardHistory.setValue(true)
|
||||
}, modifier = Modifier.padding(8.dp).fillMaxWidth()) {
|
||||
}, modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.fillMaxWidth()) {
|
||||
Text("Enable Clipboard History")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user