mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
@@ -19,6 +19,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
android:enableOnBackInvokedCallback="true"
|
||||||
android:theme="@style/Theme.FromChat.SplashScreen"
|
android:theme="@style/Theme.FromChat.SplashScreen"
|
||||||
android:windowSoftInputMode="adjustResize">
|
android:windowSoftInputMode="adjustResize">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|||||||
@@ -1,9 +1,28 @@
|
|||||||
package ru.fromchat.ui
|
package ru.fromchat.ui
|
||||||
|
|
||||||
|
import android.view.HapticFeedbackConstants
|
||||||
import androidx.activity.compose.BackHandler as AndroidBackHandler
|
import androidx.activity.compose.BackHandler as AndroidBackHandler
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.platform.LocalView
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
actual fun BackHandler(enabled: Boolean, onBack: () -> Unit) {
|
actual fun BackHandler(enabled: Boolean, onBack: () -> Unit) {
|
||||||
AndroidBackHandler(enabled = enabled, onBack = onBack)
|
AndroidBackHandler(enabled = enabled, onBack = onBack)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun rememberHapticFeedbackInternal(): (Int) -> Unit {
|
||||||
|
val view = LocalView.current
|
||||||
|
return remember(view) {
|
||||||
|
{ ordinal ->
|
||||||
|
val constant = when (ordinal) {
|
||||||
|
HapticFeedbackEvent.ProfileOpened.ordinal -> HapticFeedbackConstants.CLOCK_TICK
|
||||||
|
HapticFeedbackEvent.ProfileClosed.ordinal -> HapticFeedbackConstants.CLOCK_TICK
|
||||||
|
HapticFeedbackEvent.MessageSent.ordinal -> HapticFeedbackConstants.CONFIRM
|
||||||
|
else -> HapticFeedbackConstants.CLOCK_TICK
|
||||||
|
}
|
||||||
|
view.performHapticFeedback(constant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,3 +9,6 @@ import androidx.compose.runtime.Composable
|
|||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
expect fun BackHandler(enabled: Boolean, onBack: () -> Unit)
|
expect fun BackHandler(enabled: Boolean, onBack: () -> Unit)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
expect fun rememberHapticFeedbackInternal(): (Int) -> Unit
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package ru.fromchat.ui
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun rememberHapticFeedback(): (HapticFeedbackEvent) -> Unit {
|
||||||
|
val h = rememberHapticFeedbackInternal()
|
||||||
|
return remember(h) { { event: HapticFeedbackEvent -> h(event.ordinal) } }
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package ru.fromchat.ui
|
||||||
|
|
||||||
|
enum class HapticFeedbackEvent {
|
||||||
|
ProfileOpened,
|
||||||
|
ProfileClosed,
|
||||||
|
MessageSent
|
||||||
|
}
|
||||||
@@ -72,7 +72,9 @@ import ru.fromchat.api.WebSocketMessage
|
|||||||
import ru.fromchat.api.WebSocketUpdatesData
|
import ru.fromchat.api.WebSocketUpdatesData
|
||||||
import ru.fromchat.back
|
import ru.fromchat.back
|
||||||
import ru.fromchat.core.Logger
|
import ru.fromchat.core.Logger
|
||||||
|
import ru.fromchat.ui.HapticFeedbackEvent
|
||||||
import ru.fromchat.ui.LocalNavController
|
import ru.fromchat.ui.LocalNavController
|
||||||
|
import ru.fromchat.ui.rememberHapticFeedback
|
||||||
import ru.fromchat.ui.scaleOnPress
|
import ru.fromchat.ui.scaleOnPress
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalHazeMaterialsApi::class)
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalHazeMaterialsApi::class)
|
||||||
@@ -116,6 +118,7 @@ fun ChatScreen(
|
|||||||
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
val haptic = rememberHapticFeedback()
|
||||||
val navController = LocalNavController.current
|
val navController = LocalNavController.current
|
||||||
val profileUserId = panelState.profileUserId
|
val profileUserId = panelState.profileUserId
|
||||||
val hazeState = rememberHazeState(blurEnabled = true)
|
val hazeState = rememberHazeState(blurEnabled = true)
|
||||||
@@ -389,6 +392,7 @@ fun ChatScreen(
|
|||||||
scope.launch {
|
scope.launch {
|
||||||
panel.sendMessageWithImmediateDisplay(text, replyTo?.id)
|
panel.sendMessageWithImmediateDisplay(text, replyTo?.id)
|
||||||
replyTo = null
|
replyTo = null
|
||||||
|
haptic(HapticFeedbackEvent.MessageSent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inputText = ""
|
inputText = ""
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import ru.fromchat.ui.BackHandler
|
import ru.fromchat.ui.BackHandler
|
||||||
|
import ru.fromchat.ui.HapticFeedbackEvent
|
||||||
|
import ru.fromchat.ui.rememberHapticFeedback
|
||||||
import ru.fromchat.ui.profile.ProfileScreen
|
import ru.fromchat.ui.profile.ProfileScreen
|
||||||
|
|
||||||
private const val TRANSITION_MS = 320
|
private const val TRANSITION_MS = 320
|
||||||
@@ -27,11 +29,13 @@ fun DmContainerScreen(
|
|||||||
) {
|
) {
|
||||||
var showProfile by remember { mutableStateOf(false) }
|
var showProfile by remember { mutableStateOf(false) }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
val haptic = rememberHapticFeedback()
|
||||||
val panel = remember(otherUserId) {
|
val panel = remember(otherUserId) {
|
||||||
DmPanelCache.getOrCreate(otherUserId, scope)
|
DmPanelCache.getOrCreate(otherUserId, scope)
|
||||||
}
|
}
|
||||||
|
|
||||||
BackHandler(enabled = showProfile) {
|
BackHandler(enabled = showProfile) {
|
||||||
|
haptic(HapticFeedbackEvent.ProfileClosed)
|
||||||
showProfile = false
|
showProfile = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +55,10 @@ fun DmContainerScreen(
|
|||||||
DmScreen(
|
DmScreen(
|
||||||
panel = panel,
|
panel = panel,
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
onTitleClick = { showProfile = true },
|
onTitleClick = {
|
||||||
|
haptic(HapticFeedbackEvent.ProfileOpened)
|
||||||
|
showProfile = true
|
||||||
|
},
|
||||||
sharedTransitionScope = this@SharedTransitionLayout,
|
sharedTransitionScope = this@SharedTransitionLayout,
|
||||||
animatedVisibilityScope = this@AnimatedContent,
|
animatedVisibilityScope = this@AnimatedContent,
|
||||||
sharedAvatarKey = sharedAvatarKey
|
sharedAvatarKey = sharedAvatarKey
|
||||||
@@ -59,8 +66,14 @@ fun DmContainerScreen(
|
|||||||
} else {
|
} else {
|
||||||
ProfileScreen(
|
ProfileScreen(
|
||||||
userId = otherUserId,
|
userId = otherUserId,
|
||||||
onBack = { showProfile = false },
|
onBack = {
|
||||||
onChat = { _ -> showProfile = false },
|
haptic(HapticFeedbackEvent.ProfileClosed)
|
||||||
|
showProfile = false
|
||||||
|
},
|
||||||
|
onChat = { _ ->
|
||||||
|
haptic(HapticFeedbackEvent.ProfileClosed)
|
||||||
|
showProfile = false
|
||||||
|
},
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
sharedTransitionScope = this@SharedTransitionLayout,
|
sharedTransitionScope = this@SharedTransitionLayout,
|
||||||
animatedVisibilityScope = this@AnimatedContent,
|
animatedVisibilityScope = this@AnimatedContent,
|
||||||
|
|||||||
@@ -6,3 +6,6 @@ import androidx.compose.runtime.Composable
|
|||||||
actual fun BackHandler(enabled: Boolean, onBack: () -> Unit) {
|
actual fun BackHandler(enabled: Boolean, onBack: () -> Unit) {
|
||||||
// iOS has no system back button; back is handled by navigation.
|
// iOS has no system back button; back is handled by navigation.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
actual fun rememberHapticFeedbackInternal(): (Int) -> Unit = { }
|
||||||
|
|||||||
Reference in New Issue
Block a user