ability to enable/disable pull to refresh
This commit is contained in:
@@ -159,7 +159,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
selectedColorScheme = theme.selectedColorScheme,
|
selectedColorScheme = theme.selectedColorScheme,
|
||||||
usingAmoledBackground = theme.usingAmoledBackground,
|
usingAmoledBackground = theme.usingAmoledBackground,
|
||||||
usingBlur = theme.usingBlur,
|
usingBlur = theme.usingBlur,
|
||||||
multiline = theme.multiline,
|
isMultiline = theme.isMultiline,
|
||||||
isDeviceCompact = isDeviceCompact
|
isDeviceCompact = isDeviceCompact
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -85,4 +85,11 @@ object SettingsController {
|
|||||||
var deviceId: String
|
var deviceId: String
|
||||||
get() = get("device_id", "")
|
get() = get("device_id", "")
|
||||||
set(value) = put("device_id", value)
|
set(value) = put("device_id", value)
|
||||||
|
|
||||||
|
var enablePullToRefresh: Boolean
|
||||||
|
get() = get(
|
||||||
|
SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH,
|
||||||
|
SettingsKeys.DEFAULT_VALUE_ENABLE_PULL_TO_REFRESH
|
||||||
|
)
|
||||||
|
set(value) = put(SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH, value)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ object SettingsKeys {
|
|||||||
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 = "general_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 DEFAULT_VALUE_ENABLE_PULL_TO_REFRESH = false
|
||||||
const val KEY_SHOW_EMOJI_BUTTON = "general_show_emoji_button"
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ interface UserSettings {
|
|||||||
val debugSettingsEnabled: StateFlow<Boolean>
|
val debugSettingsEnabled: StateFlow<Boolean>
|
||||||
val useContactNames: StateFlow<Boolean>
|
val useContactNames: StateFlow<Boolean>
|
||||||
val language: StateFlow<String>
|
val language: StateFlow<String>
|
||||||
|
val enablePullToRefresh: StateFlow<Boolean>
|
||||||
|
|
||||||
fun updateUsingDarkTheme()
|
fun updateUsingDarkTheme()
|
||||||
fun useDarkThemeChanged(use: Boolean)
|
fun useDarkThemeChanged(use: Boolean)
|
||||||
@@ -30,6 +31,7 @@ interface UserSettings {
|
|||||||
fun enableDebugSettings(enable: Boolean)
|
fun enableDebugSettings(enable: Boolean)
|
||||||
fun onUseContactNamesChanged(use: Boolean)
|
fun onUseContactNamesChanged(use: Boolean)
|
||||||
fun onLanguageChanged(newLanguage: String)
|
fun onLanguageChanged(newLanguage: String)
|
||||||
|
fun onEnablePullToRefreshChanged(enable: Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserSettingsImpl(
|
class UserSettingsImpl(
|
||||||
@@ -44,7 +46,7 @@ class UserSettingsImpl(
|
|||||||
selectedColorScheme = selectedColorScheme(),
|
selectedColorScheme = selectedColorScheme(),
|
||||||
usingAmoledBackground = isUsingAmoledBackground(),
|
usingAmoledBackground = isUsingAmoledBackground(),
|
||||||
usingBlur = isUsingBlur(),
|
usingBlur = isUsingBlur(),
|
||||||
multiline = isMultiline(),
|
isMultiline = isMultiline(),
|
||||||
isDeviceCompact = false
|
isDeviceCompact = false
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -75,6 +77,8 @@ class UserSettingsImpl(
|
|||||||
|
|
||||||
override val language = MutableStateFlow("")
|
override val language = MutableStateFlow("")
|
||||||
|
|
||||||
|
override val enablePullToRefresh = MutableStateFlow(SettingsController.enablePullToRefresh)
|
||||||
|
|
||||||
override fun updateUsingDarkTheme() {
|
override fun updateUsingDarkTheme() {
|
||||||
useDarkThemeChanged(
|
useDarkThemeChanged(
|
||||||
isUsingDarkMode(
|
isUsingDarkMode(
|
||||||
@@ -105,7 +109,7 @@ class UserSettingsImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun useMultiline(use: Boolean) {
|
override fun useMultiline(use: Boolean) {
|
||||||
theme.value = theme.value.copy(multiline = use)
|
theme.value = theme.value.copy(isMultiline = use)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setLongPollStateToApply(newState: LongPollState) {
|
override fun setLongPollStateToApply(newState: LongPollState) {
|
||||||
@@ -133,4 +137,8 @@ class UserSettingsImpl(
|
|||||||
override fun onLanguageChanged(newLanguage: String) {
|
override fun onLanguageChanged(newLanguage: String) {
|
||||||
language.update { newLanguage }
|
language.update { newLanguage }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onEnablePullToRefreshChanged(enable: Boolean) {
|
||||||
|
enablePullToRefresh.update { enable }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ data class ThemeConfig(
|
|||||||
val selectedColorScheme: Int,
|
val selectedColorScheme: Int,
|
||||||
val usingAmoledBackground: Boolean,
|
val usingAmoledBackground: Boolean,
|
||||||
val usingBlur: Boolean,
|
val usingBlur: Boolean,
|
||||||
val multiline: Boolean,
|
val isMultiline: Boolean,
|
||||||
val isDeviceCompact: Boolean
|
val isDeviceCompact: Boolean
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ val LocalTheme = compositionLocalOf {
|
|||||||
selectedColorScheme = 0,
|
selectedColorScheme = 0,
|
||||||
usingAmoledBackground = false,
|
usingAmoledBackground = false,
|
||||||
usingBlur = false,
|
usingBlur = false,
|
||||||
multiline = false,
|
isMultiline = false,
|
||||||
isDeviceCompact = false
|
isDeviceCompact = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,4 +262,5 @@
|
|||||||
<string name="warning_confirmation">Confirmation</string>
|
<string name="warning_confirmation">Confirmation</string>
|
||||||
<string name="captcha_exit_warning">Are you sure? Captcha process will be cancelled</string>
|
<string name="captcha_exit_warning">Are you sure? Captcha process will be cancelled</string>
|
||||||
<string name="validation_exit_warning">Are you sure? Validation process will be cancelled</string>
|
<string name="validation_exit_warning">Are you sure? Validation process will be cancelled</string>
|
||||||
|
<string name="settings_general_enable_pull_to_refresh_title">Enable pull to refresh</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
+16
-10
@@ -54,7 +54,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
@@ -65,6 +64,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import com.meloda.app.fast.chatmaterials.ChatMaterialsViewModel
|
import com.meloda.app.fast.chatmaterials.ChatMaterialsViewModel
|
||||||
import com.meloda.app.fast.chatmaterials.ChatMaterialsViewModelImpl
|
import com.meloda.app.fast.chatmaterials.ChatMaterialsViewModelImpl
|
||||||
import com.meloda.app.fast.chatmaterials.model.ChatMaterialsScreenState
|
import com.meloda.app.fast.chatmaterials.model.ChatMaterialsScreenState
|
||||||
|
import com.meloda.app.fast.datastore.UserSettings
|
||||||
import com.meloda.app.fast.ui.R
|
import com.meloda.app.fast.ui.R
|
||||||
import com.meloda.app.fast.ui.theme.LocalTheme
|
import com.meloda.app.fast.ui.theme.LocalTheme
|
||||||
import dev.chrisbanes.haze.HazeState
|
import dev.chrisbanes.haze.HazeState
|
||||||
@@ -73,16 +73,22 @@ import dev.chrisbanes.haze.hazeChild
|
|||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import dev.chrisbanes.haze.materials.HazeMaterials
|
import dev.chrisbanes.haze.materials.HazeMaterials
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChatMaterialsRoute(
|
fun ChatMaterialsRoute(
|
||||||
onBack: () -> Unit,
|
onBack: () -> 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,
|
||||||
@@ -97,7 +103,8 @@ fun ChatMaterialsRoute(
|
|||||||
)
|
)
|
||||||
@Composable
|
@Composable
|
||||||
fun ChatMaterialsScreen(
|
fun ChatMaterialsScreen(
|
||||||
screenState: ChatMaterialsScreenState,
|
screenState: ChatMaterialsScreenState = ChatMaterialsScreenState.EMPTY,
|
||||||
|
enablePullToRefresh: Boolean = false,
|
||||||
onBack: () -> Unit = {},
|
onBack: () -> Unit = {},
|
||||||
onTypeChanged: (String) -> Unit = {},
|
onTypeChanged: (String) -> Unit = {},
|
||||||
onRefreshDropdownItemClicked: () -> Unit = {},
|
onRefreshDropdownItemClicked: () -> Unit = {},
|
||||||
@@ -168,12 +175,6 @@ fun ChatMaterialsScreen(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val pullToRefreshAlpha by animateFloatAsState(
|
|
||||||
targetValue = if (!canScrollBackward) 1f else 0f,
|
|
||||||
label = "pullToRefreshAlpha",
|
|
||||||
animationSpec = tween(durationMillis = 50)
|
|
||||||
)
|
|
||||||
|
|
||||||
val pullToRefreshState = rememberPullToRefreshState()
|
val pullToRefreshState = rememberPullToRefreshState()
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
@@ -286,7 +287,11 @@ fun ChatMaterialsScreen(
|
|||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.padding(start = padding.calculateStartPadding(LayoutDirection.Ltr))
|
.padding(start = padding.calculateStartPadding(LayoutDirection.Ltr))
|
||||||
.padding(end = padding.calculateEndPadding(LayoutDirection.Ltr))
|
.padding(end = padding.calculateEndPadding(LayoutDirection.Ltr))
|
||||||
.nestedScroll(pullToRefreshState.nestedScrollConnection)
|
.then(
|
||||||
|
if (enablePullToRefresh) {
|
||||||
|
Modifier.nestedScroll(pullToRefreshState.nestedScrollConnection)
|
||||||
|
} else Modifier
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
if (checkedTypeIndex in listOf(0, 1)) {
|
if (checkedTypeIndex in listOf(0, 1)) {
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
@@ -350,6 +355,7 @@ fun ChatMaterialsScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enablePullToRefresh) {
|
||||||
if (pullToRefreshState.isRefreshing) {
|
if (pullToRefreshState.isRefreshing) {
|
||||||
LaunchedEffect(true) {
|
LaunchedEffect(true) {
|
||||||
onRefresh()
|
onRefresh()
|
||||||
@@ -365,7 +371,6 @@ fun ChatMaterialsScreen(
|
|||||||
PullToRefreshContainer(
|
PullToRefreshContainer(
|
||||||
state = pullToRefreshState,
|
state = pullToRefreshState,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.alpha(pullToRefreshAlpha)
|
|
||||||
.align(Alignment.TopCenter)
|
.align(Alignment.TopCenter)
|
||||||
.padding(top = padding.calculateTopPadding()),
|
.padding(top = padding.calculateTopPadding()),
|
||||||
contentColor = MaterialTheme.colorScheme.primary
|
contentColor = MaterialTheme.colorScheme.primary
|
||||||
@@ -373,3 +378,4 @@ fun ChatMaterialsScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
+16
-10
@@ -51,7 +51,6 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.ui.draw.rotate
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -72,6 +71,7 @@ import com.meloda.app.fast.conversations.ConversationsViewModelImpl
|
|||||||
import com.meloda.app.fast.conversations.model.ConversationOption
|
import com.meloda.app.fast.conversations.model.ConversationOption
|
||||||
import com.meloda.app.fast.conversations.model.ConversationsScreenState
|
import com.meloda.app.fast.conversations.model.ConversationsScreenState
|
||||||
import com.meloda.app.fast.conversations.model.UiConversation
|
import com.meloda.app.fast.conversations.model.UiConversation
|
||||||
|
import com.meloda.app.fast.datastore.UserSettings
|
||||||
import com.meloda.app.fast.model.BaseError
|
import com.meloda.app.fast.model.BaseError
|
||||||
import com.meloda.app.fast.ui.components.ErrorView
|
import com.meloda.app.fast.ui.components.ErrorView
|
||||||
import com.meloda.app.fast.ui.components.FullScreenLoader
|
import com.meloda.app.fast.ui.components.FullScreenLoader
|
||||||
@@ -86,6 +86,7 @@ import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
|||||||
import dev.chrisbanes.haze.materials.HazeMaterials
|
import dev.chrisbanes.haze.materials.HazeMaterials
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
import org.koin.compose.koinInject
|
||||||
import com.meloda.app.fast.ui.R as UiR
|
import com.meloda.app.fast.ui.R as UiR
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -96,6 +97,10 @@ fun ConversationsRoute(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
val userSettings: UserSettings = koinInject()
|
||||||
|
|
||||||
|
val enablePullToRefresh by userSettings.enablePullToRefresh.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
|
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
|
||||||
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
|
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
|
||||||
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
|
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
|
||||||
@@ -115,6 +120,7 @@ fun ConversationsRoute(
|
|||||||
screenState = screenState,
|
screenState = screenState,
|
||||||
baseError = baseError,
|
baseError = baseError,
|
||||||
canPaginate = canPaginate,
|
canPaginate = canPaginate,
|
||||||
|
enablePullToRefresh = enablePullToRefresh,
|
||||||
onSessionExpiredLogOutButtonClicked = { onError(BaseError.SessionExpired) },
|
onSessionExpiredLogOutButtonClicked = { onError(BaseError.SessionExpired) },
|
||||||
onConversationItemClicked = { id ->
|
onConversationItemClicked = { id ->
|
||||||
onConversationItemClicked(id)
|
onConversationItemClicked(id)
|
||||||
@@ -143,6 +149,7 @@ fun ConversationsScreen(
|
|||||||
screenState: ConversationsScreenState = ConversationsScreenState.EMPTY,
|
screenState: ConversationsScreenState = ConversationsScreenState.EMPTY,
|
||||||
baseError: BaseError? = null,
|
baseError: BaseError? = null,
|
||||||
canPaginate: Boolean = false,
|
canPaginate: Boolean = false,
|
||||||
|
enablePullToRefresh: Boolean = false,
|
||||||
onSessionExpiredLogOutButtonClicked: () -> Unit,
|
onSessionExpiredLogOutButtonClicked: () -> Unit,
|
||||||
onConversationItemClicked: (conversationId: Int) -> Unit = {},
|
onConversationItemClicked: (conversationId: Int) -> Unit = {},
|
||||||
onConversationItemLongClicked: (conversation: UiConversation) -> Unit = {},
|
onConversationItemLongClicked: (conversation: UiConversation) -> Unit = {},
|
||||||
@@ -155,7 +162,7 @@ fun ConversationsScreen(
|
|||||||
val currentTheme = LocalTheme.current
|
val currentTheme = LocalTheme.current
|
||||||
|
|
||||||
val maxLines by remember(currentTheme) {
|
val maxLines by remember(currentTheme) {
|
||||||
mutableIntStateOf(if (currentTheme.multiline) 2 else 1)
|
mutableIntStateOf(if (currentTheme.isMultiline) 2 else 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
@@ -196,12 +203,6 @@ fun ConversationsScreen(
|
|||||||
animationSpec = tween(durationMillis = 50)
|
animationSpec = tween(durationMillis = 50)
|
||||||
)
|
)
|
||||||
|
|
||||||
val pullToRefreshAlpha by animateFloatAsState(
|
|
||||||
targetValue = if (!listState.canScrollBackward) 1f else 0f,
|
|
||||||
label = "pullToRefreshAlpha",
|
|
||||||
animationSpec = tween(durationMillis = 50)
|
|
||||||
)
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentWindowInsets = WindowInsets.statusBars,
|
contentWindowInsets = WindowInsets.statusBars,
|
||||||
@@ -342,7 +343,11 @@ fun ConversationsScreen(
|
|||||||
.padding(start = padding.calculateStartPadding(LayoutDirection.Ltr))
|
.padding(start = padding.calculateStartPadding(LayoutDirection.Ltr))
|
||||||
.padding(end = padding.calculateEndPadding(LayoutDirection.Ltr))
|
.padding(end = padding.calculateEndPadding(LayoutDirection.Ltr))
|
||||||
.padding(bottom = padding.calculateBottomPadding())
|
.padding(bottom = padding.calculateBottomPadding())
|
||||||
.nestedScroll(pullToRefreshState.nestedScrollConnection)
|
.then(
|
||||||
|
if (enablePullToRefresh) {
|
||||||
|
Modifier.nestedScroll(pullToRefreshState.nestedScrollConnection)
|
||||||
|
} else Modifier
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
ConversationsListComposable(
|
ConversationsListComposable(
|
||||||
onConversationsClick = onConversationItemClicked,
|
onConversationsClick = onConversationItemClicked,
|
||||||
@@ -362,6 +367,7 @@ fun ConversationsScreen(
|
|||||||
padding = padding
|
padding = padding
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (enablePullToRefresh) {
|
||||||
if (pullToRefreshState.isRefreshing) {
|
if (pullToRefreshState.isRefreshing) {
|
||||||
LaunchedEffect(true) {
|
LaunchedEffect(true) {
|
||||||
onRefresh()
|
onRefresh()
|
||||||
@@ -377,7 +383,6 @@ fun ConversationsScreen(
|
|||||||
PullToRefreshContainer(
|
PullToRefreshContainer(
|
||||||
state = pullToRefreshState,
|
state = pullToRefreshState,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.alpha(pullToRefreshAlpha)
|
|
||||||
.align(Alignment.TopCenter)
|
.align(Alignment.TopCenter)
|
||||||
.padding(top = padding.calculateTopPadding()),
|
.padding(top = padding.calculateTopPadding()),
|
||||||
contentColor = MaterialTheme.colorScheme.primary
|
contentColor = MaterialTheme.colorScheme.primary
|
||||||
@@ -387,6 +392,7 @@ fun ConversationsScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: 26.08.2023, Danil Nikolaev: remove usage of viewModel
|
// TODO: 26.08.2023, Danil Nikolaev: remove usage of viewModel
|
||||||
@Composable
|
@Composable
|
||||||
|
|||||||
+24
-14
@@ -39,7 +39,6 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.alpha
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@@ -50,6 +49,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import coil.imageLoader
|
import coil.imageLoader
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
|
import com.meloda.app.fast.datastore.UserSettings
|
||||||
import com.meloda.app.fast.friends.FriendsViewModel
|
import com.meloda.app.fast.friends.FriendsViewModel
|
||||||
import com.meloda.app.fast.friends.FriendsViewModelImpl
|
import com.meloda.app.fast.friends.FriendsViewModelImpl
|
||||||
import com.meloda.app.fast.friends.model.FriendsScreenState
|
import com.meloda.app.fast.friends.model.FriendsScreenState
|
||||||
@@ -66,6 +66,7 @@ import dev.chrisbanes.haze.hazeChild
|
|||||||
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi
|
||||||
import dev.chrisbanes.haze.materials.HazeMaterials
|
import dev.chrisbanes.haze.materials.HazeMaterials
|
||||||
import org.koin.androidx.compose.koinViewModel
|
import org.koin.androidx.compose.koinViewModel
|
||||||
|
import org.koin.compose.koinInject
|
||||||
import com.meloda.app.fast.ui.R as UiR
|
import com.meloda.app.fast.ui.R as UiR
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -75,8 +76,12 @@ fun FriendsRoute(
|
|||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
|
val userSettings: UserSettings = koinInject()
|
||||||
|
|
||||||
|
val enablePullToRefresh by userSettings.enablePullToRefresh.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
|
val screenState by viewModel.screenState.collectAsStateWithLifecycle()
|
||||||
|
val baseError by viewModel.baseError.collectAsStateWithLifecycle()
|
||||||
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
|
val canPaginate by viewModel.canPaginate.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
val imagesToPreload by viewModel.imagesToPreload.collectAsStateWithLifecycle()
|
val imagesToPreload by viewModel.imagesToPreload.collectAsStateWithLifecycle()
|
||||||
@@ -93,6 +98,7 @@ fun FriendsRoute(
|
|||||||
FriendsScreen(
|
FriendsScreen(
|
||||||
screenState = screenState,
|
screenState = screenState,
|
||||||
baseError = baseError,
|
baseError = baseError,
|
||||||
|
enablePullToRefresh = enablePullToRefresh,
|
||||||
canPaginate = canPaginate,
|
canPaginate = canPaginate,
|
||||||
onSessionExpiredLogOutButtonClicked = { onError(BaseError.SessionExpired) },
|
onSessionExpiredLogOutButtonClicked = { onError(BaseError.SessionExpired) },
|
||||||
onPaginationConditionsMet = viewModel::onPaginationConditionsMet,
|
onPaginationConditionsMet = viewModel::onPaginationConditionsMet,
|
||||||
@@ -110,6 +116,7 @@ fun FriendsRoute(
|
|||||||
fun FriendsScreen(
|
fun FriendsScreen(
|
||||||
screenState: FriendsScreenState = FriendsScreenState.EMPTY,
|
screenState: FriendsScreenState = FriendsScreenState.EMPTY,
|
||||||
baseError: BaseError? = null,
|
baseError: BaseError? = null,
|
||||||
|
enablePullToRefresh: Boolean = false,
|
||||||
canPaginate: Boolean = false,
|
canPaginate: Boolean = false,
|
||||||
onSessionExpiredLogOutButtonClicked: () -> Unit = {},
|
onSessionExpiredLogOutButtonClicked: () -> Unit = {},
|
||||||
onPaginationConditionsMet: () -> Unit = {},
|
onPaginationConditionsMet: () -> Unit = {},
|
||||||
@@ -119,7 +126,7 @@ fun FriendsScreen(
|
|||||||
|
|
||||||
val maxLines by remember {
|
val maxLines by remember {
|
||||||
derivedStateOf {
|
derivedStateOf {
|
||||||
if (currentTheme.multiline) 2 else 1
|
if (currentTheme.isMultiline) 2 else 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,12 +148,6 @@ fun FriendsScreen(
|
|||||||
|
|
||||||
val hazeState = LocalHazeState.current
|
val hazeState = LocalHazeState.current
|
||||||
|
|
||||||
val pullToRefreshAlpha by animateFloatAsState(
|
|
||||||
targetValue = if (!listState.canScrollBackward) 1f else 0f,
|
|
||||||
label = "pullToRefreshAlpha",
|
|
||||||
animationSpec = tween(durationMillis = 50)
|
|
||||||
)
|
|
||||||
|
|
||||||
val topBarContainerColorAlpha by animateFloatAsState(
|
val topBarContainerColorAlpha by animateFloatAsState(
|
||||||
targetValue = if (!currentTheme.usingBlur || !listState.canScrollBackward) 1f else 0f,
|
targetValue = if (!currentTheme.usingBlur || !listState.canScrollBackward) 1f else 0f,
|
||||||
label = "toolbarColorAlpha",
|
label = "toolbarColorAlpha",
|
||||||
@@ -173,7 +174,8 @@ fun FriendsScreen(
|
|||||||
mutableIntStateOf(0)
|
mutableIntStateOf(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
val tabItems = listOf(
|
val tabItems = remember {
|
||||||
|
listOf(
|
||||||
TabItem(
|
TabItem(
|
||||||
titleResId = UiR.string.title_friends_all,
|
titleResId = UiR.string.title_friends_all,
|
||||||
unselectedIconResId = null,
|
unselectedIconResId = null,
|
||||||
@@ -185,6 +187,7 @@ fun FriendsScreen(
|
|||||||
selectedIconResId = null
|
selectedIconResId = null
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
@@ -254,8 +257,6 @@ fun FriendsScreen(
|
|||||||
screenState.isLoading && screenState.friends.isEmpty() -> FullScreenLoader()
|
screenState.isLoading && screenState.friends.isEmpty() -> FullScreenLoader()
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val pullToRefreshState = rememberPullToRefreshState()
|
|
||||||
|
|
||||||
val pagerState = rememberPagerState { tabItems.size }
|
val pagerState = rememberPagerState { tabItems.size }
|
||||||
|
|
||||||
LaunchedEffect(selectedTabIndex) {
|
LaunchedEffect(selectedTabIndex) {
|
||||||
@@ -270,6 +271,8 @@ fun FriendsScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val pullToRefreshState = rememberPullToRefreshState()
|
||||||
|
|
||||||
Box(modifier = Modifier.fillMaxSize()) {
|
Box(modifier = Modifier.fillMaxSize()) {
|
||||||
HorizontalPager(
|
HorizontalPager(
|
||||||
state = pagerState,
|
state = pagerState,
|
||||||
@@ -281,7 +284,13 @@ fun FriendsScreen(
|
|||||||
.padding(start = padding.calculateStartPadding(LayoutDirection.Ltr))
|
.padding(start = padding.calculateStartPadding(LayoutDirection.Ltr))
|
||||||
.padding(end = padding.calculateEndPadding(LayoutDirection.Ltr))
|
.padding(end = padding.calculateEndPadding(LayoutDirection.Ltr))
|
||||||
.padding(bottom = padding.calculateBottomPadding())
|
.padding(bottom = padding.calculateBottomPadding())
|
||||||
.nestedScroll(pullToRefreshState.nestedScrollConnection)
|
.then(
|
||||||
|
if (enablePullToRefresh) {
|
||||||
|
Modifier.nestedScroll(
|
||||||
|
pullToRefreshState.nestedScrollConnection
|
||||||
|
)
|
||||||
|
} else Modifier
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
val friendsToDisplay = screenState.friends
|
val friendsToDisplay = screenState.friends
|
||||||
|
|
||||||
@@ -310,6 +319,7 @@ fun FriendsScreen(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enablePullToRefresh) {
|
||||||
if (pullToRefreshState.isRefreshing) {
|
if (pullToRefreshState.isRefreshing) {
|
||||||
LaunchedEffect(true) {
|
LaunchedEffect(true) {
|
||||||
onRefresh()
|
onRefresh()
|
||||||
@@ -326,7 +336,6 @@ fun FriendsScreen(
|
|||||||
state = pullToRefreshState,
|
state = pullToRefreshState,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(top = padding.calculateTopPadding())
|
.padding(top = padding.calculateTopPadding())
|
||||||
.alpha(pullToRefreshAlpha)
|
|
||||||
.align(Alignment.TopCenter),
|
.align(Alignment.TopCenter),
|
||||||
contentColor = MaterialTheme.colorScheme.primary
|
contentColor = MaterialTheme.colorScheme.primary
|
||||||
)
|
)
|
||||||
@@ -337,3 +346,4 @@ fun FriendsScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -210,6 +210,11 @@ class SettingsViewModelImpl(
|
|||||||
val isUsing = newValue as? Boolean ?: false
|
val isUsing = newValue as? Boolean ?: false
|
||||||
userSettings.onUseContactNamesChanged(isUsing)
|
userSettings.onUseContactNamesChanged(isUsing)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH -> {
|
||||||
|
val enable = newValue as? Boolean ?: false
|
||||||
|
userSettings.onEnablePullToRefreshChanged(enable)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,6 +255,11 @@ 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(
|
||||||
|
key = SettingsKeys.KEY_ENABLE_PULL_TO_REFRESH,
|
||||||
|
defaultValue = SettingsKeys.DEFAULT_VALUE_ENABLE_PULL_TO_REFRESH,
|
||||||
|
title = UiText.Resource(UiR.string.settings_general_enable_pull_to_refresh_title)
|
||||||
|
)
|
||||||
|
|
||||||
val appearanceTitle = SettingsItem.Title(
|
val appearanceTitle = SettingsItem.Title(
|
||||||
key = SettingsKeys.KEY_APPEARANCE,
|
key = SettingsKeys.KEY_APPEARANCE,
|
||||||
@@ -381,7 +391,8 @@ class SettingsViewModelImpl(
|
|||||||
)
|
)
|
||||||
val generalList = listOf(
|
val generalList = listOf(
|
||||||
generalTitle,
|
generalTitle,
|
||||||
generalUseContactNames
|
generalUseContactNames,
|
||||||
|
generalEnablePullToRefresh
|
||||||
)
|
)
|
||||||
val appearanceList = listOf(
|
val appearanceList = listOf(
|
||||||
appearanceTitle,
|
appearanceTitle,
|
||||||
|
|||||||
+2
-2
@@ -81,7 +81,7 @@ fun ListItem(
|
|||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
maxLines = if (currentTheme.multiline) Int.MAX_VALUE else 1,
|
maxLines = if (currentTheme.isMultiline) Int.MAX_VALUE else 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ fun ListItem(
|
|||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
maxLines = if (currentTheme.multiline) Int.MAX_VALUE else 1,
|
maxLines = if (currentTheme.isMultiline) Int.MAX_VALUE else 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -65,7 +65,7 @@ fun SwitchItem(
|
|||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
maxLines = if (currentTheme.multiline) Int.MAX_VALUE else 1,
|
maxLines = if (currentTheme.isMultiline) Int.MAX_VALUE else 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -78,7 +78,7 @@ fun SwitchItem(
|
|||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
maxLines = if (currentTheme.multiline) Int.MAX_VALUE else 1,
|
maxLines = if (currentTheme.isMultiline) Int.MAX_VALUE else 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -93,7 +93,7 @@ fun TextFieldItem(
|
|||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
maxLines = if (currentTheme.multiline) Int.MAX_VALUE else 1,
|
maxLines = if (currentTheme.isMultiline) Int.MAX_VALUE else 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ fun TextFieldItem(
|
|||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
maxLines = if (currentTheme.multiline) Int.MAX_VALUE else 1,
|
maxLines = if (currentTheme.isMultiline) Int.MAX_VALUE else 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@ fun TitleItem(
|
|||||||
bottom = 4.dp
|
bottom = 4.dp
|
||||||
)
|
)
|
||||||
.animateContentSize(),
|
.animateContentSize(),
|
||||||
maxLines = if (currentTheme.multiline) Int.MAX_VALUE else 1,
|
maxLines = if (currentTheme.isMultiline) Int.MAX_VALUE else 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -62,7 +62,7 @@ fun TitleTextItem(
|
|||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
maxLines = if (currentTheme.multiline) Int.MAX_VALUE else 1,
|
maxLines = if (currentTheme.isMultiline) Int.MAX_VALUE else 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -75,7 +75,7 @@ fun TitleTextItem(
|
|||||||
Text(
|
Text(
|
||||||
text = text,
|
text = text,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
maxLines = if (currentTheme.multiline) Int.MAX_VALUE else 1,
|
maxLines = if (currentTheme.isMultiline) Int.MAX_VALUE else 1,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user