diff --git a/app/src/main/java/com/bitchat/android/core/ui/utils/ModifierExt.kt b/app/src/main/java/com/bitchat/android/core/ui/utils/ModifierExt.kt new file mode 100644 index 00000000..19dabb57 --- /dev/null +++ b/app/src/main/java/com/bitchat/android/core/ui/utils/ModifierExt.kt @@ -0,0 +1,57 @@ +package com.bitchat.android.core.ui.utils + +import androidx.compose.foundation.clickable +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +fun Modifier.singleOrTripleClickable( + onSingleClick: () -> Unit, + onTripleClick: () -> Unit, + clickTimeThreshold: Long = 300L +): Modifier = composed { + var tapCount by remember { mutableIntStateOf(0) } + var lastTapTime by remember { mutableLongStateOf(0L) } + var singleClickJob by remember { mutableStateOf(null) } + val coroutineScope = rememberCoroutineScope() + + this.clickable { + val currentTime = System.currentTimeMillis() + + if (currentTime - lastTapTime < clickTimeThreshold) { + tapCount++ + } else { + tapCount = 1 + } + + lastTapTime = currentTime + + // Cancel any pending single click action + singleClickJob?.cancel() + singleClickJob = null + + when (tapCount) { + 1 -> { + // Wait to see if more taps come + singleClickJob = coroutineScope.launch { + delay(clickTimeThreshold) + if (tapCount == 1) { + onSingleClick() + } + } + } + 3 -> { + // Triple click detected - execute immediately + onTripleClick() + tapCount = 0 + } + } + + // Reset after threshold if no triple click + if (tapCount > 3) { + tapCount = 0 + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt b/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt index 65e2ee8e..ee9c699d 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatHeader.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.bitchat.android.core.ui.utils.singleOrTripleClickable /** * Header components for ChatScreen @@ -148,8 +149,7 @@ fun ChatHeaderContent( onShowAppInfo: () -> Unit ) { val colorScheme = MaterialTheme.colorScheme - var tripleClickCount by remember { mutableStateOf(0) } - + when { selectedPrivatePeer != null -> { // Private chat header - ensure state synchronization @@ -181,15 +181,8 @@ fun ChatHeaderContent( MainHeader( nickname = nickname, onNicknameChange = viewModel::setNickname, - onTitleClick = { - tripleClickCount++ - if (tripleClickCount >= 3) { - tripleClickCount = 0 - onTripleClick() - } else { - onShowAppInfo() - } - }, + onTitleClick = onShowAppInfo, + onTripleTitleClick = onTripleClick, onSidebarClick = onSidebarClick, viewModel = viewModel ) @@ -345,6 +338,7 @@ private fun MainHeader( nickname: String, onNicknameChange: (String) -> Unit, onTitleClick: () -> Unit, + onTripleTitleClick: () -> Unit, onSidebarClick: () -> Unit, viewModel: ChatViewModel ) { @@ -365,7 +359,10 @@ private fun MainHeader( text = "bitchat*", style = MaterialTheme.typography.headlineSmall, color = colorScheme.primary, - modifier = Modifier.clickable { onTitleClick() } + modifier = Modifier.singleOrTripleClickable( + onSingleClick = onTitleClick, + onTripleClick = onTripleTitleClick + ) ) Spacer(modifier = Modifier.width(8.dp))