Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

emoji search while typing popup and updates #134

Merged
merged 3 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ The Java and JNI parts are built here: https://github.com/zoff99/ffmpeg_av_jni
Java can do Notifications on Windows properly, but on macOS and Linux a native library is needed.<br>
The Java and JNI parts are built here: https://github.com/zoff99/jni_notifications

## arm64 macOS toxcore lib
The lib for arm64 macOS is built on https://codemagic.io/

<br>
Any use of this project's code by GitHub Copilot, past or present, is done
without our permission. We do not consent to GitHub's use of this project's
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ dependencies {
implementation(compose.materialIconsExtended)
//
//
implementation("org.xerial:sqlite-jdbc:3.44.1.0")
implementation("org.xerial:sqlite-jdbc:3.45.1.0")
implementation("ca.gosyer:kotlin-multiplatform-appdirs:1.1.1")
implementation("com.sksamuel.scrimage:scrimage-core:4.1.1")
implementation("com.sksamuel.scrimage:scrimage-webp:4.1.1")
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ val MYTOXID_WIDTH = 200.dp
val MYTOXID_HEIGHT = 50.dp
const val MSG_TEXT_FONT_SIZE_MIXED = 14.0f
const val MSG_TEXT_FONT_SIZE_EMOJI_ONLY = 55.0f
const val MAX_EMOJI_POP_SEARCH_LEN = 20
const val MAX_EMOJI_POP_RESULT = 15
const val MAX_ONE_ON_ONE_MESSAGES_TO_SHOW = 20000
const val MAX_GROUP_MESSAGES_TO_SHOW = 20000
const val SNACKBAR_TOAST_MS_DURATION: Long = 1000
Expand Down
118 changes: 104 additions & 14 deletions src/main/kotlin/com/zoffcc/applications/trifa2/GroupSendMessage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
Expand All @@ -51,12 +52,15 @@ import androidx.compose.ui.input.key.isShiftPressed
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.key.type
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.PopupProperties
import com.vanniktech.emoji.search.SearchEmojiManager
import com.zoffcc.applications.trifa.Log
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
Expand All @@ -67,13 +71,99 @@ private const val TAG = "trifa.SendGroupMessage"
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun GroupSendMessage(focusRequester: FocusRequester, selectedGroupId: String?, sendGroupMessage: (String) -> Unit) {
var inputText by remember { mutableStateOf("") }
var inputTextV by remember {
val textFieldValue = TextFieldValue(text = "")
mutableStateOf(textFieldValue)
}
LaunchedEffect(selectedGroupId)
{
// Log.i(TAG, "selected group changed, reset input text")
inputText = ""
inputTextV = TextFieldValue(text = "")
}
val emoji_typing_box_offset_x_px_init = 2.dp.DpAsPx.toInt()
var show_emoji_popup by remember { mutableStateOf(false) }
var show_typing_emoji_popup by remember { mutableStateOf(true) }
var emoji_typing_box_offset_x_px by remember { mutableStateOf(emoji_typing_box_offset_x_px_init) }
var emoji_typing_box_offset_y_px by remember { mutableStateOf(0) }
emoji_typing_box_offset_x_px = emoji_typing_box_offset_x_px_init
emoji_typing_box_offset_y_px = -(70.dp).DpAsPx.toInt()
val single_letter = 5.dp.DpAsPx.toInt()
if (show_typing_emoji_popup)
{
Popup(alignment = Alignment.BottomStart,
properties = PopupProperties(focusable = false, dismissOnClickOutside = true),
onDismissRequest = {},
offset = IntOffset(emoji_typing_box_offset_x_px, emoji_typing_box_offset_y_px)) {
Row(
Modifier
.size(305.dp, 40.dp)
.randomDebugBorder()
.padding(top = 1.dp, bottom = 1.dp)
.clip(RoundedCornerShape(18.dp, 18.dp, 18.dp, 18.dp))
.background(MaterialTheme.colors.background)
)
{
var li = -1
try {
li = inputTextV.text.lastIndexOf(string = ":", ignoreCase = true)
} catch(_: Exception)
{}
if (li != -1)
{
var emoji_search_str = ""
try {
if ((inputTextV.text.length - li) <= MAX_EMOJI_POP_SEARCH_LEN)
{
emoji_search_str = inputTextV.text.takeLast(inputTextV.text.length - li - 1)
}
} catch(_: Exception)
{}
SearchEmojiManager().search(query = emoji_search_str).take(MAX_EMOJI_POP_RESULT)
.forEach {
Row(modifier = Modifier.fillMaxWidth().height(40.dp).randomDebugBorder()) {
val emojistr = it.emoji.unicode
val placeholder = "?"
var curtext by remember { mutableStateOf(placeholder) }
val scope = rememberCoroutineScope()
Tooltip(text = it.shortcode) {
Log.i(TAG, "" + it.shortcode + " " + emojistr)
IconButton(modifier = Modifier.width(40.dp).height(40.dp),
onClick = {
var li2 = -1
try
{
li2 = inputTextV.text.lastIndexOf(string = ":", ignoreCase = true)
} catch (_: Exception)
{
}
if (li2 != -1)
{
try
{
if ((inputTextV.text.length - li2) <= MAX_EMOJI_POP_SEARCH_LEN)
{
val new_input_text = inputTextV.text.take(li2) + emojistr
val new_selection = TextRange(new_input_text.length)
inputTextV = TextFieldValue(text = new_input_text, selection = new_selection)
}
} catch (_: Exception)
{
}
}
}) {
Text(text = curtext, color = Color.Black, fontSize = 30.sp, maxLines = 1)
scope.launch {
delay(62)
curtext = emojistr
}
}
}
}
}
}
}
}
}
TextField(
modifier = Modifier.fillMaxWidth()
.background(MaterialTheme.colors.background)
Expand All @@ -82,18 +172,18 @@ fun GroupSendMessage(focusRequester: FocusRequester, selectedGroupId: String?, s
.onPreviewKeyEvent {
when {
(!it.isMetaPressed && !it.isAltPressed && !it.isCtrlPressed && !it.isShiftPressed && it.key == Key.Enter && it.type == KeyEventType.KeyDown) -> {
if (inputText.isNotEmpty())
if (inputTextV.text.isNotEmpty())
{
sendGroupMessage(inputText)
inputText = ""
sendGroupMessage(inputTextV.text)
inputTextV = TextFieldValue(text = "")
}
true
}
(!it.isMetaPressed && !it.isAltPressed && !it.isCtrlPressed && !it.isShiftPressed && it.key == Key.NumPadEnter && it.type == KeyEventType.KeyDown) -> {
if (inputText.isNotEmpty())
if (inputTextV.text.isNotEmpty())
{
sendGroupMessage(inputText)
inputText = ""
sendGroupMessage(inputTextV.text)
inputTextV = TextFieldValue(text = "")
}
true
}
Expand All @@ -111,21 +201,21 @@ fun GroupSendMessage(focusRequester: FocusRequester, selectedGroupId: String?, s
capitalization = KeyboardCapitalization.None,
autoCorrect = false,
),
value = inputText,
value = inputTextV,
placeholder = {
Text(text = "Type Group Message...", fontSize = 14.sp)
},
onValueChange = {
inputText = it
inputTextV = it
},
trailingIcon = {
if (inputText.isNotEmpty()) {
if (inputTextV.text.isNotEmpty()) {
Row() {
Row(
modifier = Modifier
.clickable {
sendGroupMessage(inputText)
inputText = ""
sendGroupMessage(inputTextV.text)
inputTextV = TextFieldValue(text = "")
}
.padding(10.dp),
verticalAlignment = Alignment.CenterVertically,
Expand Down Expand Up @@ -231,7 +321,7 @@ fun GroupSendMessage(focusRequester: FocusRequester, selectedGroupId: String?, s
val scope = rememberCoroutineScope()
Tooltip(text = if (emojistr.name.isEmpty()) "" else emojistr.name) {
IconButton(modifier = Modifier.width(40.dp).height(40.dp),
onClick = { inputText = inputText + it[k].char }) {
onClick = { inputTextV = TextFieldValue(text = inputTextV.text + it[k].char) }) {
Text(text = curtext, color = Color.Black, fontSize = 30.sp, maxLines = 1)
scope.launch {
delay(62)
Expand Down
Loading
Loading