mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-11 20:53:39 +00:00
New app theming (#1010)
* feat: start new app theming feature * feat: add some theming colours * refactor: start refactoring themes and colours to use dynamic attributes * feat: adding more colours and switching over default colours to be theme based instead of hard-coded or day/night specific * refactor: take a look at ocean light and logo colour * feat: global search colours for light and dark ocean * feat: more styling * feat: adding themes to conversation activity and refactoring the base theme to apply over the top of the activity's theme so it retains noActionBar etc * feat: add dynamic accent color * docs: add todo for changing how accent colour is applied * feat: update new theming to use override primary style so that the regular colorAccent attribute can be used in existing layouts * feat: coordinating styles across layouts, fixing up pinned icons and naming for conversation list items * refactor: re-styling layouts to match new themes and attributes. Need to figure out action mode close button * refactor: remove @color/text and replace with ?android:textColorPrimary to override in themes * refactor: add context theme wrapper to bottom sheet dialog that references accent color * fix: input bar bug fix and preference activity themes * refactor: new settings menu options * fix: crash for PNModeActivity.kt refactor: move ordering in seed dialog to match designs, copy changes to match new settings menu * feat: add new appearance settings activity * refactor: title and VM changes * fix: correct override * feat: add theme appearance screen UI features and start VM implementation. re-add legacy theme utils to get default for migration * fix: compile errors and missing themes from emoji features * refactor: remove background shape alteration and old bottom sheet styles, re-add the theme mode attr * feat: appearance screen wired up, just need to refresh theme * feat: add theme state recreation and fix match system settings option * refactor: add bottom margin * feat: explore custom preference category * feat: add the customized session theme for CorrectedPreferenceFragment * feat: replace AppProtectionPreferenceFragment to extend ListSummaryPreferenceFragment * refactor: change drawable style and remove explicit dividers * refactor: remove divider in CorrectedPreferenceFragment * feat: add theme state check on resume, might be jarring currently * feat: add preference divider elements for settings menu * refactor: settings menu redesigns * refactor: change led preference to integer and refactor TextSecurePreferences.kt * feat: add scroll parcel to save/restore hierarchy on restart with appearance changes * feat: add the conversations blocked contacts and refactor preference order and copy * feat: add blocked contacts activity, basic layout and vm * feat: add unblock DB functions and storage protocol, start working on the DB query state flow, might have to just implement recipient on modified listener * feat: add blocked contacts and notif recipient listeners * feat: add recipient db reader * feat: add blocked contact interactions and fix a theming crash for notifications * feat: introduce better equals and hashcode implementations to recipient, replace home diff util content check with hashcode-based comparison * feat: add settings menu vectors * fix: preview compile error * refactor: migrating settings menu to new designs * feat: help menu * refactor: simplify link opening * refactor: remove space * feat: refactor preferences and start theming for light mode options * refactor: fixing dark and light modes with dialogs * refactor: popup dialogs use proper themes now * refactor: alert dialogs and media edit fragments use attribute references * refactor: use input bar button attribute instead color control normal in vector tint * refactor: transparency, dialog fixes, notification fix * refactor: attrs and styles for buttons * fix: use prominent button color on the outline button's border * fix: fix the trash * refactor: remove the appearance * refactor: avatar placeholder generation, chips and element border styles * refactor: use colors instead of style references * refactor: theming changes to match designs and feedback * refactor: the titles are bold and the categories are tertiary coloured now * fix: appearance settings match preferences, search bottom bar uses themed attributes * refactor: increase setting button height * Update clear all data dialog * Update seed dialog * refactor: more qa feedback changes * feat: add new TLs and fa-rIR TLs * Update notification content dialog * Fix message requests clear all button text color * feat: re-add screenshot observer * refactor: make send tint accent color * feat: add unread background differences * fix: change unread count indicator * build: upgrade build numbers * Fix message requests popupmenu background color * fix: crash from attr reference in color attribute * build: upgrade build number * fix: message bubbles, thumbnail backgrounds, search bar visibility with input bar, attachment buttons * fix: tertiary text for keyboard page search view * fix: emoji overflow colour differences * fix: reaction pill dialog background is now correct colour * Add style to reactions tab layout * fix: appearance activity reverting primary color at correct time * fix: show call privacy warning every time instead of just once * fix: gradient background(?) and audio autoplay disable * fix: crash in all media containing documents * fix: reaction dialog heading fixes * Add style to reactions tab layout * fix: remove gradient backgrounds * fix: adding new reaction normal text attribute to try correct the tab layout * fix: ocean dark unread/read colours * build; update build number * build: update build number * Fix ocean light theme pin color * Update classic dark unread indicator text color * Reduce group name text size on join community screen * Restore tab indicator color on join community and all media screens * Home adapter rename * Updated the HomeViewModel to cancel old executors when new ones are added (#1) * Updated the HomeViewModel to cancel old executors when new ones are added * Removed a seemingly unneeded update * Explicitly remove observers when the HomeActivity is paused (#2) Co-authored-by: jubb <hjubb@users.noreply.github.com> Co-authored-by: charles <charles@oxen.io> Co-authored-by: Morgan Pretty <mpretty-cyro@users.noreply.github.com>
This commit is contained in:
parent
aecb40cce9
commit
38cc42a162
@ -26,7 +26,7 @@ import network.loki.messenger.R;
|
||||
|
||||
public abstract class BaseActionBarActivity extends AppCompatActivity {
|
||||
private static final String TAG = BaseActionBarActivity.class.getSimpleName();
|
||||
private ThemeState currentThemeState;
|
||||
public ThemeState currentThemeState;
|
||||
|
||||
private TextSecurePreferences getPreferences() {
|
||||
ApplicationContext appContext = (ApplicationContext) getApplicationContext();
|
||||
|
@ -0,0 +1,8 @@
|
||||
package org.thoughtcrime.securesms.home
|
||||
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
|
||||
interface ConversationClickListener {
|
||||
fun onConversationClick(thread: ThreadRecord)
|
||||
fun onLongConversationClick(thread: ThreadRecord)
|
||||
}
|
@ -93,8 +93,8 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
private val publicKey: String
|
||||
get() = textSecurePreferences.getLocalNumber()!!
|
||||
|
||||
private val homeAdapter: NewHomeAdapter by lazy {
|
||||
NewHomeAdapter(context = this, listener = this)
|
||||
private val homeAdapter: HomeAdapter by lazy {
|
||||
HomeAdapter(context = this, listener = this)
|
||||
}
|
||||
|
||||
private val globalSearchAdapter = GlobalSearchAdapter { model ->
|
||||
@ -172,23 +172,12 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
homeAdapter.glide = glide
|
||||
binding.recyclerView.adapter = homeAdapter
|
||||
binding.globalSearchRecycler.adapter = globalSearchAdapter
|
||||
|
||||
// Set up empty state view
|
||||
binding.createNewPrivateChatButton.setOnClickListener { showNewConversation() }
|
||||
IP2Country.configureIfNeeded(this@HomeActivity)
|
||||
homeViewModel.getObservable(this).observe(this) { newData ->
|
||||
val manager = binding.recyclerView.layoutManager as LinearLayoutManager
|
||||
val firstPos = manager.findFirstCompletelyVisibleItemPosition()
|
||||
val offsetTop = if(firstPos >= 0) {
|
||||
manager.findViewByPosition(firstPos)?.let { view ->
|
||||
manager.getDecoratedTop(view) - manager.getTopDecorationHeight(view)
|
||||
} ?: 0
|
||||
} else 0
|
||||
homeAdapter.data = newData
|
||||
if(firstPos >= 0) { manager.scrollToPositionWithOffset(firstPos, offsetTop) }
|
||||
setupMessageRequestsBanner()
|
||||
updateEmptyState()
|
||||
}
|
||||
homeViewModel.tryUpdateChannel()
|
||||
startObservingUpdates()
|
||||
|
||||
// Set up new conversation button
|
||||
binding.newConversationButton.setOnClickListener { showNewConversation() }
|
||||
// Observe blocked contacts changed events
|
||||
@ -286,7 +275,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
binding.searchToolbar.isVisible = isShown
|
||||
binding.sessionToolbar.isVisible = !isShown
|
||||
binding.recyclerView.isVisible = !isShown
|
||||
binding.emptyStateContainer.isVisible = (binding.recyclerView.adapter as NewHomeAdapter).itemCount == 0 && binding.recyclerView.isVisible
|
||||
binding.emptyStateContainer.isVisible = (binding.recyclerView.adapter as HomeAdapter).itemCount == 0 && binding.recyclerView.isVisible
|
||||
binding.seedReminderView.isVisible = !TextSecurePreferences.getHasViewedSeed(this) && !isShown
|
||||
binding.globalSearchRecycler.isVisible = isShown
|
||||
binding.newConversationButton.isVisible = !isShown
|
||||
@ -335,11 +324,19 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
ConfigurationMessageUtilities.syncConfigurationIfNeeded(this@HomeActivity)
|
||||
}
|
||||
}
|
||||
|
||||
// If the theme hasn't changed then start observing updates again (if it does change then we
|
||||
// will recreate the activity resulting in it responding to changes multiple times)
|
||||
if (currentThemeState == textSecurePreferences.themeState() && !homeViewModel.getObservable(this).hasActiveObservers()) {
|
||||
startObservingUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
ApplicationContext.getInstance(this).messageNotifier.setHomeScreenVisible(false)
|
||||
|
||||
homeViewModel.getObservable(this).removeObservers(this)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
@ -353,6 +350,22 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
||||
// endregion
|
||||
|
||||
// region Updating
|
||||
private fun startObservingUpdates() {
|
||||
homeViewModel.getObservable(this).observe(this) { newData ->
|
||||
val manager = binding.recyclerView.layoutManager as LinearLayoutManager
|
||||
val firstPos = manager.findFirstCompletelyVisibleItemPosition()
|
||||
val offsetTop = if(firstPos >= 0) {
|
||||
manager.findViewByPosition(firstPos)?.let { view ->
|
||||
manager.getDecoratedTop(view) - manager.getTopDecorationHeight(view)
|
||||
} ?: 0
|
||||
} else 0
|
||||
homeAdapter.data = newData
|
||||
if(firstPos >= 0) { manager.scrollToPositionWithOffset(firstPos, offsetTop) }
|
||||
setupMessageRequestsBanner()
|
||||
updateEmptyState()
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateEmptyState() {
|
||||
val threadCount = (binding.recyclerView.adapter)!!.itemCount
|
||||
binding.emptyStateContainer.isVisible = threadCount == 0 && binding.recyclerView.isVisible
|
||||
|
@ -1,8 +1,115 @@
|
||||
package org.thoughtcrime.securesms.home
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListUpdateCallback
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.NO_ID
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
|
||||
class HomeAdapter(
|
||||
private val context: Context,
|
||||
private val listener: ConversationClickListener
|
||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>(), ListUpdateCallback {
|
||||
|
||||
companion object {
|
||||
private const val HEADER = 0
|
||||
private const val ITEM = 1
|
||||
}
|
||||
|
||||
var header: View? = null
|
||||
|
||||
private var _data: List<ThreadRecord> = emptyList()
|
||||
var data: List<ThreadRecord>
|
||||
get() = _data.toList()
|
||||
set(newData) {
|
||||
val previousData = _data.toList()
|
||||
val diff = HomeDiffUtil(previousData, newData, context)
|
||||
val diffResult = DiffUtil.calculateDiff(diff)
|
||||
_data = newData
|
||||
diffResult.dispatchUpdatesTo(this as ListUpdateCallback)
|
||||
}
|
||||
|
||||
fun hasHeaderView(): Boolean = header != null
|
||||
|
||||
private val headerCount: Int
|
||||
get() = if (header == null) 0 else 1
|
||||
|
||||
override fun onInserted(position: Int, count: Int) {
|
||||
notifyItemRangeInserted(position + headerCount, count)
|
||||
}
|
||||
|
||||
override fun onRemoved(position: Int, count: Int) {
|
||||
notifyItemRangeRemoved(position + headerCount, count)
|
||||
}
|
||||
|
||||
override fun onMoved(fromPosition: Int, toPosition: Int) {
|
||||
notifyItemMoved(fromPosition + headerCount, toPosition + headerCount)
|
||||
}
|
||||
|
||||
override fun onChanged(position: Int, count: Int, payload: Any?) {
|
||||
notifyItemRangeChanged(position + headerCount, count, payload)
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
if (hasHeaderView() && position == 0) return NO_ID
|
||||
val offsetPosition = if (hasHeaderView()) position-1 else position
|
||||
return _data[offsetPosition].threadId
|
||||
}
|
||||
|
||||
lateinit var glide: GlideRequests
|
||||
var typingThreadIDs = setOf<Long>()
|
||||
set(value) {
|
||||
field = value
|
||||
// TODO: replace this with a diffed update or a partial change set with payloads
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
|
||||
when (viewType) {
|
||||
HEADER -> {
|
||||
HeaderFooterViewHolder(header!!)
|
||||
}
|
||||
ITEM -> {
|
||||
val view = ConversationView(context)
|
||||
view.setOnClickListener { view.thread?.let { listener.onConversationClick(it) } }
|
||||
view.setOnLongClickListener {
|
||||
view.thread?.let { listener.onLongConversationClick(it) }
|
||||
true
|
||||
}
|
||||
ViewHolder(view)
|
||||
}
|
||||
else -> throw Exception("viewType $viewType isn't valid")
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is ViewHolder) {
|
||||
val offset = if (hasHeaderView()) position - 1 else position
|
||||
val thread = data[offset]
|
||||
val isTyping = typingThreadIDs.contains(thread.threadId)
|
||||
holder.view.bind(thread, isTyping, glide)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is ViewHolder) {
|
||||
holder.view.recycle()
|
||||
} else {
|
||||
super.onViewRecycled(holder)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int =
|
||||
if (hasHeaderView() && position == 0) HEADER
|
||||
else ITEM
|
||||
|
||||
override fun getItemCount(): Int = data.size + if (hasHeaderView()) 1 else 0
|
||||
|
||||
class ViewHolder(val view: ConversationView) : RecyclerView.ViewHolder(view)
|
||||
|
||||
class HeaderFooterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
|
||||
|
||||
interface ConversationClickListener {
|
||||
fun onConversationClick(thread: ThreadRecord)
|
||||
fun onLongConversationClick(thread: ThreadRecord)
|
||||
}
|
@ -7,23 +7,22 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.cash.copper.flow.observeQuery
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.plus
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.thoughtcrime.securesms.database.DatabaseContentProviders
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import java.lang.ref.WeakReference
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class HomeViewModel @Inject constructor(private val threadDb: ThreadDatabase): ViewModel() {
|
||||
|
||||
private val executor = viewModelScope + SupervisorJob()
|
||||
private var lastContext: WeakReference<Context>? = null
|
||||
private var updateJobs: MutableList<Job> = mutableListOf()
|
||||
|
||||
private val _conversations = MutableLiveData<List<ThreadRecord>>()
|
||||
val conversations: LiveData<List<ThreadRecord>> = _conversations
|
||||
@ -33,12 +32,23 @@ class HomeViewModel @Inject constructor(private val threadDb: ThreadDatabase): V
|
||||
fun tryUpdateChannel() = listUpdateChannel.trySend(Unit)
|
||||
|
||||
fun getObservable(context: Context): LiveData<List<ThreadRecord>> {
|
||||
// If the context has changed (eg. the activity gets recreated) then
|
||||
// we need to cancel the old executors and recreate them to prevent
|
||||
// the app from triggering extra updates when data changes
|
||||
if (context != lastContext?.get()) {
|
||||
lastContext = WeakReference(context)
|
||||
updateJobs.forEach { it.cancel() }
|
||||
updateJobs.clear()
|
||||
|
||||
updateJobs.add(
|
||||
executor.launch(Dispatchers.IO) {
|
||||
context.contentResolver
|
||||
.observeQuery(DatabaseContentProviders.ConversationList.CONTENT_URI)
|
||||
.onEach { listUpdateChannel.trySend(Unit) }
|
||||
.collect()
|
||||
}
|
||||
)
|
||||
updateJobs.add(
|
||||
executor.launch(Dispatchers.IO) {
|
||||
for (update in listUpdateChannel) {
|
||||
threadDb.approvedConversationList.use { openCursor ->
|
||||
@ -53,6 +63,8 @@ class HomeViewModel @Inject constructor(private val threadDb: ThreadDatabase): V
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
return conversations
|
||||
}
|
||||
|
||||
|
@ -1,114 +0,0 @@
|
||||
package org.thoughtcrime.securesms.home
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.ListUpdateCallback
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.recyclerview.widget.RecyclerView.NO_ID
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests
|
||||
|
||||
class NewHomeAdapter(private val context: Context, private val listener: ConversationClickListener):
|
||||
RecyclerView.Adapter<RecyclerView.ViewHolder>(),
|
||||
ListUpdateCallback {
|
||||
|
||||
companion object {
|
||||
private const val HEADER = 0
|
||||
private const val ITEM = 1
|
||||
}
|
||||
|
||||
var header: View? = null
|
||||
|
||||
private var _data: List<ThreadRecord> = emptyList()
|
||||
var data: List<ThreadRecord>
|
||||
get() = _data.toList()
|
||||
set(newData) {
|
||||
val previousData = _data.toList()
|
||||
val diff = HomeDiffUtil(previousData, newData, context)
|
||||
val diffResult = DiffUtil.calculateDiff(diff)
|
||||
_data = newData
|
||||
diffResult.dispatchUpdatesTo(this as ListUpdateCallback)
|
||||
}
|
||||
|
||||
fun hasHeaderView(): Boolean = header != null
|
||||
|
||||
private val headerCount: Int
|
||||
get() = if (header == null) 0 else 1
|
||||
|
||||
override fun onInserted(position: Int, count: Int) {
|
||||
notifyItemRangeInserted(position + headerCount, count)
|
||||
}
|
||||
|
||||
override fun onRemoved(position: Int, count: Int) {
|
||||
notifyItemRangeRemoved(position + headerCount, count)
|
||||
}
|
||||
|
||||
override fun onMoved(fromPosition: Int, toPosition: Int) {
|
||||
notifyItemMoved(fromPosition + headerCount, toPosition + headerCount)
|
||||
}
|
||||
|
||||
override fun onChanged(position: Int, count: Int, payload: Any?) {
|
||||
notifyItemRangeChanged(position + headerCount, count, payload)
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
if (hasHeaderView() && position == 0) return NO_ID
|
||||
val offsetPosition = if (hasHeaderView()) position-1 else position
|
||||
return _data[offsetPosition].threadId
|
||||
}
|
||||
|
||||
lateinit var glide: GlideRequests
|
||||
var typingThreadIDs = setOf<Long>()
|
||||
set(value) {
|
||||
field = value
|
||||
// TODO: replace this with a diffed update or a partial change set with payloads
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
|
||||
when (viewType) {
|
||||
HEADER -> {
|
||||
HeaderFooterViewHolder(header!!)
|
||||
}
|
||||
ITEM -> {
|
||||
val view = ConversationView(context)
|
||||
view.setOnClickListener { view.thread?.let { listener.onConversationClick(it) } }
|
||||
view.setOnLongClickListener {
|
||||
view.thread?.let { listener.onLongConversationClick(it) }
|
||||
true
|
||||
}
|
||||
ViewHolder(view)
|
||||
}
|
||||
else -> throw Exception("viewType $viewType isn't valid")
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is ViewHolder) {
|
||||
val offset = if (hasHeaderView()) position - 1 else position
|
||||
val thread = data[offset]
|
||||
val isTyping = typingThreadIDs.contains(thread.threadId)
|
||||
holder.view.bind(thread, isTyping, glide)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
|
||||
if (holder is ViewHolder) {
|
||||
holder.view.recycle()
|
||||
} else {
|
||||
super.onViewRecycled(holder)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int =
|
||||
if (hasHeaderView() && position == 0) HEADER
|
||||
else ITEM
|
||||
|
||||
override fun getItemCount(): Int = data.size + if (hasHeaderView()) 1 else 0
|
||||
|
||||
class ViewHolder(val view: ConversationView) : RecyclerView.ViewHolder(view)
|
||||
|
||||
class HeaderFooterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
|
||||
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="4dp"
|
||||
android:ellipsize="end"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
|
||||
app:chipStrokeWidth="1dp"
|
||||
app:chipStrokeColor="?elementBorderColor"
|
||||
app:chipBackgroundColor="?dialog_background_color"
|
||||
|
@ -9,7 +9,7 @@
|
||||
android:paddingBottom="@dimen/react_with_any_emoji_bottom_sheet_dialog_fragment_tabs_height">
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
style="@style/Widget.Session.TabLayout"
|
||||
style="@style/Widget.Session.TabLayout.Reactions"
|
||||
android:id="@+id/emoji_tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/react_with_any_emoji_bottom_sheet_dialog_fragment_tabs_height"
|
||||
|
@ -70,6 +70,10 @@
|
||||
<item name="tabTextAppearance">@style/TextAppearance.Session.Tab</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Session.TabLayout.Reactions">
|
||||
<item name="tabIndicatorColor">@color/transparent</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.Session.Tab" parent="TextAppearance.Design.Tab">
|
||||
<item name="android:textSize">@dimen/medium_font_size</item>
|
||||
<item name="textAllCaps">false</item>
|
||||
|
@ -354,7 +354,8 @@
|
||||
<item name="conversation_unread_background_color">@color/classic_dark_2</item>
|
||||
<item name="conversation_pinned_icon_color">@color/classic_dark_4</item>
|
||||
<item name="unreadIndicatorBackgroundColor">@color/classic_dark_3</item>
|
||||
<item name="unreadIndicatorTextColor">@color/classic_dark_6</item>
|
||||
<item name="unreadIndicatorTextColor">@color/classic_dark_0</item>
|
||||
|
||||
<!-- New conversation button -->
|
||||
<item name="conversation_color_non_main">@color/classic_dark_2</item>
|
||||
<item name="conversation_shadow_non_main">@color/transparent_black_30</item>
|
||||
@ -631,7 +632,7 @@
|
||||
<item name="conversation_unread_count_indicator_background">?colorAccent</item>
|
||||
<item name="conversation_pinned_background_color">?colorCellBackground</item>
|
||||
<item name="conversation_unread_background_color">@color/ocean_light_5</item>
|
||||
<item name="conversation_pinned_icon_color">?colorPrimary</item>
|
||||
<item name="conversation_pinned_icon_color">?android:textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user