settings reorganization;

implement long press on emoji button for fast text;
some deprecations fixed;
some typos fixed;
etc
This commit is contained in:
2024-12-17 12:53:02 +03:00
parent 82695ccf6f
commit 85cda2065e
28 changed files with 267 additions and 191 deletions
@@ -209,7 +209,7 @@ class MainViewModelImpl(
} }
longPollController.setStateToApply( longPollController.setStateToApply(
if (AppSettings.Debug.longPollInBackground) { if (AppSettings.Experimental.longPollInBackground) {
LongPollState.Background LongPollState.Background
} else { } else {
LongPollState.InApp LongPollState.InApp
@@ -233,7 +233,7 @@ class MainViewModelImpl(
} }
private fun disableBackgroundLongPoll() { private fun disableBackgroundLongPoll() {
AppSettings.Debug.longPollInBackground = false AppSettings.Experimental.longPollInBackground = false
longPollController.setStateToApply(LongPollState.InApp) longPollController.setStateToApply(LongPollState.InApp)
} }
} }
@@ -24,7 +24,6 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.compose.LifecycleResumeEffect import androidx.lifecycle.compose.LifecycleResumeEffect
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -250,12 +249,11 @@ class MainActivity : AppCompatActivity() {
val noCategoryName = getString(UiR.string.notification_channel_no_category_name) val noCategoryName = getString(UiR.string.notification_channel_no_category_name)
val noCategoryDescriptionText = val noCategoryDescriptionText =
getString(UiR.string.notification_channel_no_category_description) getString(UiR.string.notification_channel_no_category_description)
val noCategoryImportance = NotificationManagerCompat.IMPORTANCE_HIGH
val noCategoryChannel = val noCategoryChannel =
NotificationChannel( NotificationChannel(
AppConstants.NOTIFICATION_CHANNEL_UNCATEGORIZED, AppConstants.NOTIFICATION_CHANNEL_UNCATEGORIZED,
noCategoryName, noCategoryName,
noCategoryImportance NotificationManager.IMPORTANCE_HIGH
).apply { ).apply {
description = noCategoryDescriptionText description = noCategoryDescriptionText
} }
@@ -263,12 +261,11 @@ class MainActivity : AppCompatActivity() {
val longPollName = getString(UiR.string.notification_channel_long_polling_service_name) val longPollName = getString(UiR.string.notification_channel_long_polling_service_name)
val longPollDescriptionText = val longPollDescriptionText =
getString(UiR.string.notification_channel_long_polling_service_description) getString(UiR.string.notification_channel_long_polling_service_description)
val longPollImportance = NotificationManagerCompat.IMPORTANCE_NONE
val longPollChannel = val longPollChannel =
NotificationChannel( NotificationChannel(
AppConstants.NOTIFICATION_CHANNEL_LONG_POLLING, AppConstants.NOTIFICATION_CHANNEL_LONG_POLLING,
longPollName, longPollName,
longPollImportance NotificationManager.IMPORTANCE_NONE
).apply { ).apply {
description = longPollDescriptionText description = longPollDescriptionText
} }
@@ -287,7 +284,7 @@ class MainActivity : AppCompatActivity() {
private fun toggleLongPollService( private fun toggleLongPollService(
enable: Boolean, enable: Boolean,
inBackground: Boolean = AppSettings.Debug.longPollInBackground inBackground: Boolean = AppSettings.Experimental.longPollInBackground
) { ) {
if (enable) { if (enable) {
val longPollIntent = Intent(this, LongPollingService::class.java) val longPollIntent = Intent(this, LongPollingService::class.java)
@@ -313,7 +310,7 @@ class MainActivity : AppCompatActivity() {
private fun stopServices() { private fun stopServices() {
toggleOnlineService(enable = false) toggleOnlineService(enable = false)
val asForeground = AppSettings.Debug.longPollInBackground val asForeground = AppSettings.Experimental.longPollInBackground
if (!asForeground) { if (!asForeground) {
toggleLongPollService(enable = false) toggleLongPollService(enable = false)
@@ -76,7 +76,7 @@ class LongPollingService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (startId > 1) return START_STICKY if (startId > 1) return START_STICKY
val inBackground = AppSettings.Debug.longPollInBackground val inBackground = AppSettings.Experimental.longPollInBackground
Log.d( Log.d(
STATE_TAG, STATE_TAG,
@@ -258,10 +258,10 @@ class LongPollingService : Service() {
super.onDestroy() super.onDestroy()
} }
override fun onLowMemory() { override fun onTrimMemory(level: Int) {
Log.d(STATE_TAG, "onLowMemory") Log.d(STATE_TAG, "onTrimMemory")
longPollController.updateCurrentState(LongPollState.Stopped) longPollController.updateCurrentState(LongPollState.Stopped)
super.onLowMemory() super.onTrimMemory(level)
} }
companion object { companion object {
@@ -9,8 +9,8 @@ import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.provideDelegate import org.gradle.kotlin.dsl.provideDelegate
import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinBaseExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
internal fun Project.configureKotlinAndroid( internal fun Project.configureKotlinAndroid(
commonExtension: CommonExtension<*, *, *, *, *, *>, commonExtension: CommonExtension<*, *, *, *, *, *>,
@@ -40,7 +40,7 @@ internal fun Project.configureKotlinJvm() {
configureKotlin<KotlinJvmProjectExtension>() configureKotlin<KotlinJvmProjectExtension>()
} }
private inline fun <reified T : KotlinTopLevelExtension> Project.configureKotlin() = configure<T> { private inline fun <reified T : KotlinBaseExtension> Project.configureKotlin() = configure<T> {
// Treat all Kotlin warnings as errors (disabled by default) // Treat all Kotlin warnings as errors (disabled by default)
// Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties
val warningsAsErrors: String? by project val warningsAsErrors: String? by project
@@ -89,12 +89,20 @@ object AppSettings {
) )
set(value) = put(SettingsKeys.KEY_USE_CONTACT_NAMES, value) set(value) = put(SettingsKeys.KEY_USE_CONTACT_NAMES, value)
var enablePullToRefresh: Boolean var showEmojiButton: Boolean
get() = get( get() = get(
SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH, SettingsKeys.KEY_SHOW_EMOJI_BUTTON,
SettingsKeys.DEFAULT_VALUE_ENABLE_PULL_TO_REFRESH SettingsKeys.DEFAULT_VALUE_KEY_SHOW_EMOJI_BUTTON
) )
set(value) = put(SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH, value) set(value) = put(SettingsKeys.KEY_SHOW_EMOJI_BUTTON, value)
var enableHaptic: Boolean
get() = get(
SettingsKeys.KEY_ENABLE_HAPTIC,
SettingsKeys.DEFAULT_ENABLE_HAPTIC
)
set(value) = put(SettingsKeys.KEY_ENABLE_HAPTIC, value)
} }
object Appearance { object Appearance {
@@ -126,6 +134,13 @@ object AppSettings {
) )
set(value) = put(SettingsKeys.KEY_USE_DYNAMIC_COLORS, value) set(value) = put(SettingsKeys.KEY_USE_DYNAMIC_COLORS, value)
var useSystemFont: Boolean
get() = get(
SettingsKeys.KEY_USE_SYSTEM_FONT,
SettingsKeys.DEFAULT_USE_SYSTEM_FONT
)
set(value) = put(SettingsKeys.KEY_USE_SYSTEM_FONT, value)
var appLanguage: String var appLanguage: String
get() = get( get() = get(
SettingsKeys.KEY_APPEARANCE_LANGUAGE, SettingsKeys.KEY_APPEARANCE_LANGUAGE,
@@ -152,6 +167,29 @@ object AppSettings {
set(value) = put(SettingsKeys.KEY_ACTIVITY_SEND_ONLINE_STATUS, value) set(value) = put(SettingsKeys.KEY_ACTIVITY_SEND_ONLINE_STATUS, value)
} }
object Experimental {
var longPollInBackground: Boolean
get() = get(
SettingsKeys.KEY_LONG_POLL_IN_BACKGROUND,
SettingsKeys.DEFAULT_LONG_POLL_IN_BACKGROUND
)
set(value) = put(SettingsKeys.KEY_LONG_POLL_IN_BACKGROUND, value)
var showTimeInActionMessages: Boolean
get() = get(
SettingsKeys.KEY_SHOW_TIME_IN_ACTION_MESSAGES,
SettingsKeys.DEFAULT_SHOW_TIME_IN_ACTION_MESSAGES
)
set(value) = put(SettingsKeys.KEY_SHOW_TIME_IN_ACTION_MESSAGES, value)
var useBlur: Boolean
get() = get(
SettingsKeys.KEY_USE_BLUR,
SettingsKeys.DEFAULT_USE_BLUR
)
set(value) = put(SettingsKeys.KEY_USE_BLUR, value)
}
object Debug { object Debug {
var showAlertAfterCrash: Boolean var showAlertAfterCrash: Boolean
get() = get( get() = get(
@@ -160,41 +198,6 @@ object AppSettings {
) )
set(value) = put(SettingsKeys.KEY_DEBUG_SHOW_CRASH_ALERT, value) set(value) = put(SettingsKeys.KEY_DEBUG_SHOW_CRASH_ALERT, value)
var longPollInBackground: Boolean
get() = get(
SettingsKeys.KEY_FEATURES_LONG_POLL_IN_BACKGROUND,
SettingsKeys.DEFAULT_VALUE_FEATURES_LONG_POLL_IN_BACKGROUND
)
set(value) = put(SettingsKeys.KEY_FEATURES_LONG_POLL_IN_BACKGROUND, value)
var useBlur: Boolean
get() = get(
SettingsKeys.KEY_APPEARANCE_USE_BLUR,
SettingsKeys.DEFAULT_VALUE_KEY_APPEARANCE_USE_BLUR
)
set(value) = put(SettingsKeys.KEY_APPEARANCE_USE_BLUR, value)
var showEmojiButton: Boolean
get() = get(
SettingsKeys.KEY_SHOW_EMOJI_BUTTON,
SettingsKeys.DEFAULT_VALUE_KEY_SHOW_EMOJI_BUTTON
)
set(value) = put(SettingsKeys.KEY_SHOW_EMOJI_BUTTON, value)
var showTimeInActionMessages: Boolean
get() = get(
SettingsKeys.KEY_APPEARANCE_SHOW_TIME_IN_ACTION_MESSAGES,
SettingsKeys.DEFAULT_VALUE_APPEARANCE_SHOW_TIME_IN_ACTION_MESSAGES
)
set(value) = put(SettingsKeys.KEY_APPEARANCE_SHOW_TIME_IN_ACTION_MESSAGES, value)
var enableHaptic: Boolean
get() = get(
SettingsKeys.KEY_DEBUG_ENABLE_HAPTIC,
SettingsKeys.DEFAULT_DEBUG_ENABLE_HAPTIC
)
set(value) = put(SettingsKeys.KEY_DEBUG_ENABLE_HAPTIC, value)
var networkLogLevel: LogLevel var networkLogLevel: LogLevel
get() = get( get() = get(
SettingsKeys.KEY_DEBUG_NETWORK_LOG_LEVEL, SettingsKeys.KEY_DEBUG_NETWORK_LOG_LEVEL,
@@ -202,13 +205,6 @@ object AppSettings {
).let(LogLevel::parse) ).let(LogLevel::parse)
set(level) = put(SettingsKeys.KEY_DEBUG_NETWORK_LOG_LEVEL, level.value) set(level) = put(SettingsKeys.KEY_DEBUG_NETWORK_LOG_LEVEL, level.value)
var useSystemFont: Boolean
get() = get(
SettingsKeys.KEY_DEBUG_USE_SYSTEM_FONT,
SettingsKeys.DEFAULT_DEBUG_USE_SYSTEM_FONT
)
set(value) = put(SettingsKeys.KEY_DEBUG_USE_SYSTEM_FONT, value)
var showDebugCategory: Boolean var showDebugCategory: Boolean
get() = get( get() = get(
SettingsKeys.KEY_SHOW_DEBUG_CATEGORY, SettingsKeys.KEY_SHOW_DEBUG_CATEGORY,
@@ -7,11 +7,9 @@ object SettingsKeys {
const val KEY_ACCOUNT_LOGOUT = "account_logout" const val KEY_ACCOUNT_LOGOUT = "account_logout"
const val KEY_GENERAL = "general" const val KEY_GENERAL = "general"
const val KEY_USE_CONTACT_NAMES = "general_use_contact_names" const val KEY_USE_CONTACT_NAMES = "use_contact_names"
const val DEFAULT_VALUE_USE_CONTACT_NAMES = false const val DEFAULT_VALUE_USE_CONTACT_NAMES = false
const val KEY_ENABLE_PULL_TO_REFRESH = "general_pull_to_refresh" const val KEY_SHOW_EMOJI_BUTTON = "show_emoji_button"
const val DEFAULT_VALUE_ENABLE_PULL_TO_REFRESH = false
const val KEY_SHOW_EMOJI_BUTTON = "general_show_emoji_button"
const val DEFAULT_VALUE_KEY_SHOW_EMOJI_BUTTON = false const val DEFAULT_VALUE_KEY_SHOW_EMOJI_BUTTON = false
const val KEY_APPEARANCE = "appearance" const val KEY_APPEARANCE = "appearance"
@@ -23,20 +21,20 @@ object SettingsKeys {
const val DEFAULT_VALUE_APPEARANCE_AMOLED_THEME = false const val DEFAULT_VALUE_APPEARANCE_AMOLED_THEME = false
const val KEY_USE_DYNAMIC_COLORS = "appearance_use_dynamic_colors" const val KEY_USE_DYNAMIC_COLORS = "appearance_use_dynamic_colors"
const val DEFAULT_VALUE_USE_DYNAMIC_COLORS = false const val DEFAULT_VALUE_USE_DYNAMIC_COLORS = false
const val KEY_APPEARANCE_COLOR_SCHEME = "appearance_color_scheme" const val KEY_COLOR_SCHEME = "appearance_color_scheme"
const val DEFAULT_VALUE_APPEARANCE_COLOR_SCHEME = 0 const val DEFAULT_COLOR_SCHEME = 0
const val KEY_APPEARANCE_LANGUAGE = "appearance_language" const val KEY_APPEARANCE_LANGUAGE = "appearance_language"
const val DEFAULT_APPEARANCE_LANGUAGE = "" const val DEFAULT_APPEARANCE_LANGUAGE = ""
const val KEY_APPEARANCE_USE_BLUR = "appearance_use_blur" const val KEY_USE_BLUR = "use_blur"
const val DEFAULT_VALUE_KEY_APPEARANCE_USE_BLUR = false const val DEFAULT_USE_BLUR = false
const val KEY_APPEARANCE_SHOW_TIME_IN_ACTION_MESSAGES = const val KEY_SHOW_TIME_IN_ACTION_MESSAGES =
"appearance_show_time_in_action_messages" "show_time_in_action_messages"
const val DEFAULT_VALUE_APPEARANCE_SHOW_TIME_IN_ACTION_MESSAGES = false const val DEFAULT_SHOW_TIME_IN_ACTION_MESSAGES = false
const val KEY_FEATURES_FAST_TEXT = "features_fast_text" const val KEY_FEATURES_FAST_TEXT = "features_fast_text"
const val DEFAULT_VALUE_FEATURES_FAST_TEXT = "¯\\_(ツ)_/¯" const val DEFAULT_VALUE_FEATURES_FAST_TEXT = "¯\\_(ツ)_/¯"
const val KEY_FEATURES_LONG_POLL_IN_BACKGROUND = "features_lp_background" const val KEY_LONG_POLL_IN_BACKGROUND = "lp_background"
const val DEFAULT_VALUE_FEATURES_LONG_POLL_IN_BACKGROUND = false const val DEFAULT_LONG_POLL_IN_BACKGROUND = false
const val KEY_ACTIVITY_SEND_ONLINE_STATUS = "activity_send_online_status" const val KEY_ACTIVITY_SEND_ONLINE_STATUS = "activity_send_online_status"
const val DEFAULT_VALUE_KEY_ACTIVITY_SEND_ONLINE_STATUS = false const val DEFAULT_VALUE_KEY_ACTIVITY_SEND_ONLINE_STATUS = false
@@ -45,12 +43,12 @@ object SettingsKeys {
const val KEY_DEBUG_SHOW_CRASH_ALERT = "debug_show_crash_alert" const val KEY_DEBUG_SHOW_CRASH_ALERT = "debug_show_crash_alert"
const val KEY_DEBUG_HIDE_DEBUG_LIST = "debug_hide_debug_list" const val KEY_DEBUG_HIDE_DEBUG_LIST = "debug_hide_debug_list"
const val KEY_ENABLE_ANIMATIONS_IN_MESSAGES = "debug_enable_animations_in_messages" const val KEY_ENABLE_ANIMATIONS_IN_MESSAGES = "debug_enable_animations_in_messages"
const val KEY_DEBUG_ENABLE_HAPTIC = "debug_enable_haptic" const val KEY_ENABLE_HAPTIC = "enable_haptic"
const val DEFAULT_DEBUG_ENABLE_HAPTIC = true const val DEFAULT_ENABLE_HAPTIC = true
const val KEY_DEBUG_NETWORK_LOG_LEVEL = "debug_network_log_level" const val KEY_DEBUG_NETWORK_LOG_LEVEL = "debug_network_log_level"
const val DEFAULT_NETWORK_LOG_LEVEL = 0 const val DEFAULT_NETWORK_LOG_LEVEL = 0
const val KEY_DEBUG_USE_SYSTEM_FONT = "debug_use_system_font" const val KEY_USE_SYSTEM_FONT = "use_system_font"
const val DEFAULT_DEBUG_USE_SYSTEM_FONT = false const val DEFAULT_USE_SYSTEM_FONT = false
const val KEY_SHOW_DEBUG_CATEGORY = "show_debug_category" const val KEY_SHOW_DEBUG_CATEGORY = "show_debug_category"
@@ -7,7 +7,6 @@ import kotlinx.coroutines.flow.StateFlow
interface UserSettings { interface UserSettings {
val useContactNames: StateFlow<Boolean> val useContactNames: StateFlow<Boolean>
val enablePullToRefresh: StateFlow<Boolean>
val enableMultiline: StateFlow<Boolean> val enableMultiline: StateFlow<Boolean>
val darkMode: StateFlow<DarkMode> val darkMode: StateFlow<DarkMode>
@@ -28,7 +27,6 @@ interface UserSettings {
val showDebugCategory: StateFlow<Boolean> val showDebugCategory: StateFlow<Boolean>
fun onUseContactNamesChanged(use: Boolean) fun onUseContactNamesChanged(use: Boolean)
fun onEnablePullToRefreshChanged(enable: Boolean)
fun onEnableMultilineChanged(enable: Boolean) fun onEnableMultilineChanged(enable: Boolean)
fun onDarkModeChanged(mode: DarkMode) fun onDarkModeChanged(mode: DarkMode)
@@ -52,7 +50,6 @@ interface UserSettings {
class UserSettingsImpl : UserSettings { class UserSettingsImpl : UserSettings {
override val useContactNames = MutableStateFlow(AppSettings.General.useContactNames) override val useContactNames = MutableStateFlow(AppSettings.General.useContactNames)
override val enablePullToRefresh = MutableStateFlow(AppSettings.General.enablePullToRefresh)
override val enableMultiline = MutableStateFlow(AppSettings.Appearance.enableMultiline) override val enableMultiline = MutableStateFlow(AppSettings.Appearance.enableMultiline)
override val darkMode = MutableStateFlow(AppSettings.Appearance.darkMode) override val darkMode = MutableStateFlow(AppSettings.Appearance.darkMode)
@@ -65,22 +62,18 @@ class UserSettingsImpl : UserSettings {
override val sendOnlineStatus = MutableStateFlow(AppSettings.Activity.sendOnlineStatus) override val sendOnlineStatus = MutableStateFlow(AppSettings.Activity.sendOnlineStatus)
override val showAlertAfterCrash = MutableStateFlow(AppSettings.Debug.showAlertAfterCrash) override val showAlertAfterCrash = MutableStateFlow(AppSettings.Debug.showAlertAfterCrash)
override val longPollInBackground = MutableStateFlow(AppSettings.Debug.longPollInBackground) override val longPollInBackground = MutableStateFlow(AppSettings.Experimental.longPollInBackground)
override val useBlur = MutableStateFlow(AppSettings.Debug.useBlur) override val useBlur = MutableStateFlow(AppSettings.Experimental.useBlur)
override val showEmojiButton = MutableStateFlow(AppSettings.Debug.showEmojiButton) override val showEmojiButton = MutableStateFlow(AppSettings.General.showEmojiButton)
override val showTimeInActionMessages = override val showTimeInActionMessages =
MutableStateFlow(AppSettings.Debug.showTimeInActionMessages) MutableStateFlow(AppSettings.Experimental.showTimeInActionMessages)
override val useSystemFont = MutableStateFlow(AppSettings.Debug.useSystemFont) override val useSystemFont = MutableStateFlow(AppSettings.Appearance.useSystemFont)
override val showDebugCategory = MutableStateFlow(AppSettings.Debug.showDebugCategory) override val showDebugCategory = MutableStateFlow(AppSettings.Debug.showDebugCategory)
override fun onUseContactNamesChanged(use: Boolean) { override fun onUseContactNamesChanged(use: Boolean) {
useContactNames.value = use useContactNames.value = use
} }
override fun onEnablePullToRefreshChanged(enable: Boolean) {
enablePullToRefresh.value = enable
}
override fun onEnableMultilineChanged(enable: Boolean) { override fun onEnableMultilineChanged(enable: Boolean) {
enableMultiline.value = enable enableMultiline.value = enable
} }
@@ -0,0 +1,90 @@
package dev.meloda.fast.ui.components
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Indication
import androidx.compose.foundation.background
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.IconButtonColors
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalUseFallbackRippleImplementation
import androidx.compose.material3.minimumInteractiveComponentSize
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun IconButton(
onClick: () -> Unit = {},
onLongClick: (() -> Unit)? = null,
modifier: Modifier = Modifier,
enabled: Boolean = true,
colors: IconButtonColors = IconButtonDefaults.iconButtonColors(),
interactionSource: MutableInteractionSource? = null,
content: @Composable () -> Unit
) {
Box(
modifier =
modifier
.minimumInteractiveComponentSize()
.size(IconButtonTokens.StateLayerSize)
.clip(IconButtonTokens.StateLayerShape)
.background(color = colors.containerColor(enabled))
.combinedClickable(
onClick = onClick,
onLongClick = onLongClick,
enabled = enabled,
interactionSource = interactionSource,
indication = rippleOrFallbackImplementation(
bounded = false,
radius = IconButtonTokens.StateLayerSize / 2
)
),
contentAlignment = Alignment.Center
) {
val contentColor = colors.contentColor(enabled)
CompositionLocalProvider(LocalContentColor provides contentColor, content = content)
}
}
@Suppress("DEPRECATION_ERROR")
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun rippleOrFallbackImplementation(
bounded: Boolean = true,
radius: Dp = Dp.Unspecified,
color: Color = Color.Unspecified
): Indication {
return if (LocalUseFallbackRippleImplementation.current) {
rememberRipple(bounded, radius, color)
} else {
ripple(bounded, radius, color)
}
}
internal object IconButtonTokens {
val StateLayerShape = CircleShape
val StateLayerSize = 40.0.dp
}
@Stable
internal fun IconButtonColors.containerColor(enabled: Boolean): Color =
if (enabled) containerColor else disabledContainerColor
@Stable
internal fun IconButtonColors.contentColor(enabled: Boolean): Color =
if (enabled) contentColor else disabledContentColor
+1 -1
View File
@@ -182,7 +182,7 @@
<string name="settings_appearance_multiline_summary">Заголовок чата и текст сообщения смогут занимать несколько строчек</string> <string name="settings_appearance_multiline_summary">Заголовок чата и текст сообщения смогут занимать несколько строчек</string>
<string name="settings_features_title">Фичи</string> <string name="settings_features_title">Фичи</string>
<string name="settings_features_fast_text_title">Fast текст</string> <string name="settings_features_fast_text_title">Fast текст</string>
<string name="settings_features_long_poll_in_background_title">[WIP] LongPoll в фоне</string> <string name="settings_features_long_poll_in_background_title">LongPoll в фоне</string>
<string name="settings_features_long_poll_in_background_summary">Ваши сообщения будут обновляться, даже если приложение находится в фоне</string> <string name="settings_features_long_poll_in_background_summary">Ваши сообщения будут обновляться, даже если приложение находится в фоне</string>
<string name="settings_activity_title">Активность</string> <string name="settings_activity_title">Активность</string>
<string name="settings_activity_send_online_title">Быть «в сети»</string> <string name="settings_activity_send_online_title">Быть «в сети»</string>
+2 -2
View File
@@ -240,8 +240,8 @@
<string name="settings_appearance_multiline_summary">The title of the conversation and the text of the message can take up multiple lines</string> <string name="settings_appearance_multiline_summary">The title of the conversation and the text of the message can take up multiple lines</string>
<string name="settings_features_title">Features</string> <string name="settings_features_title">Features</string>
<string name="settings_features_fast_text_title">Fast text</string> <string name="settings_features_fast_text_title">Fast text</string>
<string name="settings_features_long_poll_in_background_title">[WIP] LongPoll in background</string> <string name="settings_features_long_poll_in_background_title">LongPoll in background</string>
<string name="settings_features_long_poll_in_background_summary">Your messages will be updates even when app is not on the screen</string> <string name="settings_features_long_poll_in_background_summary">Your messages will be updating even when app is not on the screen</string>
<string name="settings_activity_title">Activity</string> <string name="settings_activity_title">Activity</string>
<string name="settings_activity_send_online_title">Send online status</string> <string name="settings_activity_send_online_title">Send online status</string>
<string name="settings_activity_send_online_summary">Online status will be sent every five minutes</string> <string name="settings_activity_send_online_summary">Online status will be sent every five minutes</string>
@@ -3,8 +3,8 @@ package dev.meloda.fast.auth.captcha.di
import dev.meloda.fast.auth.captcha.CaptchaViewModel import dev.meloda.fast.auth.captcha.CaptchaViewModel
import dev.meloda.fast.auth.captcha.CaptchaViewModelImpl import dev.meloda.fast.auth.captcha.CaptchaViewModelImpl
import dev.meloda.fast.auth.captcha.validation.CaptchaValidator import dev.meloda.fast.auth.captcha.validation.CaptchaValidator
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.bind import org.koin.dsl.bind
import org.koin.dsl.module import org.koin.dsl.module
@@ -368,7 +368,7 @@ class LoginViewModelImpl(
private fun startLongPoll() { private fun startLongPoll() {
longPollController.setStateToApply( longPollController.setStateToApply(
if (AppSettings.Debug.longPollInBackground) { if (AppSettings.Experimental.longPollInBackground) {
LongPollState.Background LongPollState.Background
} else { } else {
LongPollState.InApp LongPollState.InApp
@@ -4,8 +4,8 @@ import dev.meloda.fast.auth.login.LoginViewModelImpl
import dev.meloda.fast.domain.OAuthUseCase import dev.meloda.fast.domain.OAuthUseCase
import dev.meloda.fast.domain.OAuthUseCaseImpl import dev.meloda.fast.domain.OAuthUseCaseImpl
import dev.meloda.fast.auth.login.validation.LoginValidator import dev.meloda.fast.auth.login.validation.LoginValidator
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.bind import org.koin.dsl.bind
import org.koin.dsl.module import org.koin.dsl.module
@@ -5,8 +5,8 @@ import dev.meloda.fast.domain.AuthUseCaseImpl
import dev.meloda.fast.auth.validation.ValidationViewModel import dev.meloda.fast.auth.validation.ValidationViewModel
import dev.meloda.fast.auth.validation.ValidationViewModelImpl import dev.meloda.fast.auth.validation.ValidationViewModelImpl
import dev.meloda.fast.auth.validation.validation.ValidationValidator import dev.meloda.fast.auth.validation.validation.ValidationValidator
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.bind import org.koin.dsl.bind
import org.koin.dsl.module import org.koin.dsl.module
@@ -70,11 +70,9 @@ import dev.meloda.fast.chatmaterials.ChatMaterialsViewModel
import dev.meloda.fast.chatmaterials.ChatMaterialsViewModelImpl import dev.meloda.fast.chatmaterials.ChatMaterialsViewModelImpl
import dev.meloda.fast.chatmaterials.model.ChatMaterialsScreenState import dev.meloda.fast.chatmaterials.model.ChatMaterialsScreenState
import dev.meloda.fast.chatmaterials.model.UiChatMaterial import dev.meloda.fast.chatmaterials.model.UiChatMaterial
import dev.meloda.fast.datastore.UserSettings
import dev.meloda.fast.ui.R import dev.meloda.fast.ui.R
import dev.meloda.fast.ui.theme.LocalThemeConfig import dev.meloda.fast.ui.theme.LocalThemeConfig
import org.koin.androidx.compose.koinViewModel import org.koin.androidx.compose.koinViewModel
import org.koin.compose.koinInject
@Composable @Composable
fun ChatMaterialsRoute( fun ChatMaterialsRoute(
@@ -82,15 +80,10 @@ fun ChatMaterialsRoute(
onPhotoClicked: (url: String) -> Unit, onPhotoClicked: (url: String) -> Unit,
viewModel: ChatMaterialsViewModel = koinViewModel<ChatMaterialsViewModelImpl>() viewModel: ChatMaterialsViewModel = koinViewModel<ChatMaterialsViewModelImpl>()
) { ) {
val userSettings: UserSettings = koinInject()
val enablePullToRefresh by userSettings.enablePullToRefresh.collectAsStateWithLifecycle()
val screenState by viewModel.screenState.collectAsStateWithLifecycle() val screenState by viewModel.screenState.collectAsStateWithLifecycle()
ChatMaterialsScreen( ChatMaterialsScreen(
screenState = screenState, screenState = screenState,
enablePullToRefresh = enablePullToRefresh,
onBack = onBack, onBack = onBack,
onTypeChanged = viewModel::onTypeChanged, onTypeChanged = viewModel::onTypeChanged,
onRefreshDropdownItemClicked = viewModel::onRefresh, onRefreshDropdownItemClicked = viewModel::onRefresh,
@@ -107,7 +100,6 @@ fun ChatMaterialsRoute(
@Composable @Composable
fun ChatMaterialsScreen( fun ChatMaterialsScreen(
screenState: ChatMaterialsScreenState = ChatMaterialsScreenState.EMPTY, screenState: ChatMaterialsScreenState = ChatMaterialsScreenState.EMPTY,
enablePullToRefresh: Boolean = false,
onBack: () -> Unit = {}, onBack: () -> Unit = {},
onTypeChanged: (String) -> Unit = {}, onTypeChanged: (String) -> Unit = {},
onRefreshDropdownItemClicked: () -> Unit = {}, onRefreshDropdownItemClicked: () -> Unit = {},
@@ -1,14 +1,14 @@
package dev.meloda.fast.conversations.di package dev.meloda.fast.conversations.di
import dev.meloda.fast.conversations.ConversationsViewModelImpl import dev.meloda.fast.conversations.ConversationsViewModelImpl
import dev.meloda.fast.domain.ConversationsUseCaseImpl
import dev.meloda.fast.domain.ConversationsUseCase import dev.meloda.fast.domain.ConversationsUseCase
import org.koin.androidx.viewmodel.dsl.viewModelOf import dev.meloda.fast.domain.ConversationsUseCaseImpl
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.bind import org.koin.dsl.bind
import org.koin.dsl.module import org.koin.dsl.module
val conversationsModule = module { val conversationsModule = module {
singleOf(::ConversationsUseCaseImpl) bind dev.meloda.fast.domain.ConversationsUseCase::class singleOf(::ConversationsUseCaseImpl) bind ConversationsUseCase::class
viewModelOf(::ConversationsViewModelImpl) viewModelOf(::ConversationsViewModelImpl)
} }
@@ -310,7 +310,7 @@ fun ConversationsScreen(
) { ) {
FloatingActionButton( FloatingActionButton(
onClick = { onClick = {
if (AppSettings.Debug.enableHaptic) { if (AppSettings.General.enableHaptic) {
view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT) view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT)
} }
scope.launch { scope.launch {
@@ -3,13 +3,12 @@ package dev.meloda.fast.friends.di
import dev.meloda.fast.domain.FriendsUseCase import dev.meloda.fast.domain.FriendsUseCase
import dev.meloda.fast.friends.FriendsViewModelImpl import dev.meloda.fast.friends.FriendsViewModelImpl
import dev.meloda.fast.domain.FriendsUseCaseImpl import dev.meloda.fast.domain.FriendsUseCaseImpl
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.bind import org.koin.dsl.bind
import org.koin.dsl.module import org.koin.dsl.module
val friendsModule = module { val friendsModule = module {
singleOf(::FriendsUseCaseImpl) bind dev.meloda.fast.domain.FriendsUseCase::class singleOf(::FriendsUseCaseImpl) bind FriendsUseCase::class
viewModelOf(::FriendsViewModelImpl) viewModelOf(::FriendsViewModelImpl)
} }
@@ -1,7 +1,7 @@
package dev.meloda.fast.languagepicker.di package dev.meloda.fast.languagepicker.di
import dev.meloda.fast.languagepicker.LanguagePickerViewModelImpl import dev.meloda.fast.languagepicker.LanguagePickerViewModelImpl
import org.koin.androidx.viewmodel.dsl.viewModelOf import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module import org.koin.dsl.module
val languagePickerModule = module { val languagePickerModule = module {
@@ -2,6 +2,7 @@ package dev.meloda.fast.messageshistory
import android.content.SharedPreferences import android.content.SharedPreferences
import android.util.Log import android.util.Log
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.core.content.edit import androidx.core.content.edit
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
@@ -10,6 +11,7 @@ import androidx.lifecycle.viewModelScope
import com.conena.nanokt.collections.indexOfFirstOrNull import com.conena.nanokt.collections.indexOfFirstOrNull
import com.conena.nanokt.collections.indexOfOrNull import com.conena.nanokt.collections.indexOfOrNull
import com.conena.nanokt.text.isEmptyOrBlank import com.conena.nanokt.text.isEmptyOrBlank
import com.conena.nanokt.text.isNotEmptyOrBlank
import dev.meloda.fast.common.extensions.listenValue import dev.meloda.fast.common.extensions.listenValue
import dev.meloda.fast.common.extensions.setValue import dev.meloda.fast.common.extensions.setValue
import dev.meloda.fast.common.provider.ResourceProvider import dev.meloda.fast.common.provider.ResourceProvider
@@ -54,7 +56,7 @@ interface MessagesHistoryViewModel {
fun onRefresh() fun onRefresh()
fun onAttachmentButtonClicked() fun onAttachmentButtonClicked()
fun onMessageInputChanged(newText: TextFieldValue) fun onMessageInputChanged(newText: TextFieldValue)
fun onEmojiButtonClicked() fun onEmojiButtonLongClicked()
fun onActionButtonClicked() fun onActionButtonClicked()
fun onPaginationConditionsMet() fun onPaginationConditionsMet()
@@ -123,8 +125,15 @@ class MessagesHistoryViewModelImpl(
screenState.setValue { old -> old.copy(message = newText) } screenState.setValue { old -> old.copy(message = newText) }
} }
override fun onEmojiButtonClicked() { override fun onEmojiButtonLongClicked() {
AppSettings.Features.fastText.takeIf { it.isNotEmptyOrBlank() }?.let { text ->
screenState.setValue { old ->
val newText = "${old.message.text}$text"
old.copy(
message = TextFieldValue(text = newText, selection = TextRange(newText.length))
)
}
}
} }
override fun onActionButtonClicked() { override fun onActionButtonClicked() {
@@ -1,17 +1,17 @@
package dev.meloda.fast.messageshistory.di package dev.meloda.fast.messageshistory.di
import dev.meloda.fast.domain.MessagesUseCase import dev.meloda.fast.domain.MessagesUseCase
import dev.meloda.fast.domain.MessagesUseCaseImpl
import dev.meloda.fast.messageshistory.MessagesHistoryViewModel import dev.meloda.fast.messageshistory.MessagesHistoryViewModel
import dev.meloda.fast.messageshistory.MessagesHistoryViewModelImpl import dev.meloda.fast.messageshistory.MessagesHistoryViewModelImpl
import dev.meloda.fast.domain.MessagesUseCaseImpl
import dev.meloda.fast.messageshistory.validation.MessagesHistoryValidator import dev.meloda.fast.messageshistory.validation.MessagesHistoryValidator
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.core.module.dsl.singleOf import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.bind import org.koin.dsl.bind
import org.koin.dsl.module import org.koin.dsl.module
val messagesHistoryModule = module { val messagesHistoryModule = module {
singleOf(::MessagesUseCaseImpl) bind dev.meloda.fast.domain.MessagesUseCase::class singleOf(::MessagesUseCaseImpl) bind MessagesUseCase::class
singleOf(::MessagesHistoryValidator) singleOf(::MessagesHistoryValidator)
viewModelOf(::MessagesHistoryViewModelImpl) bind MessagesHistoryViewModel::class viewModelOf(::MessagesHistoryViewModelImpl) bind MessagesHistoryViewModel::class
} }
@@ -37,7 +37,6 @@ import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@@ -86,6 +85,7 @@ import dev.meloda.fast.messageshistory.model.MessagesHistoryScreenState
import dev.meloda.fast.messageshistory.util.firstMessage import dev.meloda.fast.messageshistory.util.firstMessage
import dev.meloda.fast.messageshistory.util.indexOfMessageByCmId import dev.meloda.fast.messageshistory.util.indexOfMessageByCmId
import dev.meloda.fast.model.BaseError import dev.meloda.fast.model.BaseError
import dev.meloda.fast.ui.components.IconButton
import dev.meloda.fast.ui.theme.LocalThemeConfig import dev.meloda.fast.ui.theme.LocalThemeConfig
import dev.meloda.fast.ui.util.ImmutableList import dev.meloda.fast.ui.util.ImmutableList
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -119,7 +119,8 @@ fun MessagesHistoryRoute(
onPaginationConditionsMet = viewModel::onPaginationConditionsMet, onPaginationConditionsMet = viewModel::onPaginationConditionsMet,
onMessageInputChanged = viewModel::onMessageInputChanged, onMessageInputChanged = viewModel::onMessageInputChanged,
onAttachmentButtonClicked = viewModel::onAttachmentButtonClicked, onAttachmentButtonClicked = viewModel::onAttachmentButtonClicked,
onActionButtonClicked = viewModel::onActionButtonClicked onActionButtonClicked = viewModel::onActionButtonClicked,
onEmojiButtonLongClicked = viewModel::onEmojiButtonLongClicked
) )
} }
@@ -141,7 +142,8 @@ fun MessagesHistoryScreen(
onPaginationConditionsMet: () -> Unit = {}, onPaginationConditionsMet: () -> Unit = {},
onMessageInputChanged: (TextFieldValue) -> Unit = {}, onMessageInputChanged: (TextFieldValue) -> Unit = {},
onAttachmentButtonClicked: () -> Unit = {}, onAttachmentButtonClicked: () -> Unit = {},
onActionButtonClicked: () -> Unit = {} onActionButtonClicked: () -> Unit = {},
onEmojiButtonLongClicked: () -> Unit = {}
) { ) {
val view = LocalView.current val view = LocalView.current
@@ -371,7 +373,7 @@ fun MessagesHistoryScreen(
Column(verticalArrangement = Arrangement.Bottom) { Column(verticalArrangement = Arrangement.Bottom) {
IconButton( IconButton(
onClick = { onClick = {
if (AppSettings.Debug.enableHaptic) { if (AppSettings.General.enableHaptic) {
view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT) view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT)
} }
scope.launch { scope.launch {
@@ -389,6 +391,12 @@ fun MessagesHistoryScreen(
} }
} }
}, },
onLongClick = {
if (AppSettings.General.enableHaptic) {
view.performHapticFeedback(HapticFeedbackConstantsCompat.LONG_PRESS)
}
onEmojiButtonLongClicked()
},
modifier = Modifier.rotate(rotation.value) modifier = Modifier.rotate(rotation.value)
) { ) {
Icon( Icon(
@@ -427,7 +435,7 @@ fun MessagesHistoryScreen(
Column(verticalArrangement = Arrangement.Bottom) { Column(verticalArrangement = Arrangement.Bottom) {
IconButton( IconButton(
onClick = { onClick = {
if (AppSettings.Debug.enableHaptic) { if (AppSettings.General.enableHaptic) {
view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT) view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT)
} }
scope.launch { scope.launch {
@@ -463,7 +471,7 @@ fun MessagesHistoryScreen(
IconButton( IconButton(
onClick = { onClick = {
if (screenState.actionMode == ActionMode.Record) { if (screenState.actionMode == ActionMode.Record) {
if (AppSettings.Debug.enableHaptic) { if (AppSettings.General.enableHaptic) {
view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT) view.performHapticFeedback(HapticFeedbackConstantsCompat.REJECT)
} }
scope.launch { scope.launch {
@@ -2,7 +2,7 @@ package dev.meloda.fast.photoviewer.di
import dev.meloda.fast.photoviewer.PhotoViewViewModel import dev.meloda.fast.photoviewer.PhotoViewViewModel
import dev.meloda.fast.photoviewer.PhotoViewViewModelImpl import dev.meloda.fast.photoviewer.PhotoViewViewModelImpl
import org.koin.androidx.viewmodel.dsl.viewModelOf import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.bind import org.koin.dsl.bind
import org.koin.dsl.module import org.koin.dsl.module
@@ -123,7 +123,7 @@ fun TopBar(
} }
}, },
actions = { actions = {
// IconButton( // IconButton.kt(
// onClick = { dropdownMenuShown = true } // onClick = { dropdownMenuShown = true }
// ) { // ) {
// Icon( // Icon(
@@ -1,7 +1,7 @@
package dev.meloda.fast.profile.di package dev.meloda.fast.profile.di
import dev.meloda.fast.profile.ProfileViewModelImpl import dev.meloda.fast.profile.ProfileViewModelImpl
import org.koin.androidx.viewmodel.dsl.viewModelOf import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module import org.koin.dsl.module
val profileModule = module { val profileModule = module {
@@ -154,13 +154,6 @@ class SettingsViewModelImpl(
userSettings.onUseContactNamesChanged(isUsing) userSettings.onUseContactNamesChanged(isUsing)
} }
SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH -> {
val enable =
newValue as? Boolean ?: SettingsKeys.DEFAULT_VALUE_ENABLE_PULL_TO_REFRESH
userSettings.onEnablePullToRefreshChanged(enable)
}
SettingsKeys.KEY_APPEARANCE_MULTILINE -> { SettingsKeys.KEY_APPEARANCE_MULTILINE -> {
val isUsing = newValue as? Boolean ?: SettingsKeys.DEFAULT_VALUE_MULTILINE val isUsing = newValue as? Boolean ?: SettingsKeys.DEFAULT_VALUE_MULTILINE
userSettings.onEnableMultilineChanged(isUsing) userSettings.onEnableMultilineChanged(isUsing)
@@ -206,9 +199,9 @@ class SettingsViewModelImpl(
userSettings.onShowAlertAfterCrashChanged(show) userSettings.onShowAlertAfterCrashChanged(show)
} }
SettingsKeys.KEY_FEATURES_LONG_POLL_IN_BACKGROUND -> { SettingsKeys.KEY_LONG_POLL_IN_BACKGROUND -> {
val inBackground = newValue as? Boolean val inBackground = newValue as? Boolean
?: SettingsKeys.DEFAULT_VALUE_FEATURES_LONG_POLL_IN_BACKGROUND ?: SettingsKeys.DEFAULT_LONG_POLL_IN_BACKGROUND
userSettings.onLongPollInBackgroundChanged(inBackground) userSettings.onLongPollInBackgroundChanged(inBackground)
longPollController.setStateToApply( longPollController.setStateToApply(
@@ -221,9 +214,9 @@ class SettingsViewModelImpl(
) )
} }
SettingsKeys.KEY_APPEARANCE_USE_BLUR -> { SettingsKeys.KEY_USE_BLUR -> {
val isUsing = val isUsing =
newValue as? Boolean ?: SettingsKeys.DEFAULT_VALUE_KEY_APPEARANCE_USE_BLUR newValue as? Boolean ?: SettingsKeys.DEFAULT_USE_BLUR
userSettings.onUseBlurChanged(isUsing) userSettings.onUseBlurChanged(isUsing)
} }
@@ -232,14 +225,14 @@ class SettingsViewModelImpl(
userSettings.onShowEmojiButtonChanged(show) userSettings.onShowEmojiButtonChanged(show)
} }
SettingsKeys.KEY_APPEARANCE_SHOW_TIME_IN_ACTION_MESSAGES -> { SettingsKeys.KEY_SHOW_TIME_IN_ACTION_MESSAGES -> {
val show = newValue as? Boolean val show = newValue as? Boolean
?: SettingsKeys.DEFAULT_VALUE_APPEARANCE_SHOW_TIME_IN_ACTION_MESSAGES ?: SettingsKeys.DEFAULT_SHOW_TIME_IN_ACTION_MESSAGES
userSettings.onShowTimeInActionMessagesChanged(show) userSettings.onShowTimeInActionMessagesChanged(show)
} }
SettingsKeys.KEY_DEBUG_USE_SYSTEM_FONT -> { SettingsKeys.KEY_USE_SYSTEM_FONT -> {
val use = newValue as? Boolean ?: SettingsKeys.DEFAULT_DEBUG_USE_SYSTEM_FONT val use = newValue as? Boolean ?: SettingsKeys.DEFAULT_USE_SYSTEM_FONT
userSettings.onUseSystemFontChanged(use) userSettings.onUseSystemFontChanged(use)
} }
@@ -283,10 +276,16 @@ class SettingsViewModelImpl(
text = UiText.Resource(UiR.string.settings_general_contact_names_summary), text = UiText.Resource(UiR.string.settings_general_contact_names_summary),
defaultValue = SettingsKeys.DEFAULT_VALUE_USE_CONTACT_NAMES defaultValue = SettingsKeys.DEFAULT_VALUE_USE_CONTACT_NAMES
) )
val generalEnablePullToRefresh = SettingsItem.Switch( val generalShowEmojiButton = SettingsItem.Switch(
key = SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH, key = SettingsKeys.KEY_SHOW_EMOJI_BUTTON,
defaultValue = SettingsKeys.DEFAULT_VALUE_ENABLE_PULL_TO_REFRESH, title = UiText.Simple("Show emoji button"),
title = UiText.Resource(UiR.string.settings_general_enable_pull_to_refresh_title) text = UiText.Simple("Show emoji button in chat panel"),
defaultValue = SettingsKeys.DEFAULT_VALUE_KEY_SHOW_EMOJI_BUTTON
)
val generalEnableHaptic = SettingsItem.Switch(
key = SettingsKeys.KEY_ENABLE_HAPTIC,
defaultValue = SettingsKeys.DEFAULT_ENABLE_HAPTIC,
title = UiText.Simple("Enable haptic")
) )
val appearanceTitle = SettingsItem.Title( val appearanceTitle = SettingsItem.Title(
@@ -340,7 +339,11 @@ class SettingsViewModelImpl(
text = UiText.Resource(UiR.string.settings_dynamic_colors_description), text = UiText.Resource(UiR.string.settings_dynamic_colors_description),
defaultValue = SettingsKeys.DEFAULT_VALUE_USE_DYNAMIC_COLORS defaultValue = SettingsKeys.DEFAULT_VALUE_USE_DYNAMIC_COLORS
) )
val appearanceUseSystemFont = SettingsItem.Switch(
key = SettingsKeys.KEY_USE_SYSTEM_FONT,
defaultValue = SettingsKeys.DEFAULT_USE_SYSTEM_FONT,
title = UiText.Simple("Use system font")
)
val appearanceLanguage = SettingsItem.TitleText( val appearanceLanguage = SettingsItem.TitleText(
key = SettingsKeys.KEY_APPEARANCE_LANGUAGE, key = SettingsKeys.KEY_APPEARANCE_LANGUAGE,
title = UiText.Resource(UiR.string.settings_application_language), title = UiText.Resource(UiR.string.settings_application_language),
@@ -374,6 +377,28 @@ class SettingsViewModelImpl(
text = UiText.Resource(UiR.string.settings_activity_send_online_summary) text = UiText.Resource(UiR.string.settings_activity_send_online_summary)
) )
val experimentalTitle = SettingsItem.Title(
key = "experimental",
title = UiText.Simple("Experimental - VERY unstable")
)
val experimentalLongPollBackground = SettingsItem.Switch(
key = SettingsKeys.KEY_LONG_POLL_IN_BACKGROUND,
defaultValue = SettingsKeys.DEFAULT_LONG_POLL_IN_BACKGROUND,
title = UiText.Resource(UiR.string.settings_features_long_poll_in_background_title),
text = UiText.Resource(UiR.string.settings_features_long_poll_in_background_summary)
)
val experimentalUseBlur = SettingsItem.Switch(
key = SettingsKeys.KEY_USE_BLUR,
defaultValue = SettingsKeys.DEFAULT_USE_BLUR,
title = UiText.Simple("Use blur"),
text = UiText.Simple("Adds blur wherever possible\nWorks on android 12 and newer"),
)
val experimentalShowTimeInActionMessages = SettingsItem.Switch(
key = SettingsKeys.KEY_SHOW_TIME_IN_ACTION_MESSAGES,
defaultValue = SettingsKeys.DEFAULT_SHOW_TIME_IN_ACTION_MESSAGES,
title = UiText.Simple("Show time in action messages")
)
val debugTitle = SettingsItem.Title( val debugTitle = SettingsItem.Title(
key = "debug", key = "debug",
title = UiText.Resource(UiR.string.settings_debug_title) title = UiText.Resource(UiR.string.settings_debug_title)
@@ -389,34 +414,6 @@ class SettingsViewModelImpl(
title = UiText.Simple("Show alert after crash"), title = UiText.Simple("Show alert after crash"),
text = UiText.Simple("Shows alert dialog with stacktrace after app crashed\n(it will be not shown if you perform crash manually)") text = UiText.Simple("Shows alert dialog with stacktrace after app crashed\n(it will be not shown if you perform crash manually)")
) )
val debugLongPollBackground = SettingsItem.Switch(
key = SettingsKeys.KEY_FEATURES_LONG_POLL_IN_BACKGROUND,
defaultValue = SettingsKeys.DEFAULT_VALUE_FEATURES_LONG_POLL_IN_BACKGROUND,
title = UiText.Resource(UiR.string.settings_features_long_poll_in_background_title),
text = UiText.Resource(UiR.string.settings_features_long_poll_in_background_summary)
)
val debugUseBlur = SettingsItem.Switch(
key = SettingsKeys.KEY_APPEARANCE_USE_BLUR,
defaultValue = SettingsKeys.DEFAULT_VALUE_KEY_APPEARANCE_USE_BLUR,
title = UiText.Simple("[WIP] Use blur"),
text = UiText.Simple("Adds blur wherever possible\nWorks on android 12 and newer"),
)
val debugShowEmojiButton = SettingsItem.Switch(
key = SettingsKeys.KEY_SHOW_EMOJI_BUTTON,
title = UiText.Simple("Show emoji button"),
text = UiText.Simple("Show emoji button in chat panel"),
defaultValue = SettingsKeys.DEFAULT_VALUE_KEY_SHOW_EMOJI_BUTTON
)
val debugShowTimeInActionMessages = SettingsItem.Switch(
key = SettingsKeys.KEY_APPEARANCE_SHOW_TIME_IN_ACTION_MESSAGES,
defaultValue = SettingsKeys.DEFAULT_VALUE_APPEARANCE_SHOW_TIME_IN_ACTION_MESSAGES,
title = UiText.Simple("Show time in action messages")
)
val debugEnableHaptic = SettingsItem.Switch(
key = SettingsKeys.KEY_DEBUG_ENABLE_HAPTIC,
defaultValue = SettingsKeys.DEFAULT_DEBUG_ENABLE_HAPTIC,
title = UiText.Simple("Enable haptic")
)
val logLevelValues = listOf( val logLevelValues = listOf(
LogLevel.NONE to UiText.Simple("None"), LogLevel.NONE to UiText.Simple("None"),
@@ -440,12 +437,6 @@ class SettingsViewModelImpl(
} }
} }
val debugUseSystemFont = SettingsItem.Switch(
key = SettingsKeys.KEY_DEBUG_USE_SYSTEM_FONT,
defaultValue = SettingsKeys.DEFAULT_DEBUG_USE_SYSTEM_FONT,
title = UiText.Simple("Use system font")
)
val debugHideDebugList = SettingsItem.TitleText( val debugHideDebugList = SettingsItem.TitleText(
key = SettingsKeys.KEY_DEBUG_HIDE_DEBUG_LIST, key = SettingsKeys.KEY_DEBUG_HIDE_DEBUG_LIST,
title = UiText.Simple("Hide debug list") title = UiText.Simple("Hide debug list")
@@ -458,7 +449,8 @@ class SettingsViewModelImpl(
val generalList = listOf( val generalList = listOf(
generalTitle, generalTitle,
generalUseContactNames, generalUseContactNames,
generalEnablePullToRefresh generalShowEmojiButton,
generalEnableHaptic
) )
val appearanceList = listOf( val appearanceList = listOf(
appearanceTitle, appearanceTitle,
@@ -466,6 +458,7 @@ class SettingsViewModelImpl(
appearanceDarkTheme, appearanceDarkTheme,
appearanceUseAmoledDarkTheme, appearanceUseAmoledDarkTheme,
appearanceUseDynamicColors, appearanceUseDynamicColors,
appearanceUseSystemFont,
appearanceLanguage appearanceLanguage
) )
val featuresList = listOf( val featuresList = listOf(
@@ -476,18 +469,18 @@ class SettingsViewModelImpl(
activityTitle, activityTitle,
visibilitySendOnlineStatus, visibilitySendOnlineStatus,
) )
val experimentalList = listOf(
experimentalTitle,
experimentalLongPollBackground,
experimentalShowTimeInActionMessages,
experimentalUseBlur
)
val debugList = mutableListOf<SettingsItem<*>>() val debugList = mutableListOf<SettingsItem<*>>()
listOf( listOf(
debugTitle, debugTitle,
debugPerformCrash, debugPerformCrash,
debugShowCrashAlert, debugShowCrashAlert,
debugLongPollBackground,
debugUseBlur,
debugShowEmojiButton,
debugShowTimeInActionMessages,
debugEnableHaptic,
debugNetworkLogLevel, debugNetworkLogLevel,
debugUseSystemFont
).forEach(debugList::add) ).forEach(debugList::add)
debugList += debugHideDebugList debugList += debugHideDebugList
@@ -499,6 +492,7 @@ class SettingsViewModelImpl(
appearanceList, appearanceList,
featuresList, featuresList,
visibilityList, visibilityList,
experimentalList,
debugList, debugList,
).forEach(settingsList::addAll) ).forEach(settingsList::addAll)
@@ -2,7 +2,7 @@ package dev.meloda.fast.settings.di
import dev.meloda.fast.settings.SettingsViewModel import dev.meloda.fast.settings.SettingsViewModel
import dev.meloda.fast.settings.SettingsViewModelImpl import dev.meloda.fast.settings.SettingsViewModelImpl
import org.koin.androidx.viewmodel.dsl.viewModelOf import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.bind import org.koin.dsl.bind
import org.koin.dsl.module import org.koin.dsl.module
@@ -113,7 +113,7 @@ fun SettingsScreen(
LaunchedEffect(hapticType) { LaunchedEffect(hapticType) {
if (hapticType != null) { if (hapticType != null) {
if (AppSettings.Debug.enableHaptic) { if (AppSettings.General.enableHaptic) {
view.performHapticFeedback(hapticType.getHaptic()) view.performHapticFeedback(hapticType.getHaptic())
} }
onHapticPerformed() onHapticPerformed()