mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-21 01:30:33 +02:00
Paste text in calculator
This commit is contained in:
parent
3bc9891b81
commit
684d7f2d9a
@ -79,7 +79,8 @@ private fun CalculatorScreen(
|
||||
text = uiState.input,
|
||||
selection = TextRange(uiState.selection.first, uiState.selection.last)
|
||||
),
|
||||
onCursorChange = onCursorChange
|
||||
onCursorChange = onCursorChange,
|
||||
pasteCallback = addSymbol
|
||||
)
|
||||
AnimatedVisibility(visible = uiState.output.isNotEmpty()) {
|
||||
Text(
|
||||
|
@ -121,6 +121,8 @@ internal class CalculatorViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun onCursorChange(selection: IntRange) {
|
||||
// When we paste, selection is set to the length of the pasted text (start and end)
|
||||
if (selection.first > _input.value.length) return
|
||||
_selection.update { selection }
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Unitto is a unit converter for Android
|
||||
* Copyright (c) 2023 Elshan Agaev
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto.feature.calculator.components
|
||||
|
||||
import android.view.ActionMode
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
@RequiresApi(23)
|
||||
internal class FloatingTextActionModeCallback(
|
||||
private val callback: UnittoActionModeCallback
|
||||
) : ActionMode.Callback2() {
|
||||
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
|
||||
return callback.onActionItemClicked(mode, item)
|
||||
}
|
||||
|
||||
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
return callback.onCreateActionMode(mode, menu)
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
return callback.onPrepareActionMode()
|
||||
}
|
||||
|
||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||
callback.onDestroyActionMode()
|
||||
}
|
||||
|
||||
override fun onGetContentRect(
|
||||
mode: 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()
|
||||
)
|
||||
}
|
||||
}
|
@ -23,7 +23,10 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalTextInputService
|
||||
import androidx.compose.ui.platform.LocalTextToolbar
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import com.sadellie.unitto.core.ui.theme.NumbersTextStyleDisplayLarge
|
||||
@ -32,16 +35,24 @@ import com.sadellie.unitto.core.ui.theme.NumbersTextStyleDisplayLarge
|
||||
internal fun InputTextField(
|
||||
modifier: Modifier,
|
||||
value: TextFieldValue,
|
||||
onCursorChange: (IntRange) -> Unit
|
||||
onCursorChange: (IntRange) -> Unit,
|
||||
pasteCallback: (String) -> Unit
|
||||
) {
|
||||
val clipboardManager = LocalClipboardManager.current
|
||||
CompositionLocalProvider(
|
||||
// FIXME Can't paste if this is null
|
||||
LocalTextInputService provides null
|
||||
LocalTextInputService provides null,
|
||||
LocalTextToolbar provides UnittoTextToolbar(
|
||||
view = LocalView.current,
|
||||
pasteCallback = { pasteCallback(clipboardManager.getText()?.text ?: "") }
|
||||
)
|
||||
) {
|
||||
BasicTextField(
|
||||
modifier = modifier,
|
||||
singleLine = true,
|
||||
value = value,
|
||||
onValueChange = { onCursorChange(it.selection.start..it.selection.end) },
|
||||
onValueChange = {
|
||||
onCursorChange(it.selection.start..it.selection.end)
|
||||
},
|
||||
textStyle = NumbersTextStyleDisplayLarge.copy(
|
||||
textAlign = TextAlign.End,
|
||||
color = MaterialTheme.colorScheme.onBackground
|
||||
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Unitto is a unit converter for Android
|
||||
* Copyright (c) 2023 Elshan Agaev
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto.feature.calculator.components
|
||||
|
||||
import android.view.ActionMode
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
|
||||
private const val MENU_ITEM_COPY = 0
|
||||
private const val MENU_ITEM_PASTE = 1
|
||||
private const val MENU_ITEM_CUT = 2
|
||||
private const val MENU_ITEM_SELECT_ALL = 3
|
||||
|
||||
internal class UnittoActionModeCallback(
|
||||
var rect: Rect = Rect.Zero,
|
||||
var onCopyRequested: (() -> Unit)? = null,
|
||||
var onPasteRequested: (() -> Unit)? = null,
|
||||
var onCutRequested: (() -> Unit)? = null,
|
||||
var onSelectAllRequested: (() -> Unit)? = null
|
||||
) {
|
||||
fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
requireNotNull(menu)
|
||||
requireNotNull(mode)
|
||||
|
||||
onCopyRequested?.let {
|
||||
menu.add(0, MENU_ITEM_COPY, 0, android.R.string.copy)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
||||
}
|
||||
|
||||
onPasteRequested?.let {
|
||||
menu.add(0, MENU_ITEM_PASTE, 1, android.R.string.paste)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
||||
}
|
||||
|
||||
onCutRequested?.let {
|
||||
menu.add(0, MENU_ITEM_CUT, 2, android.R.string.cut)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
||||
}
|
||||
|
||||
onSelectAllRequested?.let {
|
||||
menu.add(0, MENU_ITEM_SELECT_ALL, 3, android.R.string.selectAll)
|
||||
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun onPrepareActionMode(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
|
||||
when (item!!.itemId) {
|
||||
MENU_ITEM_COPY -> onCopyRequested?.invoke()
|
||||
MENU_ITEM_PASTE -> onPasteRequested?.invoke()
|
||||
MENU_ITEM_CUT -> onCutRequested?.invoke()
|
||||
MENU_ITEM_SELECT_ALL -> onSelectAllRequested?.invoke()
|
||||
else -> return false
|
||||
}
|
||||
mode?.finish()
|
||||
return true
|
||||
}
|
||||
|
||||
fun onDestroyActionMode() {}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Unitto is a unit converter for Android
|
||||
* Copyright (c) 2023 Elshan Agaev
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto.feature.calculator.components
|
||||
|
||||
import android.view.ActionMode
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
|
||||
internal class UnittoPrimaryTextActionModeCallback(
|
||||
private val callback: UnittoActionModeCallback
|
||||
) : ActionMode.Callback {
|
||||
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
|
||||
return callback.onActionItemClicked(mode, item)
|
||||
}
|
||||
|
||||
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
return callback.onCreateActionMode(mode, menu)
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
|
||||
return callback.onPrepareActionMode()
|
||||
}
|
||||
|
||||
override fun onDestroyActionMode(mode: ActionMode?) {
|
||||
callback.onDestroyActionMode()
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Unitto is a unit converter for Android
|
||||
* Copyright (c) 2023 Elshan Agaev
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sadellie.unitto.feature.calculator.components
|
||||
|
||||
import android.os.Build
|
||||
import android.view.ActionMode
|
||||
import android.view.View
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.platform.TextToolbar
|
||||
import androidx.compose.ui.platform.TextToolbarStatus
|
||||
|
||||
internal class UnittoTextToolbar(
|
||||
private val view: View,
|
||||
private val pasteCallback: () -> Unit
|
||||
) : TextToolbar {
|
||||
|
||||
private var actionMode: ActionMode? = null
|
||||
private val textActionModeCallback: UnittoActionModeCallback = UnittoActionModeCallback()
|
||||
override var status: TextToolbarStatus = TextToolbarStatus.Hidden
|
||||
private set
|
||||
|
||||
override fun showMenu(
|
||||
rect: Rect,
|
||||
onCopyRequested: (() -> Unit)?,
|
||||
onPasteRequested: (() -> Unit)?,
|
||||
onCutRequested: (() -> Unit)?,
|
||||
onSelectAllRequested: (() -> Unit)?
|
||||
) {
|
||||
textActionModeCallback.rect = rect
|
||||
textActionModeCallback.onCopyRequested = onCopyRequested
|
||||
textActionModeCallback.onCutRequested = onCutRequested
|
||||
textActionModeCallback.onPasteRequested = { pasteCallback(); onPasteRequested?.invoke() }
|
||||
textActionModeCallback.onSelectAllRequested = onSelectAllRequested
|
||||
if (actionMode == null) {
|
||||
status = TextToolbarStatus.Shown
|
||||
actionMode = startActionMode(view, textActionModeCallback)
|
||||
} else {
|
||||
actionMode?.invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
override fun hide() {
|
||||
status = TextToolbarStatus.Hidden
|
||||
actionMode?.finish()
|
||||
actionMode = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun startActionMode(
|
||||
view: View,
|
||||
textActionModeCallback: UnittoActionModeCallback
|
||||
): ActionMode {
|
||||
return if (Build.VERSION.SDK_INT >= 23) {
|
||||
view.startActionMode(
|
||||
FloatingTextActionModeCallback(textActionModeCallback),
|
||||
ActionMode.TYPE_FLOATING
|
||||
)
|
||||
} else {
|
||||
// Old devices use toolbar instead of a floating menu
|
||||
view.startActionMode(
|
||||
UnittoPrimaryTextActionModeCallback(textActionModeCallback)
|
||||
)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user