mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-23 03:05:26 +00:00
Allow users to select a compact tab bar.
This commit is contained in:
committed by
Cody Henthorne
parent
06f19aa6cd
commit
09cf8074aa
@@ -2,10 +2,12 @@ package org.thoughtcrime.securesms.components.settings.app.appearance
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.Navigation
|
||||
import org.signal.core.util.concurrent.observe
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.settings.DSLConfiguration
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsFragment
|
||||
import org.thoughtcrime.securesms.components.settings.DSLSettingsText
|
||||
import org.thoughtcrime.securesms.components.settings.app.appearance.navbar.ChooseNavigationBarStyleFragment
|
||||
import org.thoughtcrime.securesms.components.settings.configure
|
||||
import org.thoughtcrime.securesms.keyvalue.SettingsValues
|
||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
||||
@@ -30,10 +32,25 @@ class AppearanceSettingsFragment : DSLSettingsFragment(R.string.preferences__app
|
||||
viewModel.state.observe(viewLifecycleOwner) { state ->
|
||||
adapter.submitList(getConfiguration(state).toMappingModelList())
|
||||
}
|
||||
|
||||
childFragmentManager.setFragmentResultListener(ChooseNavigationBarStyleFragment.REQUEST_KEY, viewLifecycleOwner) { key, bundle ->
|
||||
if (bundle.getBoolean(key, false)) {
|
||||
viewModel.refreshState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getConfiguration(state: AppearanceSettingsState): DSLConfiguration {
|
||||
return configure {
|
||||
radioListPref(
|
||||
title = DSLSettingsText.from(R.string.preferences__language),
|
||||
listItems = languageLabels,
|
||||
selected = languageValues.indexOf(state.language),
|
||||
onSelected = {
|
||||
viewModel.setLanguage(languageValues[it])
|
||||
}
|
||||
)
|
||||
|
||||
radioListPref(
|
||||
title = DSLSettingsText.from(R.string.preferences__theme),
|
||||
listItems = themeLabels,
|
||||
@@ -59,12 +76,17 @@ class AppearanceSettingsFragment : DSLSettingsFragment(R.string.preferences__app
|
||||
}
|
||||
)
|
||||
|
||||
radioListPref(
|
||||
title = DSLSettingsText.from(R.string.preferences__language),
|
||||
listItems = languageLabels,
|
||||
selected = languageValues.indexOf(state.language),
|
||||
onSelected = {
|
||||
viewModel.setLanguage(languageValues[it])
|
||||
clickPref(
|
||||
title = DSLSettingsText.from(R.string.preferences_navigation_bar_size),
|
||||
summary = DSLSettingsText.from(
|
||||
if (state.isCompactNavigationBar) {
|
||||
R.string.preferences_compact
|
||||
} else {
|
||||
R.string.preferences_normal
|
||||
}
|
||||
),
|
||||
onClick = {
|
||||
ChooseNavigationBarStyleFragment().show(childFragmentManager, null)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ import org.thoughtcrime.securesms.keyvalue.SettingsValues
|
||||
data class AppearanceSettingsState(
|
||||
val theme: SettingsValues.Theme,
|
||||
val messageFontSize: Int,
|
||||
val language: String
|
||||
val language: String,
|
||||
val isCompactNavigationBar: Boolean
|
||||
)
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.appearance
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import io.reactivex.rxjava3.core.Flowable
|
||||
import org.thoughtcrime.securesms.jobs.EmojiSearchIndexDownloadJob
|
||||
import org.thoughtcrime.securesms.keyvalue.SettingsValues.Theme
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.SplashScreenUtil
|
||||
import org.thoughtcrime.securesms.util.livedata.Store
|
||||
import org.thoughtcrime.securesms.util.rx.RxStore
|
||||
|
||||
class AppearanceSettingsViewModel : ViewModel() {
|
||||
private val store: Store<AppearanceSettingsState>
|
||||
private val store = RxStore(getState())
|
||||
val state: Flowable<AppearanceSettingsState> = store.stateFlowable
|
||||
|
||||
init {
|
||||
val initialState = AppearanceSettingsState(
|
||||
SignalStore.settings().theme,
|
||||
SignalStore.settings().messageFontSize,
|
||||
SignalStore.settings().language
|
||||
)
|
||||
|
||||
store = Store(initialState)
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
store.dispose()
|
||||
}
|
||||
|
||||
val state: LiveData<AppearanceSettingsState> = store.stateLiveData
|
||||
fun refreshState() {
|
||||
store.update { getState() }
|
||||
}
|
||||
|
||||
fun setTheme(activity: Activity?, theme: Theme) {
|
||||
store.update { it.copy(theme = theme) }
|
||||
@@ -40,4 +38,13 @@ class AppearanceSettingsViewModel : ViewModel() {
|
||||
store.update { it.copy(messageFontSize = size) }
|
||||
SignalStore.settings().messageFontSize = size
|
||||
}
|
||||
|
||||
private fun getState(): AppearanceSettingsState {
|
||||
return AppearanceSettingsState(
|
||||
SignalStore.settings().theme,
|
||||
SignalStore.settings().messageFontSize,
|
||||
SignalStore.settings().language,
|
||||
SignalStore.settings().useCompactNavigationBar
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package org.thoughtcrime.securesms.components.settings.app.appearance.navbar
|
||||
|
||||
import android.app.Dialog
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.ViewBinderDelegate
|
||||
import org.thoughtcrime.securesms.databinding.ChooseNavigationBarStyleFragmentBinding
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
|
||||
/**
|
||||
* Allows the user to choose between a compact and full-sized navigation bar.
|
||||
*/
|
||||
class ChooseNavigationBarStyleFragment : DialogFragment(R.layout.choose_navigation_bar_style_fragment) {
|
||||
private val binding by ViewBinderDelegate(ChooseNavigationBarStyleFragmentBinding::bind)
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
val dialog = super.onCreateDialog(savedInstanceState)
|
||||
dialog.window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
|
||||
|
||||
return dialog
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
presentToggleState(SignalStore.settings().useCompactNavigationBar)
|
||||
|
||||
binding.toggle.addOnButtonCheckedListener { group, checkedId, isChecked ->
|
||||
if (isChecked) {
|
||||
presentToggleState(checkedId == R.id.compact)
|
||||
}
|
||||
}
|
||||
|
||||
binding.ok.setOnClickListener {
|
||||
val isCompact = binding.toggle.checkedButtonId == R.id.compact
|
||||
SignalStore.settings().useCompactNavigationBar = isCompact
|
||||
dismissAllowingStateLoss()
|
||||
setFragmentResult(REQUEST_KEY, bundleOf(REQUEST_KEY to true))
|
||||
}
|
||||
}
|
||||
|
||||
private fun presentToggleState(isCompact: Boolean) {
|
||||
binding.toggle.check(if (isCompact) R.id.compact else R.id.normal)
|
||||
binding.image.setImageResource(PreviewImages.getImageResourceId(isCompact))
|
||||
binding.normal.setIconResource(if (isCompact) 0 else R.drawable.ic_check_20)
|
||||
binding.compact.setIconResource(if (isCompact) R.drawable.ic_check_20 else 0)
|
||||
}
|
||||
|
||||
private sealed class PreviewImages(
|
||||
@DrawableRes private val compact: Int,
|
||||
@DrawableRes private val normal: Int
|
||||
) {
|
||||
|
||||
@DrawableRes
|
||||
fun getImageResource(isCompact: Boolean): Int {
|
||||
return if (isCompact) compact else normal
|
||||
}
|
||||
|
||||
private object ThreeButtons : PreviewImages(
|
||||
compact = R.drawable.navbar_compact,
|
||||
normal = R.drawable.navbar_normal
|
||||
)
|
||||
|
||||
private object TwoButtons : PreviewImages(
|
||||
compact = R.drawable.navbar_compact_2,
|
||||
normal = R.drawable.navbar_normal_2
|
||||
)
|
||||
|
||||
companion object {
|
||||
@DrawableRes
|
||||
fun getImageResourceId(isCompact: Boolean): Int {
|
||||
return if (FeatureFlags.callsTab()) {
|
||||
ThreeButtons.getImageResource(isCompact)
|
||||
} else {
|
||||
TwoButtons.getImageResource(isCompact)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val REQUEST_KEY = "ChooseNavigationBarStyle"
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.webrtc.CallBandwidthMode;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@@ -71,6 +70,7 @@ public final class SettingsValues extends SignalStoreValues {
|
||||
private static final String SENT_MEDIA_QUALITY = "settings.sentMediaQuality";
|
||||
private static final String CENSORSHIP_CIRCUMVENTION_ENABLED = "settings.censorshipCircumventionEnabled";
|
||||
private static final String KEEP_MUTED_CHATS_ARCHIVED = "settings.keepMutedChatsArchived";
|
||||
private static final String USE_COMPACT_NAVIGATION_BAR = "settings.useCompactNavigationBar";
|
||||
|
||||
private final SingleLiveEvent<String> onConfigurationSettingChanged = new SingleLiveEvent<>();
|
||||
|
||||
@@ -115,7 +115,8 @@ public final class SettingsValues extends SignalStoreValues {
|
||||
NOTIFY_WHEN_CONTACT_JOINS_SIGNAL,
|
||||
UNIVERSAL_EXPIRE_TIMER,
|
||||
SENT_MEDIA_QUALITY,
|
||||
KEEP_MUTED_CHATS_ARCHIVED);
|
||||
KEEP_MUTED_CHATS_ARCHIVED,
|
||||
USE_COMPACT_NAVIGATION_BAR);
|
||||
}
|
||||
|
||||
public @NonNull LiveData<String> getOnConfigurationSettingChanged() {
|
||||
@@ -455,6 +456,14 @@ public final class SettingsValues extends SignalStoreValues {
|
||||
return getBoolean(KEEP_MUTED_CHATS_ARCHIVED, false);
|
||||
}
|
||||
|
||||
public void setUseCompactNavigationBar(boolean enabled) {
|
||||
putBoolean(USE_COMPACT_NAVIGATION_BAR, enabled);
|
||||
}
|
||||
|
||||
public boolean getUseCompactNavigationBar() {
|
||||
return getBoolean(USE_COMPACT_NAVIGATION_BAR, false);
|
||||
}
|
||||
|
||||
private @Nullable Uri getUri(@NonNull String key) {
|
||||
String uri = getString(key, "");
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.animation.ValueAnimator
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.animation.PathInterpolatorCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
@@ -14,9 +15,11 @@ import com.airbnb.lottie.LottieAnimationView
|
||||
import com.airbnb.lottie.LottieProperty
|
||||
import com.airbnb.lottie.model.KeyPath
|
||||
import org.signal.core.util.DimensionUnit
|
||||
import org.signal.core.util.dp
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.ViewBinderDelegate
|
||||
import org.thoughtcrime.securesms.databinding.ConversationListTabsBinding
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.stories.Stories
|
||||
import org.thoughtcrime.securesms.util.FeatureFlags
|
||||
import org.thoughtcrime.securesms.util.visible
|
||||
@@ -32,9 +35,15 @@ class ConversationListTabsFragment : Fragment(R.layout.conversation_list_tabs) {
|
||||
private var shouldBeImmediate = true
|
||||
private var pillAnimator: Animator? = null
|
||||
|
||||
private val largeConstraintSet: ConstraintSet = ConstraintSet()
|
||||
private val smallConstraintSet: ConstraintSet = ConstraintSet()
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
val iconTint = ContextCompat.getColor(requireContext(), R.color.signal_colorOnSecondaryContainer)
|
||||
|
||||
largeConstraintSet.clone(binding.root)
|
||||
smallConstraintSet.clone(requireContext(), R.layout.conversation_list_tabs_small)
|
||||
|
||||
binding.chatsTabIcon.addValueCallback(
|
||||
KeyPath("**"),
|
||||
LottieProperty.COLOR
|
||||
@@ -76,6 +85,14 @@ class ConversationListTabsFragment : Fragment(R.layout.conversation_list_tabs) {
|
||||
}
|
||||
|
||||
private fun updateTabsVisibility() {
|
||||
if (SignalStore.settings().useCompactNavigationBar) {
|
||||
smallConstraintSet.applyTo(binding.root)
|
||||
binding.root.minHeight = 48.dp
|
||||
} else {
|
||||
largeConstraintSet.applyTo(binding.root)
|
||||
binding.root.minHeight = 80.dp
|
||||
}
|
||||
|
||||
listOf(
|
||||
binding.callsPill,
|
||||
binding.callsTabIcon,
|
||||
@@ -98,6 +115,16 @@ class ConversationListTabsFragment : Fragment(R.layout.conversation_list_tabs) {
|
||||
it.visible = Stories.isFeatureEnabled()
|
||||
}
|
||||
|
||||
if (SignalStore.settings().useCompactNavigationBar) {
|
||||
listOf(
|
||||
binding.callsTabLabel,
|
||||
binding.chatsTabLabel,
|
||||
binding.storiesTabLabel
|
||||
).forEach {
|
||||
it.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
update(viewModel.stateSnapshot, true)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user